Python en Financiën – Verbeter uw spreadsheets

Samenvatting

Waarom is Python een geweldige programmeertaal voor financiële professionals om te leren?
  • Python is een programmeertaal op hoog niveau, wat betekent dat het veel van de technische aspecten van programmeren wegneemt en afhandelt, zoals geheugenbeheer, dat expliciet in andere talen moet worden afgehandeld. Dit maakt Python gemakkelijk te gebruiken voor mensen zonder technische achtergrond.
  • Omdat de taal is ontworpen met het oog op leesbaarheid en gebruiksgemak, is het een van de gemakkelijkst te leren talen. Python-code is beknopt en bijna Engels.
  • Python is ideaal voor prototyping en snelle, iteratieve ontwikkeling. De interactieve tolktools bieden omgevingen waarin u elke regel code afzonderlijk kunt schrijven en uitvoeren en de resultaten onmiddellijk kunt zien.
  • Tegelijkertijd is Python robuust en performant, waardoor het ook een haalbare keuze is voor kernsystemen en grotere applicaties.
  • Naast de grote standaardbibliotheek met handige tools, heeft Python geweldige bibliotheken van derden voor financiële analyse en computergebruik, zoals de Pandas- en NumPy-bibliotheken die in deze tutorial worden gebruikt.
Wat zijn enkele use-cases voor het samen implementeren van Python en Finance?
  • Python-scripts kunnen worden gebruikt om repetitieve taken en workflows te automatiseren, waardoor tijd wordt bespaard en het risico op handmatige fouten wordt verkleind.
  • Met scripts kunnen gebruikers eenvoudig gegevens uit spreadsheets, databases en API's halen, of zelfs webgegevens schrapen, die vervolgens kunnen worden verwerkt en geanalyseerd met krachtige statistische en analytische hulpmiddelen.
  • Met verschillende plug-ins voor Excel kunnen gebruikers realtime tweerichtingskoppelingen maken tussen uw spreadsheets en Python-code.
  • Python maakt nieuwe soorten analyse mogelijk, zoals Monte Carlo-simulaties, die niet direct beschikbaar zijn in standaard spreadsheets.
  • Algoritmische handel is niet langer het exclusieve domein van hedgefondsen en grote investeringsbanken. Met Python kunt u in korte tijd en tegen lage kosten uw eigen handelsstrategieën ontwikkelen, backtesten en implementeren.

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.

Gebruiksscenario's:voorbeelden van waar ik Python voor heb gebruikt

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:

1. Honderden activiteiten in de loop van de tijd volgen in een M&A-integratie PMO-setup

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:

  1. Sla de status van het hele bord wekelijks op als een CSV-bestand.
  2. Lees alle historische CSV-bestanden in een Pandas DataFrame.
  3. Sorteer, filter, groepeer en manipuleer de gegevens in overeengekomen formaten van hoe we de voortgang willen volgen (op de status van activiteit, werkstroom, enz.).
  4. Schrijf de uitvoer naar een Excel-bestand met de gegevens van elke analyse in een eigen blad, zodanig opgemaakt dat het eenvoudig kan worden gekopieerd en geplakt in denkceldiagrammen.
  5. Maak tabellen en grafieken voor het rapportagepakket voor de maandelijkse stuurgroepvergadering.

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.

2. Huisprijsstatistieken analyseren met behulp van webscraping, Google Maps API en Excel

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:

  1. Schrap gegevens van onroerend goed, inclusief adres, grootte, aantal kamers, vraagprijs en andere kenmerken, voor een bepaald gebied; een paar honderd tot misschien wel duizend regels in totaal.
  2. Opslaan in een Python-gegevensstructuur.
  3. Maak verbinding met de Google Maps API en haal voor elke vermelding de afstand op tussen de accommodatie en belangrijke bezienswaardigheden zoals de zee, het stadscentrum, het dichtstbijzijnde treinstation, de dichtstbijzijnde luchthaven, enz.
  4. Exporteer de gegevens naar een Excel-bestand.
  5. Gebruik standaard Excel-functionaliteit om regressies uit te voeren, statistieken te berekenen en grafieken te maken op basis van standaardstatistieken zoals prijs per vierkante meter en afstand tot oriëntatiepunten.

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.

Waarom Python een geweldige keuze is voor financiële professionals

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.

1. Python is een programmeertaal op hoog niveau

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.

2. Het is beknopt

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.

3. Gemakkelijk te leren en te begrijpen

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.

4. Geschikt voor snelle, iteratieve ontwikkeling

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.

5. Kan zowel voor prototypes als productiecodes worden gebruikt

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.

6. Wordt geleverd met "Inbegrepen batterijen:" De Python-standaardbibliotheek

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.

7. Geweldige bibliotheken van derden voor financiële analyse

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.

8. Python is gratis!

Python is ontwikkeld onder een open source-licentie, waardoor het ook gratis is voor commercieel gebruik.

Stap-voor-stap handleiding voor het samen gebruiken van Python en Finance

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.

Het uitgangspunt en de gewenste uitkomst

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.

Een aanpak in twee stappen voor het ontwikkelen van een klein script

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:

  1. Eerst ontwikkel ik een werkend prototype met behulp van een rechttoe rechtaan aanpak die volgens mij gemakkelijk te volgen is en niet helemaal anders is dan het proces dat je zou kunnen gebruiken om dit project te starten als je helemaal opnieuw zou beginnen.
  2. Nadat ik het werkende prototype heb ontwikkeld, loop ik door het proces van refactoring - de structuur van code veranderen zonder de functionaliteit ervan te veranderen. Misschien wil je voor dat deel blijven - het is een elegantere oplossing dan de eerste, en als bonus is het ongeveer 75x sneller in termen van uitvoeringstijd.

1. Een werkend prototype ontwikkelen

De Jupyter-notebook instellen

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.

De financiële overzichten maken

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.

De DCF-waardering uitvoeren

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.

De gegevens exporteren

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

Waarschijnlijkheidsverdelingen maken voor onze Monte Carlo-simulatie

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()

2. Het prototype verfijnen

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:

  1. Organiseer de verschillende onderdelen op een verstandigere manier.
  2. Hernoem variabelen en functies om hun doel en werking duidelijker te maken.
  3. Toestaan ​​en voorbereiden op toekomstige functies.
  4. Verbeter de uitvoeringssnelheid, geheugenvoetafdruk of ander resourcegebruik.

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.

Taking it Further

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:

  • Scrape or download relevant company or sector statistics from web pages or other data sources, to help inform your choice of assumptions and probability distributions.
  • Use Python in quantitative finance applications, such as in an automated trading algorithm based on fundamental and/or macroeconomic factors.
  • Build exporting capabilities that generate output in a spreadsheet and/or presentation format, to be used as part of your internal transaction review and approval process, or for external presentations.

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.

In Summary:A Useful Language for Your Financial Toolbox

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.

  • O’Reilly books. I can especially recommend:
    • Python for Finance by Yves Hilpisch
    • Learning Python by Mark Lutz
    • Fluent Python by Luciano Ramalho
  • The Python Quants
  • PyCon talks on YouTube
  • Udemy

Bedrijfsfinanciering
  1. boekhouding
  2. Bedrijfsstrategie
  3. Bedrijf
  4. Klantrelatiebeheer
  5. financiën
  6. Aandelen beheer
  7. Persoonlijke financiën
  8. investeren
  9. Bedrijfsfinanciering
  10. begroting
  11. Besparingen
  12. verzekering
  13. schuld
  14. met pensioen gaan