Voor beroepen die lange tijd vertrouwden op het doorbladeren van spreadsheets, is Python vooral waardevol. Citigroup, een Amerikaanse bank, heeft een spoedcursus Python geïntroduceerd voor haar stagiair-analisten. - De econoom
Financiële professionals hebben al lang toegang tot VBA (Visual Basic for Applications) in Excel om aangepaste functionaliteit te bouwen en workflows te automatiseren. Met de opkomst in de afgelopen jaren van Google Spreadsheets als een serieuze concurrent in de spreadsheetruimte, biedt Google Apps Script nu een extra keuze.
Ik wil echter de aandacht vestigen op een derde optie, de programmeertaal Python, die op een aantal gebieden enorm populair is geworden.
In dit artikel zal ik enkele voorbeelden geven van wat u met Python kunt bereiken, te beginnen met een overzicht van de taal zelf en waarom deze zo populair is geworden in zo'n grote verscheidenheid aan gebieden, variërend van webontwikkeling, machine learning, financiën, wetenschap en onderwijs, om er maar een paar te noemen. De tweede helft bestaat dan uit een stapsgewijze zelfstudie.
Het doel van mijn schrijven is om u te helpen beslissen of Python er intrigerend genoeg uitziet om te overwegen het aan uw financiële gereedschapskist toe te voegen. Als je de sprong waagt, zijn er veel apps, cursussen, video's, artikelen, boeken en blogposts beschikbaar om de taal te leren. Aan het einde van het stuk heb ik een aantal bronnen opgesomd die me op weg hebben geholpen.
Mijn introductie tot programmeren was het leren van BASIC op een Oric 1 in het midden van de jaren tachtig. Destijds was BASIC de meest voorkomende beginnerstaal. Andere talen waar ik eind jaren 80 tot midden jaren 90 mee bezig was, waren Pascal en C, maar ik gebruikte ze nooit in een professionele hoedanigheid en ik verwachtte niet dat ik programmeervaardigheden nodig zou hebben of gebruiken. Voor zover ik weet, eind jaren 90, waren financiën en programmeren heel verschillende gebieden, toen ik ervoor koos om een carrière in de financiële wereld te beginnen.
Snel vooruit naar 2012, en ik wilde programmeren weer oppakken als hobby, dus begon ik onderzoek te doen naar de talen die op dat moment beschikbaar waren. Het bleek dat er nogal wat was gebeurd, en toen ik Python tegenkwam, was ik verslaafd, om veel van de redenen die ik in de volgende sectie zal schetsen. Sindsdien heb ik Python gebruikt voor een breed scala aan taken, van kleine scripts tot grotere projecten, zowel persoonlijk als professioneel. Veel, maar niet alle, hebben spreadsheets gebruikt, de werkbank van menig financieel professional.
Hier zijn een paar voorbeelden van hoe goed spreadsheets en Python samen kunnen gaan:
Ik werk met alle aspecten van M&A transacties, niet alleen de uitvoering, maar ook de integratie. In een recent geval besloot het PMO-team tot een hybride programma- en projectmanagementaanpak, waarbij watervalplanning en Gantt-diagrammen werden gebruikt voor plannen op hoog niveau voor elk van de twaalf integratiewerkstromen, naast een Kanban-bord voor het volgen van de honderden activiteiten die gaande zijn. op elk willekeurig moment, in het eerste 100-dagenplan en daarna. De gekozen Kanban-tool, MeisterTask, heeft een aantal statistische en rapportagefuncties, maar onze behoeften gingen verder dan dat op het gebied van analyse en presentatie, waarvoor een oplossing op maat nodig was. Dit is de workflow die ik heb geautomatiseerd met Python:
Het ontwikkelen van het script vergde een initiële investering van een paar uur, maar nu duurt het updaten van het rapportagepakket voor stuurgroepvergaderingen of ad-hocanalyse slechts enkele minuten. Letterlijk ongeveer 30 seconden om naar de juiste map te gaan en het script uit te voeren met een opdracht van één regel, en dan een paar minuten om de uitvoer in het diadeck te kopiëren en plakken. Met ongeveer 500 activiteiten (kaarten) verspreid over twaalf werkstromen die al ongeveer een maand in uitvoering zijn, wekelijks bijhouden hoe ze bewegen, binnen een programmatijdlijn van twee jaar, merk je al snel dat je te maken hebt met duizenden en uiteindelijk tienduizenden datapunten over tientallen van bestanden. Zonder automatisering hebben we het hier over een aantal zeer vervelende taken.
De afweging "tijdswaarde van geld" tussen gewoon doorgaan met dingen of meer initiële werklast toevoegen door automatisering in te stellen, is een veelvoorkomend thema in financiën. Ik nam een soortgelijke beslissing met de eerste stap van dit proces, door de gegevens als CSV-bestanden te exporteren. MeisterTask heeft, net als veel moderne webapplicaties, een API, die kan worden verbonden met je Python-applicatie, maar de tijd die het kost om het in te stellen zou veel groter zijn dan de tijdwinst voor onze use case hier.
Dus, zoals u ziet, is de optimale oplossing vaak om bepaalde stappen van een workflow te automatiseren en andere handmatig te houden.
Een ander voorbeeld is iets dat ik deed uit persoonlijke interesse, maar ik wil het benadrukken omdat het enkele andere interessante elementen van Python's hulpprogramma bevat:
De resultaten hier kunnen worden gecombineerd met uw eigen persoonlijke wegingen in termen van voorkeuren en financiële beperkingen bij het zoeken naar onroerend goed.
Dit zijn slechts twee voorbeelden, gericht op het automatiseren van spreadsheetgerelateerd werk en het toevoegen van functies, maar de mogelijkheden met Python zijn bijna eindeloos. In het volgende gedeelte zal ik de redenen uiteenzetten waarom het zo populair is geworden, voordat ik verder ga met een stapsgewijze Monte Carlo-simulatie-tutorial in Python.
De programmeertaal Python bestaat al sinds 1990, maar het is pas de laatste jaren dat zijn populariteit explodeerde.
Hier zijn verschillende redenen voor, laten we ze een voor een bekijken.
Een programmeertaal op hoog niveau is er een die veel van de details van de innerlijke werking van de computer wegneemt. Een goed voorbeeld is geheugenbeheer. Programmeertalen op een lager niveau vereisen een gedetailleerd begrip van de complexiteit van hoe het geheugen van de computer is ingedeeld, toegewezen en vrijgegeven, naast de tijd en regels die nodig zijn om taken uit te voeren. Python abstraheert en verwerkt veel van deze details automatisch, zodat jij je kunt concentreren op wat je wilt bereiken.
Omdat Python een programmeertaal op hoog niveau is, is de code beknopter en bijna volledig gericht op de bedrijfslogica van wat u wilt bereiken, in plaats van op technische implementatiedetails. Taalontwerpkeuzes dragen hieraan bij:Python vereist bijvoorbeeld niet het gebruik van accolades of puntkomma's om functies, lussen en lijnen af te bakenen zoals veel andere talen doen, wat het beknopter maakt en, zoals sommigen beweren, verbetert leesbaarheid.
Een observatie die de taalontwerpkeuzes in Python heeft beïnvloed, is dat programma's vaker worden gelezen dan dat ze worden geschreven. Python blinkt hier uit omdat de code erg op gewoon Engels lijkt, vooral als je de verschillende componenten van je script of programma op een verstandige manier een naam geeft.
Verlicht vallen en opstaan overtreft de planning van een onberispelijk intellect. - David Kelley
Python is ideaal voor prototyping en snelle, iteratieve ontwikkeling (en ja, trial-and-error) omdat interactieve interpreter-tools zoals de Python-shell, IPython en Jupyter-notebooks centraal staan in de Python-toolchain. In deze interactieve omgevingen kunt u elke regel code afzonderlijk schrijven en uitvoeren en de resultaten (of een nuttige foutmelding) onmiddellijk zien. Andere talen hebben dit ook, maar in de meeste gevallen niet in dezelfde mate als Python.
Python is niet alleen geweldig voor prototyping, maar ook een uitstekende en krachtige taal voor grote productietoepassingen. Enkele van de grootste softwarebedrijven ter wereld maken intensief gebruik van Python in een verscheidenheid aan toepassingen en gebruiksscenario's.
Alles wat nodig is voor basisbewerkingen is rechtstreeks in de taal ingebouwd, maar daarnaast heeft de Python-standaardbibliotheek tools voor het werken met bestanden, media, netwerken, datum- en tijdinformatie en nog veel meer. Hierdoor kunt u een breed scala aan taken uitvoeren zonder dat u naar pakketten van derden hoeft te zoeken.
Voor financiële professionals, Panda's met zijn DataFrame en Serie objecten, en Numpy met zijn ndarray zijn de werkpaarden van financiële analyse met Python. In combinatie met matplotlib en andere visualisatiebibliotheken heb je geweldige tools tot je beschikking om de productiviteit te ondersteunen.
Python is ontwikkeld onder een open source-licentie, waardoor het ook gratis is voor commercieel gebruik.
Wat volgt is een stapsgewijze zelfstudie die laat zien hoe u een vereenvoudigde versie van de Monte Carlo-simulatie kunt maken die in mijn vorige blogpost is beschreven, maar met Python in plaats van de @RISK-plug-in voor Excel.
Monte Carlo-methoden zijn afhankelijk van willekeurige steekproeven om numerieke resultaten te verkrijgen. Een van die toepassingen is het trekken van willekeurige steekproeven uit een kansverdeling die onzekere potentiële toekomstige toestanden van de wereld vertegenwoordigt waar variabelen of aannames een reeks waarden kunnen aannemen.
Het is handig om de Monte Carlo-simulatie uit te voeren op een vereenvoudigd DCF-waarderingsmodel in plaats van de meer gebruikelijke voorbeelden die u ziet met de waardering van opties of andere derivaten, omdat we hiervoor geen wiskunde nodig hebben die verder gaat dan de basis van het berekenen van de financiële overzichten en cashflows verdisconteren, waardoor we ons kunnen concentreren op de Python-concepten en -tools. Houd er echter rekening mee dat dit basismodel voor zelfstudie bedoeld is om de belangrijkste concepten te illustreren en niet bruikbaar is voor praktische doeleinden. Ik zal ook niet ingaan op de meer academische aspecten van Monte Carlo-simulaties.
De tutorial gaat ervan uit dat je bekend bent met de basisbouwstenen van programmeren, zoals variabelen en functies. Zo niet, dan kan het handig zijn om 10 minuten de tijd te nemen om de belangrijkste concepten in bijvoorbeeld deze inleiding te controleren.
Ik begin met hetzelfde zeer vereenvoudigde DCF-waarderingsmodel dat werd gebruikt in de Monte Carlo-simulatiehandleiding. Het bevat enkele belangrijke regelitems uit de drie financiële overzichten en drie gemarkeerde invoercellen, die in de Excel-versie puntschattingen hebben die we nu willen vervangen door kansverdelingen om mogelijke reeksen van resultaten te verkennen.
Zorg dat het werkt, maak het goed, maak het snel - Kent Beck
De bedoeling van deze tutorial is om financiële professionals die nieuw zijn in Python niet alleen een introductie te geven van hoe een nuttig programma eruit zou kunnen zien, maar ook een introductie in het iteratieve proces dat je kunt gebruiken om het te ontwikkelen. Het bestaat daarom uit twee delen:
De Jupyter-notebook is een geweldig hulpmiddel om interactief met Python te werken. Het is een interactieve Python-interpreter met cellen die code, Markdown-tekst, afbeeldingen of andere gegevens kunnen bevatten. Voor deze tutorial heb ik het Python Quant Platform gebruikt, maar ik kan Colaboratory van Google ook aanraden, dat gratis is en in de cloud draait. Eenmaal daar selecteert u eenvoudig "Nieuw Python 3 Notebook" in het menu "Bestand" en u bent klaar om te gaan.
Als we dat hebben gedaan, is de volgende stap het importeren van de pakketten van derden die we nodig hebben voor gegevensmanipulatie en visualisaties, en het programma vertellen dat we grafieken inline in onze notebook willen zien, in plaats van in afzonderlijke vensters:
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline
Een opmerking voordat we onze eerste variabelen gaan benoemen. Zoals ik al heb benadrukt, is leesbaarheid een van de sterke punten van Python. Taalontwerp ondersteunt dat in grote mate, maar iedereen die code schrijft, is verantwoordelijk voor het leesbaar en begrijpelijk maken, niet alleen voor anderen, maar ook voor zichzelf. Zoals de wet van Eagleson stelt:"Elke eigen code waar je zes of meer maanden niet naar hebt gekeken, had net zo goed door iemand anders kunnen zijn geschreven."
Een goede vuistregel is om de onderdelen van je programma zo te noemen dat je zo min mogelijk aparte opmerkingen nodig hebt waarin wordt uitgelegd wat je programma doet.
Laten we met dat in gedachten verder gaan.
Er zijn veel manieren waarop we met bestaande spreadsheetgegevens in Python kunnen werken. We kunnen bijvoorbeeld een blad in een Pandas DataFrame lezen met één regel code met behulp van de read_excel
opdracht. Als u een nauwere integratie en realtime koppeling tussen uw spreadsheet en Python-code wilt, zijn er zowel gratis als commerciële opties beschikbaar om die functionaliteit te bieden.
Omdat het model hier heel eenvoudig is en om ons te concentreren op de Python-concepten, zullen we het helemaal opnieuw maken in ons script. Aan het einde van het eerste deel zal ik laten zien hoe u kunt exporteren wat we hebben gemaakt naar een spreadsheet.
Als eerste stap naar het maken van een Python-weergave van de jaarrekening hebben we een geschikte datastructuur nodig. Er zijn er veel om uit te kiezen, sommige ingebouwd in Python, andere uit verschillende bibliotheken, of we kunnen er zelf een maken. Laten we voor nu een serie uit de Pandas-bibliotheek gebruiken om de functionaliteit ervan te bekijken:
years = ['2018A', '2019B', '2020P', '2021P', '2022P', '2023P']
sales = pd.Series(index=years)
sales['2018A'] = 31.0
sales
Deze ingang en de bijbehorende uitgang worden hieronder weergegeven:
Met de eerste drie regels hebben we een datastructuur gecreëerd met een index bestaande uit jaren (elk gemarkeerd om aan te geven of het Actual, Budget of Projected is), een startwaarde (in miljoenen euro's, zoals in het originele DCF-model), en lege (NaN, "Not a Number") cellen voor de projecties. De vierde regel drukt een representatie van de gegevens af - in het algemeen geeft het typen van de naam van een variabele of andere objecten in de interactieve interpreter u er meestal een zinnige voorstelling van.
Vervolgens declareren we een variabele om de verwachte jaarlijkse omzetgroei weer te geven. In dit stadium is het een puntschatting, hetzelfde cijfer als in ons oorspronkelijke DCF-model. We willen eerst dezelfde invoer gebruiken en bevestigen dat onze Python-versie hetzelfde presteert en hetzelfde resultaat geeft als de Excel-versie, voordat we puntschattingen gaan vervangen door kansverdelingen. Met behulp van deze variabele creëren we een lus die de verkoop in elk jaar van de projecties berekent op basis van het voorgaande jaar en de groeisnelheid:
growth_rate = 0.1
for year in range(1, 6):
sales[year] = sales[year - 1] * (1 + growth_rate)
sales
We hebben nu geprojecteerde verkopen in plaats van NaN:
Op dezelfde manier doorlopen we de jaarrekening, declareren we variabelen wanneer we ze nodig hebben en voeren we de nodige berekeningen uit om uiteindelijk tot vrije kasstroom te komen. Als we daar eenmaal zijn, kunnen we controleren of wat we hebben overeenkomt met wat de Excel-versie van het DCF-model zegt.
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
Dit geeft ons de vrije kasstromen:
De ene regel erboven die in dit stadium misschien een opmerking nodig heeft, is de tweede tax_payment
referentie. Hier passen we een kleine functie toe om ervoor te zorgen dat in scenario's waarin de winst voor belasting negatief wordt, we dan geen positieve belastingbetaling hebben. Dit laat zien hoe effectief u aangepaste functies kunt toepassen op alle cellen in een Pandas Series of DataFrame. De feitelijk toegepaste functie is natuurlijk een vereenvoudiging. Een realistischer model voor een grotere waarderingsoefening zou een afzonderlijk belastingmodel hebben dat de daadwerkelijk betaalde contante belastingen berekent op basis van een aantal bedrijfsspecifieke factoren.
Nu we zijn aangekomen bij de geprojecteerde kasstromen, kunnen we nu een eenvoudige eindwaarde berekenen en alle kasstromen terug naar het heden verdisconteren om het DCF-resultaat te krijgen. De volgende code introduceert indexering en slicing, waarmee we toegang hebben tot een of meer elementen in een gegevensstructuur, zoals het Pandas Series-object.
We hebben toegang tot elementen door vierkante haken direct achter de naam van de structuur te schrijven. Eenvoudig indexeren benadert elementen op hun positie, beginnend met nul, wat betekent dat free_cash_flow[1]
zou ons het tweede element geven. [-1]
is een afkorting voor toegang tot het laatste element (de cashflow van het afgelopen jaar wordt gebruikt om de eindwaarde te berekenen), en het gebruik van een dubbele punt geeft ons een segment, wat betekent dat [1:]
geeft ons alle elementen behalve de eerste, omdat we het historische jaar 2018A
niet willen opnemen in onze DCF-waardering.
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
Daarmee is het eerste deel van ons prototype afgesloten - we hebben nu een werkend DCF-model, zij het een zeer rudimentair model, in Python.
Voordat we verder gaan met de daadwerkelijke Monte Carlo-simulatie, is dit misschien een goed moment om de exportmogelijkheden te noemen die beschikbaar zijn in het Pandas-pakket. Als je een Pandas DataFrame-object hebt, kun je dat met één regel naar een Excel-bestand schrijven met de to_excel
methode. Er is een vergelijkbare functionaliteit om te exporteren naar meer dan een dozijn andere formaten en bestemmingen.
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
Nu zijn we klaar om de volgende uitdaging aan te gaan:een deel van de puntschattingsinvoer vervangen door kansverdelingen. Hoewel de stappen tot nu toe misschien wat omslachtig leken vergeleken met het bouwen van hetzelfde model in Excel, zullen de volgende regels je een idee geven van hoe krachtig Python kan zijn.
Onze eerste stap is om te beslissen hoeveel iteraties we in de simulatie willen uitvoeren. Door 1.000 als uitgangspunt te gebruiken, wordt een balans gevonden tussen het verkrijgen van voldoende datapunten om zinvolle outputplots te krijgen, versus het voltooien van de simulatie binnen een redelijk tijdsbestek. Vervolgens genereren we de werkelijke verdelingen. Voor de eenvoud heb ik hier drie normale distributies gegenereerd, maar de NumPy-bibliotheek heeft een groot aantal distributies om uit te kiezen, en er zijn ook andere plaatsen om te kijken, waaronder de standaardbibliotheek van Python. Nadat we hebben besloten welke verdeling we moeten gebruiken, moeten we de parameters specificeren die nodig zijn om hun vorm te beschrijven, zoals gemiddelde en standaarddeviatie, en het aantal gewenste uitkomsten.
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()
Hier zou je kunnen stellen dat EBITDA geen afzonderlijke willekeurige variabele moet zijn die onafhankelijk is van de verkoop, maar in plaats daarvan tot op zekere hoogte gecorreleerd moet zijn met de verkoop. Ik ben het hiermee eens en voeg eraan toe dat het moet worden gedreven door een gedegen begrip van de dynamiek van de kostenstructuur (variabele, semi-variabele en vaste kosten) en de belangrijkste kostenfactoren (waarvan sommige hun eigen kansverdelingen kunnen hebben, zoals bijvoorbeeld de prijzen van inputgrondstoffen), maar die complexiteiten laat ik hier voor de ruimte en duidelijkheid buiten beschouwing.
Hoe minder gegevens u hebt om uw keuze van distributie en parameters te bepalen, hoe meer u zult moeten vertrouwen op de uitkomst van uw verschillende due diligence-werkstromen, gecombineerd met ervaring, om een consensus te vormen over de reeksen van waarschijnlijke scenario's. In dit voorbeeld, met kasstroomprojecties, zal er een grote subjectieve component zijn, waardoor het visualiseren van de kansverdelingen belangrijk wordt. Hier kunnen we een basisvisualisatie krijgen, die de distributie van de verkoopgroei laat zien, met slechts twee korte regels code. Op deze manier kunnen we snel elke distributie naar eyeball bekijken die het beste de collectieve visie van het team weerspiegelt.
Nu hebben we alle bouwstenen die we nodig hebben om de simulatie uit te voeren, maar ze hebben geen handig formaat om de simulatie uit te voeren. Hier is dezelfde code waarmee we tot nu toe hebben gewerkt, maar allemaal verzameld in één cel en voor het gemak herschikt in een functie:
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
We kunnen nu de hele simulatie uitvoeren en de outputverdeling plotten, wat de contante waarde van de cashflow van dit bedrijf in elk van de 1000 iteraties zal zijn, met de volgende code. De %time
commando is geen Python-code, maar een notebook-steno die de tijd meet om iets uit te voeren (u zou in plaats daarvan de Python-functie uit de standaardbibliotheek kunnen gebruiken). Het hangt af van de computer waarop u het uitvoert, maar deze versie heeft 1-2 seconden nodig om de 1000 herhalingen uit te voeren en het resultaat te visualiseren.
%time plt.hist(run_mcs(), bins=20, color='r')
plt.show()
Het op de loer liggende vermoeden dat iets vereenvoudigd kan worden, is 's werelds rijkste bron van lonende uitdagingen. - Edsger Dijkstra
Refactoring verwijst naar het proces van het herschrijven van bestaande code om de structuur te verbeteren zonder de functionaliteit te veranderen, en het kan een van de leukste en meest lonende elementen van coderen zijn. Er kunnen verschillende redenen zijn om dit te doen. Het kan zijn om:
Om te laten zien hoe een stap in dat proces eruit zou kunnen zien, heb ik het prototype waar we zojuist doorheen liepen opgeschoond door alle initiële variabelen op één plek te verzamelen, in plaats van overal verspreid zoals in het prototypescript, en de uitvoeringssnelheid geoptimaliseerd via een proces genaamd vectorisatie .
Door NumPy-arrays te gebruiken, kunt u vele soorten gegevensverwerkingstaken uitdrukken als beknopte array-expressies waarvoor anders schrijflussen nodig zouden zijn. Deze praktijk van het vervangen van expliciete lussen door array-expressies wordt gewoonlijk vectorisatie genoemd. Wes McKinney
Het ziet er nu overzichtelijker en gemakkelijker te begrijpen uit:
# 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.
Apple iPhone XS, XS Max en XR:je eerste blik
Hoe u uw kinderen thuisonderwijs kunt geven
De kracht van CAS en uw e-mail-ID in uw beleggingen in beleggingsfondsen
Waarom en hoe u uw marketinginspanningen kunt automatiseren
Uw zakelijke doel schrijven (en waarom het ertoe doet)
Vrouwelijke ondernemers:bezit uw kracht
Vrouwen in accountancy en financiële prijzen