スプレッドシートのトロールに長い間依存してきた職業にとって、Pythonは特に価値があります。アメリカの銀行であるCitigroupは、研修生のアナリスト向けにPythonのクラッシュコースを導入しました。 -エコノミスト
財務の専門家は、カスタム機能を構築し、ワークフローを自動化するために、ExcelのVBA(Visual Basic for Applications)に長い間アクセスしてきました。近年のGoogleスプレッドシートがスプレッドシートの分野で真剣な競争相手として登場したことで、GoogleAppsScriptは追加の選択肢を提供するようになりました。
ただし、3番目のオプションであるPythonプログラミング言語に注目したいと思います。これは、多くの分野で非常に人気があります。
この記事では、Pythonで達成できることの例をいくつか紹介します。まず、言語自体の概要と、Web開発、機械学習、金融など、さまざまな分野でPythonが非常に人気がある理由について説明します。ほんの数例を挙げると、科学と教育です。後半は、ステップバイステップのチュートリアルで構成されます。
私がこれを書く目的は、Pythonを財務ツールボックスに追加することを検討するのに十分な興味をそそられるように見えるかどうかを判断するのに役立つことです。あなたが飛躍するならば、言語を学ぶために利用できる多くのアプリ、コース、ビデオ、記事、本とブログ投稿があります。作品の最後に、その過程で私を助けてくれたいくつかのリソースをリストアップしました。
私がプログラミングを始めたのは、1980年代半ばにOric1でBASICを学ぶことでした。当時、BASICは最も一般的な初心者の言語でした。 80年代後半から90年代半ばまで私が手を出した他の言語は、パスカルとCでしたが、専門的な立場でそれらを使用したことはなく、プログラミングスキルを必要としたり使用したりすることは期待していませんでした。 90年代後半の私の知る限り、私が金融のキャリアパスに着手することを選択したとき、金融とプログラミングは非常に異なる分野でした。
2012年に早送りし、趣味としてプログラミングを取り戻すことを考えていたので、当時利用可能な言語の調査を開始しました。かなりのことが起こったことが判明し、Pythonに出くわしたとき、次のセクションで概説する多くの理由で夢中になりました。それ以来、私は個人的にも専門的にも、小さなスクリプトから大きなプロジェクトまで、幅広いタスクにPythonを使用してきました。すべてではありませんが、多くの金融専門家の作業台であるスプレッドシートが関係しています。
スプレッドシートとPythonがうまく連携できる例をいくつか示します。
私は、実行だけでなく統合も含めて、M&Aトランザクションのすべての側面に取り組んでいます。最近のケースでは、PMOチームは、進行中の数百のアクティビティを追跡するためのかんばんボードに加えて、12の統合ワークストリームのそれぞれの高レベル計画にウォーターフォール計画とガントチャートを使用して、ハイブリッドプログラムとプロジェクト管理アプローチを決定しました。最初の100日間の計画以降、いつでもオンになります。選択されたかんばんツールであるMeisterTaskには、多くの統計機能とレポート機能がありますが、分析と表示の点で私たちのニーズはそれを超えており、カスタムソリューションが必要でした。これは、Pythonを使用して自動化したワークフローです:
スクリプトの開発には数時間の先行投資が必要でしたが、現在、運営委員会の会議や臨時の分析のためにレポートパックを更新するのに数分かかります。文字通り、適切なフォルダーに移動して1行のコマンドでスクリプトを実行するのに約30秒かかり、次に出力をコピーしてスライドデッキに貼り付けるのに数分かかります。すでに実行開始から約1か月の12のワークストリームで約500のアクティビティ(カード)があり、それらの動きを毎週追跡します。2年間のプログラムのタイムライン内で、数十、最終的には数万のデータポイントを処理していることにすぐに気付きます。ファイルの。自動化がなければ、ここでは非常に面倒な作業について話し合っています。
物事に取り掛かるだけか、自動化を設定して初期ワークロードを追加するかの間の「お金の時間価値」のトレードオフは、財務の一般的なテーマです。このプロセスの最初のステップで、データをCSVファイルとしてエクスポートすることで、同様の決定を行いました。 MeisterTaskは、多くの最新のWebアプリケーションと同様に、Pythonアプリケーションに接続できるAPIを備えていますが、セットアップにかかる時間は、ここでのユースケースの時間節約をはるかに上回ります。
したがって、ご覧のとおり、多くの場合、最適なソリューションは、ワークフローの特定のステップを自動化し、他のステップを手動に保つことです。
もう1つの例は、私が個人的な興味から行ったことですが、Pythonのユーティリティの他の興味深い要素が含まれているため、強調したいと思います。
ここでの結果は、好みや不動産を探す際の経済的制限の観点から、あなた自身の個人的な重みと組み合わせることができます。
これらは、スプレッドシート関連の作業の自動化と機能の追加に焦点を当てた2つの例にすぎませんが、Pythonの機会はほぼ無限です。次のセクションでは、Pythonでのモンテカルロシミュレーションのチュートリアルに進む前に、人気が高まった理由の概要を説明します。
プログラミング言語Pythonは1990年から存在していますが、その人気が爆発的に高まったのは近年になってからです。
これにはいくつかの理由があります。それぞれを順番に見ていきましょう。
高水準プログラミング言語は、コンピューターの内部動作の詳細の多くを抽象化する言語です。良い例はメモリ管理です。低レベルのプログラミング言語では、タスクの処理に費やされる時間とコード行に加えて、コンピュータのメモリのレイアウト、割り当て、解放の複雑さを詳細に理解する必要があります。 Pythonはこれらの詳細の多くを抽象化して自動的に処理するため、達成したいことに集中できます。
Pythonは高級プログラミング言語であるため、コードはより簡潔で、技術的な実装の詳細ではなく、達成したいことのビジネスロジックにほぼ完全に焦点を合わせています。言語設計の選択がこれに貢献します。例として、Pythonは、他の多くの言語のように関数、ループ、および線を描くために中括弧やセミコロンを使用する必要がないため、より簡潔になり、一部の人が主張するように、改善されます。読みやすさ。
Pythonでの言語設計の選択に影響を与えた1つの観察は、プログラムが書かれるよりも頻繁に読まれるということです。 Pythonは、コードが平易な英語に非常に近いため、特にスクリプトまたはプログラムのさまざまなコンポーネントに適切な方法で名前を付ける場合に優れています。
啓発された試行錯誤は、完璧な知性の計画よりも優れています。 -デビッド・ケリー
Pythonは、Pythonシェル、IPython、JupyterノートブックなどのインタラクティブなインタープリターツールがPythonツールチェーンの中心であるため、プロトタイピングと迅速な反復型開発(そしてもちろん試行錯誤)に理想的です。これらのインタラクティブな環境では、コードの各行を個別に記述して実行し、結果(または役立つエラーメッセージ)をすぐに確認できます。他の言語にもこれがありますが、ほとんどの場合、Pythonと同程度ではありません。
Pythonは、プロトタイピングに最適であるだけでなく、大規模な本番アプリケーション向けの優れた強力な言語でもあります。世界最大のソフトウェア会社のいくつかは、さまざまなアプリケーションやユースケースでPythonを多用しています。
基本的な操作に必要なものはすべて言語に組み込まれていますが、それに加えて、Python標準ライブラリには、ファイル、メディア、ネットワーキング、日付と時刻の情報などを操作するためのツールがあります。これにより、サードパーティのパッケージを探すことなく、さまざまなタスクを実行できます。
金融の専門家向けに、 DataFrameを備えたPandas およびシリーズ オブジェクト、およびNumpyとその ndarray Pythonを使用した財務分析の主力製品です。 matplotlibやその他の視覚化ライブラリと組み合わせると、生産性を高めるための優れたツールを自由に使用できます。
Pythonはオープンソースライセンスの下で開発されており、商用利用も無料です。
以下は、以前のブログ投稿で説明したモンテカルロシミュレーションの簡略化されたバージョンを作成する方法を示すステップバイステップのチュートリアルですが、Excel用の@RISKプラグインの代わりにPythonを使用しています。
モンテカルロ法は、数値結果を得るためにランダムサンプリングに依存しています。そのようなアプリケーションの1つは、変数または仮定がさまざまな値をとることができる、世界の不確実な潜在的な将来の状態を表す確率分布からランダムなサンプルを抽出することです。
オプションやその他のデリバティブの評価を示す一般的な例ではなく、簡略化されたDCF評価モデルでモンテカルロシミュレーションを実行すると便利です。これには、財務諸表の計算の基本以外の計算は必要ないためです。キャッシュフローを割り引いて、Pythonの概念とツールに集中できるようにします。ただし、この基本的なチュートリアルモデルは、主要な概念を説明することを目的としており、実際の目的でそのまま使用することはできません。また、モンテカルロシミュレーションのより学術的な側面については触れません。
このチュートリアルは、変数や関数など、プログラミングの基本的な構成要素に精通していることを前提としています。そうでない場合は、たとえばこの紹介の主要な概念を確認するのに10分かかると役立つ場合があります。
モンテカルロシミュレーションチュートリアルで使用したものと同じ非常に単純化されたDCF評価モデルから始めます。 3つの財務諸表からのいくつかの重要な項目と、強調表示された3つの入力セルがあり、Excelバージョンでは、潜在的な結果の範囲の調査を開始するために確率分布に置き換えたいと考えている点推定があります。
それを機能させ、正しくし、速くする-ケントベック
このチュートリアルの目的は、Pythonを初めて使用する財務専門家に、便利なプログラムがどのように見えるかだけでなく、プログラムの開発に使用できる反復プロセスについても紹介することです。したがって、2つの部分で構成されます。
Jupyterノートブックは、Pythonをインタラクティブに操作するための優れたツールです。これは、コード、マークダウンテキスト、画像、またはその他のデータを含むことができるセルを備えたインタラクティブなPythonインタープリターです。このチュートリアルでは、Python Quant Platformを使用しましたが、無料でクラウドで実行されるColaboratorybyGoogleをお勧めすることもできます。そこに到達したら、[ファイル]メニューで[新しいPython 3ノートブック]を選択するだけで、準備が整います。
それが終わったら、次のステップは、データの操作と視覚化に必要なサードパーティのパッケージをインポートし、個別のウィンドウではなく、ノートブックにグラフをインラインで表示することをプログラムに指示することです。
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
最初の変数に名前を付ける前のメモ。すでに強調したように、読みやすさはPythonの強みの1つです。言語設計はそれをサポートするのに大いに役立ちますが、コードを書くすべての人は、他の人だけでなく自分自身にとっても、それを読みやすく理解できるようにする責任があります。イーグルソンの法則が述べているように、「6か月以上見ていなかった自分のコードは、他の誰かによって書かれた可能性もあります。」
経験則として、プログラムの機能を説明する個別のコメントの必要性を最小限に抑えるような方法で、プログラムのコンポーネントに名前を付けることをお勧めします。
それを念頭に置いて、次に進みましょう。
Pythonで既存のスプレッドシートデータを操作する方法はたくさんあります。たとえば、read_excel
を使用して、1行のコードでPandasDataFrameにシートを読み込むことができます。 指図。スプレッドシートとPythonコードをより緊密に統合してリアルタイムでリンクしたい場合は、その機能を提供するために無料と商用の両方のオプションを利用できます。
ここでのモデルは非常に単純であり、Pythonの概念に焦点を当てるために、スクリプトで最初からモデルを再作成します。最初のパートの最後に、作成したものをスプレッドシートにエクスポートする方法を示します。
財務諸表のPython表現を作成するための最初のステップとして、適切なデータ構造が必要になります。選択できるものはたくさんあり、Pythonに組み込まれているものもあれば、さまざまなライブラリからのものもあります。または、独自に作成することもできます。とりあえず、Pandasライブラリのシリーズを使用してその機能を見てみましょう:
years = ['2018A', '2019B', '2020P', '2021P', '2022P', '2023P']
sales = pd.Series(index=years)
sales['2018A'] = 31.0
sales
この入力とそれに対応する出力を以下に示します。
最初の3行で、年(それぞれが実際、予算、または予測のいずれであるかを示すためにマークされている)、開始値(元のDCFモデルの場合のように、数百万ユーロ)で構成されるインデックスを持つデータ構造を作成しました。投影用の空の(NaN、「数値ではない」)セル。 4行目は、データの表現を出力します。一般に、対話型インタープリターで変数または他のオブジェクトの名前を入力すると、通常、データの適切な表現が得られます。
次に、予測される年間売上成長を表す変数を宣言します。この段階では、元のDCFモデルと同じ数値である点推定です。最初にこれらの同じ入力を使用し、PythonバージョンがExcelバージョンと同じように実行され、同じ結果が得られることを確認してから、点推定を確率分布に置き換えることを検討します。この変数を使用して、前年と成長率に基づいて予測の各年の売上を計算するループを作成します。
growth_rate = 0.1
for year in range(1, 6):
sales[year] = sales[year - 1] * (1 + growth_rate)
sales
NaNの代わりに売上を予測しました:
同じアプローチを使用して、財務諸表を継続し、必要に応じて変数を宣言し、最終的にフリーキャッシュフローに到達するために必要な計算を実行します。そこに着いたら、私たちが持っているものがDCFモデルのExcelバージョンが言っていることに対応していることを確認できます。
ebitda_margin = 0.14
depr_percent = 0.032
ebitda = sales * ebitda_margin
depreciation = sales * depr_percent
ebit = ebitda - depreciation
nwc_percent = 0.24
nwc = sales * nwc_percent
change_in_nwc = nwc.shift(1) - nwc
capex_percent = depr_percent
capex = -(sales * capex_percent)
tax_rate = 0.25
tax_payment = -ebit * tax_rate
tax_payment = tax_payment.apply(lambda x: min(x, 0))
free_cash_flow = ebit + depreciation + tax_payment + capex + change_in_nwc
free_cash_flow
これにより、フリーキャッシュフローが得られます:
この段階でおそらくコメントが必要な上記の1行は、2番目のtax_payment
です。 参照。ここでは、小さな関数を適用して、税引前利益がマイナスになるシナリオで、プラスの納税が行われないようにします。これは、PandasシリーズまたはDataFrameのすべてのセルにカスタム関数を効果的に適用できることを示しています。もちろん、実際に適用される関数は単純化です。より大規模な評価を行うためのより現実的なモデルには、企業固有のいくつかの要因に基づいて支払われる実際の現金税を計算する別の税モデルがあります。
予測キャッシュフローに到達したら、単純な最終価値を計算し、すべてのキャッシュフローを現在まで割引してDCF結果を取得できます。次のコードは、インデックス作成とスライスを導入しています。これにより、PandasSeriesオブジェクトなどのデータ構造内の1つ以上の要素にアクセスできます。
構造体の名前の直後に角かっこを書くことで要素にアクセスします。単純なインデックス作成では、ゼロから始まる位置で要素にアクセスします。つまり、free_cash_flow[1]
2番目の要素を与えます。 [-1]
は最後の要素にアクセスするための省略形であり(昨年のキャッシュフローは最終値の計算に使用されます)、コロンを使用するとスライスが得られます。つまり、[1:]
過去の年2018A
を含めたくないため、最初の要素を除くすべての要素を提供します DCF評価で。
cost_of_capital = 0.12
terminal_growth = 0.02
terminal_value = ((free_cash_flow[-1] * (1 + terminal_growth)) /
(cost_of_capital - terminal_growth))
discount_factors = [(1 / (1 + cost_of_capital)) ** i for i in range (1,6)]
dcf_value = (sum(free_cash_flow[1:] * discount_factors) +
terminal_value * discount_factors[-1])
dcf_value
これで、プロトタイプの最初の部分は終わりです。これで、Pythonで、非常に基本的なモデルではありますが、動作するDCFモデルができました。
実際のモンテカルロシミュレーションに移る前に、Pandasパッケージで利用可能なエクスポート機能について説明する良い機会かもしれません。 Pandas DataFrameオブジェクトがある場合は、to_excel
を使用して、1行でExcelファイルに書き込むことができます。 方法。他の12以上のフォーマットや宛先にもエクスポートするための同様の機能があります。
output = pd.DataFrame([sales, ebit, free_cash_flow],
index=['Sales', 'EBIT', 'Free Cash Flow']).round(1)
output.to_excel('Python DCF Model Output.xlsx')
output
これで、次の課題に取り組む準備が整いました。点推定入力の一部を確率分布に置き換えることです。この時点までの手順は、Excelで同じモデルを作成する場合に比べてやや面倒に思えるかもしれませんが、次の数行で、Pythonがいかに強力であるかを垣間見ることができます。
最初のステップは、シミュレーションで実行する反復回数を決定することです。開始点として1,000を使用すると、適切な出力プロットを取得するのに十分なデータポイントを取得することと、適切な時間枠内でシミュレーションを終了することのバランスが取れます。次に、実際の分布を生成します。簡単にするために、ここでは3つの正規分布を生成しましたが、NumPyライブラリには多数の分布から選択でき、Python標準ライブラリなど他の場所もあります。使用する分布を決定したら、平均や標準偏差、望ましい結果の数など、形状を記述するために必要なパラメーターを指定する必要があります。
iterations = 1000
sales_growth_dist = np.random.normal(loc=0.1, scale=0.01, size=iterations)
ebitda_margin_dist = np.random.normal(loc=0.14, scale=0.02, size=iterations)
nwc_percent_dist = np.random.normal(loc=0.24, scale=0.01, size=iterations)
plt.hist(sales_growth_dist, bins=20)
plt.show()
ここで、EBITDAは売上高から独立した別個の確率変数ではなく、ある程度売上高と相関しているべきであると主張することができます。私はこれに同意し、コスト構造(可変、半可変、固定コスト)のダイナミクスと主要なコスト要因(一部には独自の確率分布がある場合があります)をしっかりと理解することによって推進されるべきであると付け加えます。たとえば、入力商品の価格など)ですが、スペースと明確さのために、これらの複雑さはここでは脇に置いておきます。
分布とパラメーターの選択を通知する必要のあるデータが少なければ少ないほど、さまざまなデューデリジェンスワークストリームの結果と経験を組み合わせて、さまざまな可能性のあるシナリオに関するコンセンサスビューを形成する必要があります。この例では、キャッシュフロー予測では、主観的な要素が大きくなります。つまり、確率分布を視覚化することが重要になります。ここでは、2行の短いコードで、売上成長の分布を示す基本的な視覚化を取得できます。このようにして、チームの集合的な見解を最もよく反映する眼球への分布をすばやく表示できます。
これで、シミュレーションを実行するために必要なすべてのビルディングブロックができましたが、シミュレーションを実行するのに便利な形式ではありません。これまでに使用したものと同じコードを次に示しますが、すべてを1つのセルにまとめ、便宜上関数に再配置しました。
def run_mcs():
# Create probability distributions
sales_growth_dist = np.random.normal(loc=0.1, scale=0.01, size=iterations)
ebitda_margin_dist = np.random.normal(loc=0.14, scale=0.02, size=iterations)
nwc_percent_dist = np.random.normal(loc=0.24, scale=0.01, size=iterations)
# Calculate DCF value for each set of random inputs
output_distribution = []
for i in range(iterations):
for year in range(1, 6):
sales[year] = sales[year - 1] * (1 + sales_growth_dist[0])
ebitda = sales * ebitda_margin_dist[i]
depreciation = (sales * depr_percent)
ebit = ebitda - depreciation
nwc = sales * nwc_percent_dist[i]
change_in_nwc = nwc.shift(1) - nwc
capex = -(sales * capex_percent)
tax_payment = -ebit * tax_rate
tax_payment = tax_payment.apply(lambda x: min(x, 0))
free_cash_flow = ebit + depreciation + tax_payment + capex + change_in_nwc
# DCF valuation
terminal_value = (free_cash_flow[-1] * 1.02) / (cost_of_capital - 0.02)
free_cash_flow[-1] += terminal_value
discount_factors = [(1 / (1 + cost_of_capital)) ** i for i in range (1,6)]
dcf_value = sum(free_cash_flow[1:] * discount_factors )
output_distribution.append(dcf_value)
return output_distribution
これで、シミュレーション全体を実行し、出力分布をプロットできます。これは、次のコードを使用して、1,000回の反復ごとのこの会社の割引キャッシュフロー値になります。 %time
コマンドはPythonコードではなく、何かを実行する時間を測定するノートブックの省略形です(代わりに、標準ライブラリのPython関数を使用できます)。実行するコンピューターによって異なりますが、このバージョンでは、1,000回の反復を実行して結果を視覚化するのに1〜2秒かかります。
%time plt.hist(run_mcs(), bins=20, color='r')
plt.show()
何かを単純化できるという疑念が潜んでいるのは、やりがいのある課題の世界で最も豊富な情報源です。 -エドガー・ダイクストラ
リファクタリングとは、既存のコードを書き直して、機能を変更せずに構造を改善するプロセスのことであり、コーディングの最も楽しくやりがいのある要素の1つです。これを行うにはいくつかの理由があります。次のような場合があります:
そのプロセスの1つのステップがどのように見えるかを示すために、プロトタイプスクリプトのように全体に散らばるのではなく、すべての初期変数を1つの場所に収集することで、ウォークスルーしたプロトタイプをクリーンアップし、次のプロセスを通じて実行速度を最適化しました。 ベクトル化 。
NumPy配列を使用すると、さまざまな種類のデータ処理タスクを、ループの記述が必要になる可能性のある簡潔な配列式として表現できます。明示的なループを配列式に置き換えるこの方法は、一般にベクトル化と呼ばれます。ウェス・マッキニー
見た目がすっきりとわかりやすくなりました:
# Key inputs from DCF model
years = 5
starting_sales = 31.0
capex_percent = depr_percent = 0.032
sales_growth = 0.1
ebitda_margin = 0.14
nwc_percent = 0.24
tax_rate = 0.25
# DCF assumptions
r = 0.12
g = 0.02
# For MCS model
iterations = 1000
sales_std_dev = 0.01
ebitda_std_dev = 0.02
nwc_std_dev = 0.01
def run_mcs():
# Generate probability distributions
sales_growth_dist = np.random.normal(loc=sales_growth,
scale=sales_std_dev,
size=(years, iterations))
ebitda_margin_dist = np.random.normal(loc=ebitda_margin,
scale=ebitda_std_dev,
size=(years, iterations))
nwc_percent_dist = np.random.normal(loc=nwc_percent,
scale=nwc_std_dev,
size=(years, iterations))
# Calculate free cash flow
sales_growth_dist += 1
for i in range(1, len(sales_growth_dist)):
sales_growth_dist[i] *= sales_growth_dist[i-1]
sales = sales_growth_dist * starting_sales
ebitda = sales * ebitda_margin_dist
ebit = ebitda - (sales * depr_percent)
tax = -(ebit * tax_rate)
np.clip(tax, a_min=None, a_max=0)
nwc = nwc_percent_dist * sales
starting_nwc = starting_sales * nwc_percent
prev_year_nwc = np.roll(nwc, 1, axis=0)
prev_year_nwc[0] = starting_nwc
delta_nwc = prev_year_nwc - nwc
capex = -(sales * capex_percent)
free_cash_flow = ebitda + tax + delta_nwc + capex
# Discount cash flows to get DCF value
terminal_value = free_cash_flow[-1] * (1 + g) / (r - g)
discount_rates = [(1 / (1 + r)) ** i for i in range (1,6)]
dcf_value = sum((free_cash_flow.T * discount_rates).T)
dcf_value += terminal_value * discount_rates[-1]
return dcf_value
The main difference you will notice between this version and the previous one is the absence of the for i in range(iterations)
loop. Using NumPy’s array operation, this version runs in 18 milliseconds compared to the 1.35 seconds for the prototype version - roughly 75x faster.
%time plt.hist(run_mcs(), bins=20, density=True, color="r")
plt.show()
I’m sure that further optimization is possible, since I put together both the prototype and refined version in a short time solely for the purpose of this tutorial.
This tutorial showed some of the powerful features of Python, and if you were to develop this further the opportunities are almost endless. You could for example:
I haven’t even touched upon what you could also do with the various web, data science, and machine learning applications that have contributed to Python’s success.
This article gave an introduction to the Python programming language, listed some of the reasons why it has become so popular in finance and showed how to build a small Python script. In a step-by-step tutorial, I walked through how Python can be used for iterative prototyping, interactive financial analysis, and for application code for valuation models, algorithmic trading programs and more.
For me, at the end of the day, the killer feature of Python technology is that it is simply fun to work with! If you enjoy problem-solving, building things and making workflows more efficient, then I encourage you to try it out. I would love to hear what you have done with it or would like to do with it.