Python i finanse — usprawnij swoje arkusze kalkulacyjne
Opublikowany: 2022-03-11Podsumowanie wykonawcze
Dlaczego Python jest świetnym językiem programowania dla finansistów?
- Python jest językiem programowania wysokiego poziomu, co oznacza, że abstrahuje i obsługuje wiele technicznych aspektów programowania, takich jak zarządzanie pamięcią, które muszą być wyraźnie obsługiwane w innych językach. To sprawia, że Python jest łatwy w użyciu dla osób bez wiedzy technicznej.
- Ponieważ język został zaprojektowany z myślą o czytelności i łatwości użycia, jest to jeden z najłatwiejszych języków do nauki. Kod Pythona jest zwięzły i zbliżony do zwykłego angielskiego.
- Python jest idealny do tworzenia prototypów i szybkiego, iteracyjnego programowania. Jego interaktywne narzędzia interpretujące zapewniają środowiska, w których można napisać i wykonać każdy wiersz kodu oddzielnie i natychmiast zobaczyć wyniki.
- Jednocześnie Python jest solidny i wydajny, co czyni go opłacalnym wyborem również w przypadku podstawowych systemów i większych aplikacji.
- Oprócz dużej standardowej biblioteki przydatnych narzędzi, Python ma świetne biblioteki innych firm do analizy finansowej i obliczeń, takie jak biblioteki Pandas i NumPy używane w tym samouczku.
Jakie są przypadki użycia dla wspólnego wdrożenia Pythona i finansów?
- Skrypty Pythona mogą być używane do automatyzacji powtarzalnych zadań i przepływów pracy, oszczędzając czas i zmniejszając ryzyko błędów ręcznych.
- Skrypty umożliwiają użytkownikom łatwe pobieranie danych z arkuszy kalkulacyjnych, baz danych i interfejsów API, a nawet pobieranie danych internetowych, które następnie można przetwarzać i analizować za pomocą potężnych narzędzi statystycznych i analitycznych.
- Różne wtyczki do programu Excel umożliwiają użytkownikom tworzenie w czasie rzeczywistym dwukierunkowych połączeń między arkuszami kalkulacyjnymi a kodem Python.
- Python umożliwia nowe typy analiz, takie jak symulacje Monte Carlo, które nie są łatwo dostępne w standardowych arkuszach kalkulacyjnych.
- Handel algorytmiczny nie jest już wyłączną domeną funduszy hedgingowych i dużych banków inwestycyjnych. Dzięki Pythonowi możesz opracowywać, testować wstecznie i wdrażać własne strategie handlowe w krótkim czasie i przy niskich kosztach.
W przypadku zawodów, które od dawna polegają na przeglądaniu arkuszy kalkulacyjnych, Python jest szczególnie cenny. Amerykański bank Citigroup wprowadził przyspieszony kurs języka Python dla swoich stażystów analityków. - Ekonomista
Specjaliści ds. finansów od dawna mają dostęp do VBA (Visual Basic for Applications) w programie Excel, aby tworzyć niestandardowe funkcje i automatyzować przepływy pracy. Wraz z pojawieniem się w ostatnich latach Arkuszy Google jako poważnego konkurenta w przestrzeni arkuszy kalkulacyjnych, Google Apps Script oferuje teraz dodatkowy wybór.
Chciałbym jednak zwrócić uwagę na trzecią opcję, język programowania Python, który stał się niezwykle popularny w wielu dziedzinach.
W tym artykule przedstawię kilka przykładów tego, co możesz osiągnąć za pomocą Pythona, zaczynając od przeglądu samego języka i dlaczego stał się on tak popularny w tak wielu różnych dziedzinach, począwszy od tworzenia stron internetowych, uczenia maszynowego, finansów, nauka i edukacja, żeby wymienić tylko kilka. Druga połowa będzie się składać z samouczka krok po kroku.
Celem, który piszę, jest pomoc w podjęciu decyzji, czy Python wygląda na tyle intrygująco, abyś rozważył dodanie go do swojego zestawu narzędzi finansowych. Jeśli zdecydujesz się na ten krok, dostępnych jest wiele aplikacji, kursów, filmów, artykułów, książek i wpisów na blogu do nauki języka. Na końcu artykułu wymieniłem kilka zasobów, które pomogły mi w drodze.
Przypadki użycia: przykłady tego, do czego użyłem Pythona
Moim wprowadzeniem do programowania była nauka języka BASIC na Oric 1 w połowie lat 80-tych. W tamtych czasach BASIC był najpopularniejszym językiem dla początkujących. Inne języki, którymi zajmowałem się od późnych lat 80. do połowy lat 90. to Pascal i C, ale nigdy nie używałem ich zawodowo i nie spodziewałem się, że będę potrzebować ani używać umiejętności programistycznych. Według mojej wiedzy pod koniec lat 90. finanse i programowanie były bardzo różnymi dziedzinami, kiedy zdecydowałem się rozpocząć karierę w finansach.
Szybko do 2012 roku i chciałem wrócić do programowania jako hobby, więc zacząłem szukać dostępnych wówczas języków. Okazało się, że całkiem sporo się wydarzyło i kiedy natknąłem się na Pythona, wciągnąłem się z wielu powodów, które opiszę w następnej sekcji. Od tego czasu używam Pythona do szerokiego zakresu zadań, od małych skryptów po większe projekty, zarówno osobiście, jak i zawodowo. Wiele, ale nie wszystkie, korzystały z arkuszy kalkulacyjnych, które są warsztatem wielu specjalistów od finansów.
Oto kilka przykładów tego, jak dobrze arkusze kalkulacyjne i Python mogą ze sobą współpracować:
1. Śledzenie setek działań w czasie w konfiguracji PMO integracji fuzji i przejęć
Zajmuję się wszystkimi aspektami transakcji M&A, nie tylko ich realizacją, ale także integracją. W niedawnym przypadku zespół PMO zdecydował się na hybrydowe podejście do zarządzania programami i projektami, wykorzystując planowanie kaskadowe i wykresy Gantta dla planów wysokiego poziomu dla każdego z dwunastu strumieni roboczych integracji, a także tablicę Kanban do śledzenia setek wykonywanych czynności w dowolnym momencie, w pierwszym abonamencie 100-dniowym i później. Wybrane narzędzie Kanban, MeisterTask, posiada szereg funkcji statystycznych i raportowych, ale nasze potrzeby wykraczały poza analizę i prezentację, która wymagała niestandardowego rozwiązania. Oto przepływ pracy, który zautomatyzowałem za pomocą Pythona:
- Zapisuj status całej tablicy co tydzień jako plik CSV.
- Wczytaj wszystkie historyczne pliki CSV do Pandas DataFrame.
- Sortuj, filtruj, grupuj i manipuluj danymi w uzgodnionych formatach, w jaki sposób chcemy śledzić postępy (według statusu aktywności, strumienia pracy itp.).
- Zapisz wynik do pliku Excel z danymi z każdej analizy w osobnym arkuszu, sformatowanym w taki sposób, aby można go było po prostu skopiować i wkleić do wykresów typu think-cell.
- Twórz tabele i wykresy do pakietu sprawozdawczego na comiesięczne posiedzenie komitetu sterującego.
Opracowanie skryptu wymagało kilkugodzinnej inwestycji z góry, ale teraz aktualizacja pakietu raportów na spotkania komitetu sterującego lub analizy ad hoc zajmuje tylko kilka minut. Dosłownie około 30 sekund, aby przejść do odpowiedniego folderu i uruchomić skrypt za pomocą polecenia jednowierszowego, a następnie kilka minut, aby skopiować i wkleić dane wyjściowe do talii. Z około 500 czynnościami (kartami) w dwunastu strumieniach roboczych już po około miesiącu od wykonania, cotygodniowym śledzeniu ich ruchu, w obrębie dwuletniej osi czasu programu, szybko okazuje się, że masz do czynienia z tysiącami, a ostatecznie dziesiątkami tysięcy punktów danych w dziesiątkach plików. Bez automatyzacji mówimy tutaj o bardzo żmudnych zadaniach.
Kompromis „wartości pieniądza w czasie” między zwykłym zajęciem się rzeczami lub zwiększeniem początkowego obciążenia pracą poprzez skonfigurowanie automatyzacji jest powszechnym tematem w finansach. Podobną decyzję podjąłem w pierwszym kroku tego procesu, eksportując dane jako pliki CSV. MeisterTask, podobnie jak wiele nowoczesnych aplikacji internetowych, ma interfejs API, który można podłączyć do aplikacji Pythona, ale czas poświęcony na jego skonfigurowanie znacznie przewyższyłby oszczędność czasu w naszym przypadku użycia.
Jak widać, często optymalnym rozwiązaniem jest zautomatyzowanie niektórych etapów przepływu pracy i trzymanie innych instrukcji.
2. Analizowanie statystyk cen domów za pomocą Web Scraping, Google Maps API i Excel
Innym przykładem jest coś, co zrobiłem z osobistego zainteresowania, ale chcę to podkreślić, ponieważ zawiera kilka innych interesujących elementów narzędzia Pythona:
- Dane ze skrobania wykazów nieruchomości, w tym adres, wielkość, liczba pokoi, cena wywoławcza i inne cechy dla danego obszaru; w sumie od kilkuset do może tysiąca wierszy.
- Zapisz w strukturze danych Pythona.
- Połącz się z interfejsem API Map Google i dla każdego wpisu pobierz odległość między obiektem a kluczowymi punktami orientacyjnymi, takimi jak morze, centrum miasta, najbliższa stacja kolejowa, najbliższe lotnisko itp.
- Eksportuj dane do pliku Excel.
- Użyj standardowej funkcji Excela do wykonywania regresji, obliczania statystyk i tworzenia wykresów na podstawie standardowych wskaźników, takich jak cena za metr kwadratowy i odległość do punktów orientacyjnych.
Wyniki tutaj można połączyć z własnymi wagami w zakresie preferencji i ograniczeń finansowych podczas poszukiwania nieruchomości.
To tylko dwa przykłady, koncentrujące się na automatyzacji pracy związanej z arkuszami kalkulacyjnymi i dodawaniu funkcji, ale możliwości Pythona są prawie nieograniczone. W następnej sekcji przedstawię powody, dla których stała się tak popularna, zanim przejdę do samouczka symulacji Monte Carlo w Pythonie krok po kroku.
Dlaczego Python jest doskonałym wyborem dla specjalistów finansowych
Język programowania Python istnieje od 1990 roku, ale dopiero w ostatnich latach jego popularność eksplodowała.
Powodów jest kilka, spójrzmy na każdy z nich po kolei.
1. Python to język programowania wysokiego poziomu
Język programowania wysokiego poziomu to taki, który abstrahuje od wielu szczegółów wewnętrznego działania komputera. Dobrym przykładem jest zarządzanie pamięcią. Języki programowania niższego poziomu wymagają szczegółowego zrozumienia złożoności sposobu rozmieszczania, przydzielania i zwalniania pamięci komputera, a także czasu spędzonego i linii kodu wymaganych do obsługi zadań. Python abstrahuje i automatycznie obsługuje wiele z tych szczegółów, pozostawiając ci skupienie się na tym, co chcesz osiągnąć.
2. To jest zwięzłe
Ponieważ Python jest językiem programowania wysokiego poziomu, kod jest bardziej zwięzły i prawie całkowicie skoncentrowany na logice biznesowej tego, co chcesz osiągnąć, a nie na technicznych szczegółach implementacji. Przyczyniają się do tego wybory dotyczące projektowania języka: na przykład Python nie wymaga używania nawiasów klamrowych ani średników do wyznaczania funkcji, pętli i linii, tak jak robi to wiele innych języków, co czyni go bardziej zwięzłym i, jak twierdzą niektórzy, poprawia czytelność.
3. Łatwy do nauczenia i zrozumienia
Jedną z obserwacji, która wpłynęła na wybory dotyczące projektowania języka w Pythonie, jest to, że programy są czytane częściej niż są pisane. Python przoduje tutaj, ponieważ jego kod wygląda bardzo podobnie do zwykłego angielskiego, zwłaszcza jeśli nazywasz różne komponenty swojego skryptu lub programu w rozsądny sposób.
4. Nadaje się do szybkiego, iteracyjnego rozwoju
Oświecone metody prób i błędów przewyższają planowanie doskonałych intelektów. - David Kelley
Python jest idealny do tworzenia prototypów i szybkiego, iteracyjnego programowania (a także prób i błędów), ponieważ interaktywne narzędzia interpretujące, takie jak powłoka Pythona, IPython i notatniki Jupyter, znajdują się na pierwszym miejscu w łańcuchu narzędzi Pythona. W tych interaktywnych środowiskach możesz napisać i wykonać każdy wiersz kodu oddzielnie i natychmiast zobaczyć wyniki (lub pomocny komunikat o błędzie). Inne języki też to mają, ale w większości przypadków nie w takim stopniu jak Python.
5. Może być używany zarówno do prototypowania, jak i kodu produkcyjnego
Oprócz tego, że doskonale nadaje się do tworzenia prototypów, Python jest również doskonałym i potężnym językiem dla dużych aplikacji produkcyjnych. Niektóre z największych firm programistycznych na świecie intensywnie wykorzystują Python w różnych aplikacjach i przypadkach użycia.
6. Zawiera „Baterie w zestawie”: standardową bibliotekę Pythona
Wszystko, co jest potrzebne do podstawowych operacji, jest wbudowane bezpośrednio w język, ale oprócz tego standardowa biblioteka Pythona zawiera narzędzia do pracy z plikami, multimediami, sieciami, informacjami o dacie i godzinie i nie tylko. Pozwala to na wykonywanie szerokiej gamy zadań bez konieczności szukania pakietów innych firm.
7. Świetne zewnętrzne biblioteki do analiz finansowych
Dla specjalistów od finansów Pandas z obiektami DataFrame i Series oraz Numpy z ndarray to konie robocze analizy finansowej w Pythonie. W połączeniu z matplotlib i innymi bibliotekami wizualizacji masz do dyspozycji doskonałe narzędzia, które pomagają zwiększyć produktywność.
8. Python jest darmowy!
Python jest rozwijany na licencji open source, dzięki czemu jest darmowy również do użytku komercyjnego.
Samouczek krok po kroku dotyczący wspólnego korzystania z Pythona i finansów
Poniżej znajduje się samouczek krok po kroku pokazujący, jak stworzyć uproszczoną wersję symulacji Monte Carlo opisanej w moim poprzednim wpisie na blogu, ale przy użyciu Pythona zamiast wtyczki @RISK do programu Excel.
Metody Monte Carlo polegają na losowym próbkowaniu w celu uzyskania wyników liczbowych. Jednym z takich zastosowań jest pobieranie losowych próbek z rozkładu prawdopodobieństwa reprezentującego niepewne potencjalne przyszłe stany świata, w których zmienne lub założenia mogą przyjmować szereg wartości.
Pomocne jest przeprowadzenie symulacji Monte Carlo na uproszczonym modelu wyceny DCF zamiast bardziej powszechnych przykładów, które widzisz, pokazując wycenę opcji lub innych instrumentów pochodnych, ponieważ nie potrzebujemy do tego żadnej matematyki poza podstawami obliczania sprawozdań finansowych i dyskontowanie przepływów pieniężnych, co pozwala nam skupić się na koncepcjach i narzędziach Pythona. Należy jednak pamiętać, że ten podstawowy model samouczka ma na celu zilustrowanie kluczowych pojęć i nie jest przydatny do jakichkolwiek celów praktycznych. Nie będę też poruszał żadnych bardziej akademickich aspektów symulacji Monte Carlo.
W samouczku założono, że znasz podstawowe bloki konstrukcyjne programowania, takie jak zmienne i funkcje. Jeśli nie, warto poświęcić 10 minut na sprawdzenie kluczowych pojęć, na przykład w tym wprowadzeniu.
Punkt wyjścia i pożądany rezultat
Zaczynam od tego samego, bardzo uproszczonego modelu wyceny DCF, używanego w samouczku symulacji Monte Carlo. Zawiera kilka kluczowych pozycji z trzech sprawozdań finansowych i trzy podświetlone komórki wejściowe, które w wersji Excela mają oszacowania punktowe, które teraz chcemy zastąpić rozkładami prawdopodobieństwa, aby rozpocząć badanie potencjalnych zakresów wyników.
Dwuetapowe podejście do tworzenia małego skryptu
Spraw, aby to działało, spraw, by było dobrze, spraw, by to działało — Kent Beck
Intencją tego samouczka jest przedstawienie finansistom, którzy są nowicjuszami w Pythonie, nie tylko tego, jak może wyglądać użyteczny program, ale także do procesu iteracyjnego, którego można użyć do jego tworzenia. Składa się zatem z dwóch części:
- Najpierw opracowuję działający prototyp przy użyciu prostego podejścia, które moim zdaniem jest łatwe do naśladowania i nie różni się całkowicie od procesu, którego można użyć do rozpoczęcia tego projektu, gdybyś zaczął od zera.
- Następnie po opracowaniu działającego prototypu przechodzę przez proces refaktoryzacji - zmiany struktury kodu bez zmiany jego funkcjonalności. Możesz chcieć pozostać przy tej części - jest to bardziej eleganckie rozwiązanie niż pierwsze, a jako bonus jest około 75x szybsze pod względem czasu realizacji.
1. Opracowanie działającego prototypu
Konfigurowanie notatnika Jupyter
Notatnik Jupyter to doskonałe narzędzie do interaktywnej pracy z językiem Python. Jest to interaktywny interpreter Pythona z komórkami, które mogą zawierać kod, tekst Markdown, obrazy lub inne dane. Do tego samouczka użyłem Python Quant Platform, ale mogę też polecić Colaboratory by Google, który jest darmowy i działa w chmurze. Tam po prostu wybierz "Nowy notatnik Python 3" w menu "Plik" i jesteś gotowy do pracy.
Po wykonaniu tej czynności, następnym krokiem jest zaimportowanie pakietów innych firm, których potrzebujemy do manipulacji danymi i wizualizacji, i poinformowanie programu, że chcemy widzieć wykresy w naszym notatniku, a nie w osobnych oknach:
import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline
Uwaga, zanim zaczniemy nazywać nasze pierwsze zmienne. Jak już podkreśliłem, czytelność jest jedną z mocnych stron Pythona. Projektowanie języka znacznie to wspiera, ale każdy, kto pisze kod, jest odpowiedzialny za uczynienie go czytelnym i zrozumiałym, nie tylko dla innych, ale także dla siebie. Jak mówi Prawo Eaglesona: „Każdy własny kod, na który nie patrzyłeś przez sześć lub więcej miesięcy, równie dobrze mógł zostać napisany przez kogoś innego”.
Dobrą zasadą jest nazywanie składników programu w taki sposób, aby zminimalizować potrzebę osobnych komentarzy wyjaśniających, co robi program.
Mając to na uwadze, przejdźmy dalej.
Tworzenie sprawozdań finansowych
Istnieje wiele sposobów pracy z istniejącymi danymi arkusza kalkulacyjnego w Pythonie. Moglibyśmy na przykład wczytać arkusz do Pandas DataFrame za pomocą jednego wiersza kodu za pomocą polecenia read_excel
. Jeśli chcesz ściślejszej integracji i połączenia w czasie rzeczywistym między arkuszem kalkulacyjnym a kodem Python, dostępne są zarówno bezpłatne, jak i komercyjne opcje, które zapewniają tę funkcjonalność.

Ponieważ model tutaj jest bardzo prosty i aby skupić się na koncepcjach Pythona, odtworzymy go od podstaw w naszym skrypcie. Na końcu pierwszej części pokażę, jak możesz wyeksportować to, co stworzyliśmy, do arkusza kalkulacyjnego.
Jako pierwszy krok w kierunku stworzenia reprezentacji sprawozdań finansowych w Pythonie będziemy potrzebować odpowiedniej struktury danych. Jest wiele do wyboru, niektóre wbudowane w Pythona, inne z różnych bibliotek lub możemy stworzyć własne. Na razie skorzystajmy z Serii z biblioteki Pandy, aby przyjrzeć się jej funkcjonalności:
years = ['2018A', '2019B', '2020P', '2021P', '2022P', '2023P'] sales = pd.Series(index=years) sales['2018A'] = 31.0 sales
To wejście i odpowiadające mu wyjście pokazano poniżej:
W pierwszych trzech wierszach utworzyliśmy strukturę danych z indeksem składającym się z lat (każdy zaznaczony, aby pokazać, czy jest to Rzeczywista, Budżetowa czy Przewidywana), wartości początkowej (w milionach euro, jak w oryginalnym modelu DCF) oraz puste (NaN, „Nie liczba”) komórki dla projekcji. Czwarta linia wyświetla reprezentację danych - ogólnie rzecz biorąc, wpisanie nazwy zmiennej lub innych obiektów w interaktywnym interpreterze zwykle daje sensowną jej reprezentację.
Następnie deklarujemy zmienną reprezentującą przewidywany roczny wzrost sprzedaży. Na tym etapie jest to oszacowanie punktowe, takie samo jak w naszym oryginalnym modelu DCF. Chcemy najpierw użyć tych samych danych wejściowych i potwierdzić, że nasza wersja Pythona działa tak samo i daje takie same wyniki jak wersja Excel, zanim przyjrzymy się zastąpieniu oszacowań punktowych rozkładami prawdopodobieństwa. Korzystając z tej zmiennej tworzymy pętlę obliczającą sprzedaż w każdym roku z prognoz na podstawie roku poprzedniego i tempa wzrostu:
growth_rate = 0.1 for year in range(1, 6): sales[year] = sales[year - 1] * (1 + growth_rate) sales
Mamy teraz prognozowaną sprzedaż zamiast NaN:
Stosując to samo podejście, kontynuujemy przeglądanie sprawozdań finansowych, deklarując zmienne zgodnie z potrzebami i wykonując niezbędne obliczenia, aby ostatecznie uzyskać wolny przepływ środków pieniężnych. Gdy już tam dotrzemy, możemy sprawdzić, czy to, co mamy, odpowiada temu, co mówi wersja modelu DCF w Excelu.
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
To daje nam wolne przepływy pieniężne:
Jedna linia powyżej, która być może wymaga komentarza na tym etapie, to druga referencja tax_payment
. Tutaj stosujemy małą funkcję, aby zapewnić, że w scenariuszach, w których zysk przed opodatkowaniem stanie się ujemny, nie będziemy mieli dodatniej zapłaty podatku. To pokazuje, jak skutecznie możesz zastosować niestandardowe funkcje do wszystkich komórek w serii Pandas lub DataFrame. Faktycznie zastosowana funkcja jest oczywiście uproszczeniem. Bardziej realistyczny model dla większej wyceny miałby oddzielny model podatkowy, który oblicza faktycznie zapłacony podatek gotówkowy w oparciu o szereg czynników specyficznych dla firmy.
Wykonywanie wyceny DCF
Po dojściu do prognozowanych przepływów pieniężnych możemy teraz obliczyć prostą wartość końcową i zdyskontować wszystkie przepływy pieniężne z powrotem do chwili obecnej, aby uzyskać wynik DCF. Poniższy kod wprowadza indeksowanie i wycinanie, które umożliwiają nam dostęp do jednego lub więcej elementów w strukturze danych, takich jak obiekt Pandas Series.
Dostęp do elementów uzyskujemy pisząc nawiasy kwadratowe bezpośrednio po nazwie konstrukcji. Proste indeksowanie umożliwia dostęp do elementów według ich pozycji, zaczynając od zera, co oznacza, że free_cash_flow[1]
da nam drugi element. [-1]
jest skrótem dostępu do ostatniego elementu (przepływ gotówki z ostatniego roku jest używany do obliczenia wartości końcowej), a użycie dwukropka daje nam wycinek, co oznacza, że [1:]
daje nam wszystkie elementy oprócz pierwszego, ponieważ nie chcemy uwzględniać historycznego roku 2018A
w naszej wycenie 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
Na tym kończy się pierwsza część naszego prototypu — mamy teraz działający model DCF, aczkolwiek bardzo szczątkowy, w Pythonie.
Eksportowanie danych
Zanim przejdziemy do rzeczywistej symulacji Monte Carlo, może to być dobry moment, aby wspomnieć o możliwościach eksportowania dostępnych w pakiecie Pandas. Jeśli masz obiekt Pandas DataFrame, możesz zapisać go do pliku Excela w jednym wierszu, używając metody to_excel
. Podobną funkcjonalność umożliwia eksportowanie do kilkunastu innych formatów i miejsc docelowych.
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
Tworzenie rozkładów prawdopodobieństwa dla naszej symulacji Monte Carlo
Teraz jesteśmy gotowi do podjęcia kolejnego wyzwania: zastąpienia niektórych danych wejściowych estymacji punktowej rozkładami prawdopodobieństwa. Chociaż kroki do tego momentu mogły wydawać się nieco kłopotliwe w porównaniu z budowaniem tego samego modelu w programie Excel, te kilka następnych wierszy da ci wgląd w to, jak potężny może być Python.
Naszym pierwszym krokiem jest określenie, ile iteracji chcemy uruchomić w symulacji. Użycie 1000 jako punktu początkowego zapewnia równowagę między uzyskaniem wystarczającej liczby punktów danych, aby uzyskać rozsądne wykresy wyjściowe, a zakończeniem symulacji w rozsądnym czasie. Następnie generujemy rzeczywiste rozkłady. Dla uproszczenia wygenerowałem tutaj trzy dystrybucje normalne, ale biblioteka NumPy ma dużą liczbę dystrybucji do wyboru, są też inne miejsca, w których warto zajrzeć, w tym standardowa biblioteka Pythona. Po podjęciu decyzji, którego rozkładu użyć, musimy określić parametry wymagane do opisania ich kształtu, takie jak średnia i odchylenie standardowe oraz liczba pożądanych wyników.
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()
Tutaj można argumentować, że EBITDA nie powinna być odrębną zmienną losową niezależną od sprzedaży, ale w pewnym stopniu skorelowaną ze sprzedażą. Zgadzam się z tym i dodam, że powinno się to opierać na solidnym zrozumieniu dynamiki struktury kosztów (koszty zmienne, półzmienne i stałe) oraz kluczowych czynników kosztotwórczych (niektóre z nich mogą mieć własne rozkłady prawdopodobieństwa, takie jak na przykład ceny surowców), ale odkładam te zawiłości na bok ze względu na przestrzeń i przejrzystość.
Im mniej masz danych do wyboru dystrybucji i parametrów, tym bardziej będziesz musiał polegać na wynikach różnych strumieni roboczych due diligence w połączeniu z doświadczeniem, aby stworzyć konsensusowy pogląd na zakres prawdopodobnych scenariuszy. W tym przykładzie, z prognozami przepływów pieniężnych, będzie duży składnik subiektywny, co oznacza, że wizualizacja rozkładów prawdopodobieństwa staje się ważna. Tutaj możemy uzyskać podstawową wizualizację, pokazującą rozkład wzrostu sprzedaży, za pomocą zaledwie dwóch krótkich linijek kodu. W ten sposób możemy szybko przejrzeć dowolną dystrybucję do oka takiej, która najlepiej odzwierciedla zbiorowy pogląd zespołu.
Teraz mamy już wszystkie elementy potrzebne do uruchomienia symulacji, ale nie są one w formacie dogodnym do uruchomienia symulacji. Oto ten sam kod, z którym pracowaliśmy do tej pory, ale wszystkie zebrane w jednej komórce i przegrupowane w funkcję dla wygody:
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
Możemy teraz uruchomić całą symulację i wykreślić rozkład wyników, który będzie zdyskontowaną wartością przepływów pieniężnych tej firmy w każdej z 1000 iteracji, za pomocą następującego kodu. Polecenie %time
nie jest kodem Pythona, ale skrótem notatnika, który mierzy czas do uruchomienia czegoś (możesz zamiast tego użyć funkcji Pythona ze standardowej biblioteki). Zależy to od komputera, na którym go uruchomisz, ale ta wersja potrzebuje 1-2 sekund, aby uruchomić 1000 iteracji i zwizualizować wynik.
%time plt.hist(run_mcs(), bins=20, color='r') plt.show()
2. Udoskonalanie prototypu
Czyhające podejrzenie, że coś można uprościć, jest najbogatszym na świecie źródłem satysfakcjonujących wyzwań. - Edsger Dijkstra
Refaktoryzacja odnosi się do procesu przepisywania istniejącego kodu w celu ulepszenia jego struktury bez zmiany jego funkcjonalności i może być jednym z najbardziej zabawnych i satysfakcjonujących elementów kodowania. Powodów może być kilka. Może to być:
- Uporządkuj różne części w bardziej rozsądny sposób.
- Zmień nazwy zmiennych i funkcji, aby ich cel i działanie były jaśniejsze.
- Zezwól i przygotuj się na przyszłe funkcje.
- Popraw szybkość wykonywania, zużycie pamięci lub inne wykorzystanie zasobów.
Aby pokazać, jak może wyglądać jeden krok w tym procesie, wyczyściłem prototyp, przez który właśnie przeszliśmy, zbierając wszystkie początkowe zmienne w jednym miejscu, a nie rozrzucone po całym skrypcie, i zoptymalizowałem szybkość jego wykonywania w procesie zwanym wektoryzacja .
Korzystanie z tablic NumPy umożliwia wyrażanie wielu rodzajów zadań przetwarzania danych jako zwięzłych wyrażeń tablicowych, które w przeciwnym razie mogłyby wymagać zapisywania pętli. Ta praktyka zastępowania wyraźnych pętli wyrażeniami tablicowymi jest powszechnie nazywana wektoryzacją. Wes McKinney
Teraz wygląda na czystszy i łatwiejszy do zrozumienia:
# 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
Główną różnicą, jaką zauważysz między tą wersją a poprzednią, jest brak pętli for i in range(iterations)
. Korzystając z operacji na tablicy NumPy, ta wersja działa w ciągu 18 milisekund w porównaniu do 1,35 sekundy w przypadku wersji prototypowej – około 75 razy szybciej.
%time plt.hist(run_mcs(), bins=20, density=True, color="r") plt.show()
Jestem pewien, że dalsza optymalizacja jest możliwa, ponieważ zarówno prototypową, jak i dopracowaną wersję złożyłem w krótkim czasie wyłącznie na potrzeby tego samouczka.
Idąc dalej
Ten samouczek pokazał niektóre z potężnych funkcji Pythona, a jeśli miałbyś je dalej rozwijać, możliwości są prawie nieograniczone. Możesz na przykład:
- Wyszukuj lub pobieraj odpowiednie statystyki firmy lub sektora ze stron internetowych lub innych źródeł danych, aby pomóc w wyborze założeń i rozkładów prawdopodobieństwa.
- Używaj Pythona w ilościowych aplikacjach finansowych, na przykład w automatycznym algorytmie handlowym opartym na czynnikach fundamentalnych i/lub makroekonomicznych.
- Twórz możliwości eksportowania, które generują dane wyjściowe w formacie arkusza kalkulacyjnego i/lub prezentacji, do wykorzystania jako część wewnętrznego procesu przeglądu i zatwierdzania transakcji lub do prezentacji zewnętrznych.
Nie wspomniałem nawet o tym, co można zrobić z różnymi aplikacjami internetowymi, data science i machine learning, które przyczyniły się do sukcesu Pythona.
Podsumowując: przydatny język dla twojego zestawu narzędzi finansowych
W tym artykule przedstawiono wprowadzenie do języka programowania Python, wymieniono niektóre powody, dla których stał się on tak popularny w finansach, oraz pokazano, jak zbudować mały skrypt w Pythonie. W samouczku krok po kroku omówiłem, w jaki sposób Python może być używany do iteracyjnego prototypowania, interaktywnej analizy finansowej i kodu aplikacji do modeli wyceny, programów do handlu algorytmicznego i nie tylko.
Dla mnie, pod koniec dnia, zabójczą cechą technologii Pythona jest to, że po prostu fajnie się z nią pracuje! Jeśli lubisz rozwiązywać problemy, budować rzeczy i usprawniać przepływy pracy, zachęcam do wypróbowania tego. Chciałbym usłyszeć, co z nim zrobiłeś lub chciałbyś z nim zrobić.
Zasoby zalecane dla specjalistów finansowych do nauki języka Python
- Książki O'Reilly'ego. Szczególnie polecam:
- Python for Finance by Yves Hilpisch
- Learning Python by Mark Lutz
- Fluent Python by Luciano Ramalho
- The Python Quants
- PyCon talks on YouTube
- Udemy