Python och ekonomi – Förstärk dina kalkylblad

Sammanfattning

Varför är Python ett bra programmeringsspråk för finansproffs att lära sig?
  • Python är ett programmeringsspråk på hög nivå, vilket betyder att det abstraherar bort och hanterar många av de tekniska aspekterna av programmering, såsom minneshantering, som uttryckligen måste hanteras på andra språk. Detta gör Python lätt att använda för de utan teknisk bakgrund.
  • Eftersom språket har utformats med läsbarhet och användarvänlighet i åtanke är det ett av de enklaste språken att lära sig. Python-koden är kortfattad och nära vanlig engelska.
  • Python är idealiskt för prototyper och snabb, iterativ utveckling. Dess interaktiva tolkverktyg tillhandahåller miljöer där du kan skriva och exekvera varje rad kod isolerat och se resultaten direkt.
  • Samtidigt är Python robust och prestanda, vilket gör det till ett lönsamt val även för kärnsystem och större applikationer.
  • Förutom sitt stora standardbibliotek med användbara verktyg, har Python fantastiska tredjepartsbibliotek för finansiell analys och beräkning, såsom Pandas och NumPy-biblioteken som används i den här handledningen.
Vilka användningsfall finns det för att implementera Python och ekonomi tillsammans?
  • Python-skript kan användas för att automatisera repetitiva uppgifter och arbetsflöden, vilket sparar tid och minskar risken för manuella fel.
  • Skript tillåter användare att enkelt hämta data från kalkylblad, databaser och API:er, eller till och med skrapa webbdata, som sedan kan bearbetas och analyseras med hjälp av kraftfulla statistiska och analytiska verktyg.
  • Med olika plugins för Excel kan användare skapa tvåvägslänkar i realtid mellan dina kalkylblad och Python-kod.
  • Python möjliggör nya typer av analyser, som Monte Carlo-simuleringar, som inte är lättillgängliga i standardkalkylblad.
  • Algorithmisk handel är inte längre den exklusiva domänen för hedgefonder och stora investeringsbanker. Med Python kan du utveckla, backtesta och distribuera dina egna handelsstrategier på kort tid och till en låg kostnad.

För yrken som länge har förlitat sig på trålning genom kalkylblad är Python särskilt värdefullt. Citigroup, en amerikansk bank, har infört en snabbkurs i Python för sina analytikerpraktikanter. - The Economist

Ekonomiproffs har länge haft tillgång till VBA (Visual Basic for Applications) i Excel för att bygga anpassad funktionalitet och automatisera arbetsflöden. Med framväxten under de senaste åren av Google Sheets som en seriös utmanare i kalkylarksutrymmet, erbjuder Google Apps Script nu ett ytterligare val.

Jag skulle dock vilja uppmärksamma ett tredje alternativ, programmeringsspråket Python, som har blivit oerhört populärt inom ett antal områden.

I den här artikeln kommer jag att ge några exempel på vad du kan åstadkomma med Python, och börjar med en översikt över själva språket och varför det har blivit så populärt inom så många olika områden, allt från webbutveckling, maskininlärning, ekonomi, vetenskap och utbildning, för att bara nämna några. Den andra halvan kommer sedan att bestå av en steg-för-steg handledning.

Syftet med att jag skriver detta är att hjälpa dig att avgöra om Python ser tillräckligt spännande ut för att du ska överväga att lägga till den i din finansiella verktygslåda. Om du tar steget finns det många appar, kurser, videor, artiklar, böcker och blogginlägg tillgängliga för att lära dig språket. I slutet av stycket har jag listat några resurser som har hjälpt mig på vägen.

Användningsfall:Exempel på vad jag har använt Python till

Min introduktion till programmering var att lära mig BASIC på en Oric 1 i mitten av 1980-talet. Då var BASIC det vanligaste nybörjarspråket. Andra språk som jag sysslade med i slutet av 80-talet fram till mitten av 90-talet var Pascal och C, men jag använde dem aldrig i någon professionell egenskap, och jag förväntade mig inte att behöva eller använda programmeringskunskaper. Såvitt jag vet vid den tiden i slutet av 90-talet var ekonomi och programmering väldigt olika områden, när jag valde att ge mig in på en karriärväg inom finans.

Spola framåt till 2012, och jag tänkte välja tillbaka programmering som en hobby, så jag började undersöka vilka språk som fanns tillgängliga vid den tiden. Det visade sig att det hade hänt en hel del, och när jag stötte på Python var jag fast, av många av anledningarna som jag kommer att beskriva i nästa avsnitt. Sedan dess har jag använt Python för ett brett spektrum av uppgifter, från små skript till större projekt, både personligt och professionellt. Många, men inte alla, har involverat kalkylblad, arbetsbänken för många finansproffs.

Här är några exempel på hur bra kalkylblad och Python kan gå ihop:

1. Spåra hundratals aktiviteter över tid i en PMO-uppsättning för M&A-integrering

Jag arbetar med alla aspekter av M&A-transaktioner, inte bara utförandet, utan även integrationen. I ett nyligen fall beslutade PMO-teamet om en hybrid program- och projektledningsstrategi, med hjälp av vattenfallsplanering och Gantt-diagram för planer på hög nivå för var och en av de tolv integrationsarbetsflödena, förutom en Kanban-styrelse för att spåra de hundratals aktiviteter som pågår på vid varje given tidpunkt, i den första 100-dagarsplanen och därefter. Kanban-verktyget som valdes, MeisterTask, har ett antal statistiska och rapporteringsfunktioner, men våra behov gick längre än vad det gäller analys och presentation, vilket krävde en anpassad lösning. Det här är arbetsflödet som jag automatiserade med Python:

  1. Spara status för hela tavlan varje vecka som en CSV-fil.
  2. Läs alla historiska CSV-filer i en Pandas DataFrame.
  3. Sortera, filtrera, gruppera och manipulera data till överenskomna format för hur vi vill spåra framsteg (efter aktivitetsstatus, arbetsflöde, etc.).
  4. Skriv utdata till en Excel-fil med data från varje analys i sitt eget ark, formaterad på ett sådant sätt att den enkelt kan kopieras och klistras in i tankecellsdiagram.
  5. Skapa tabeller och diagram för rapporteringspaketet för det månatliga styrkommitténs möte.

Att utveckla manuset krävde en förhandsinvestering på några timmar, men nu tar det bara några minuter att uppdatera rapporteringspaketet för styrgruppsmöten eller ad hoc-analyser. Bokstavligen cirka 30 sekunder för att gå till rätt mapp och köra skriptet med ett enradskommando, och sedan några minuter för att kopiera och klistra in utdata i bildspelet. Med cirka 500 aktiviteter (kort) över tolv arbetsflöden som redan har körts ungefär en månad, veckovis spårning av hur de rör sig, inom en programtidslinje på två år, kommer du snabbt på att ta itu med tusentals och så småningom tiotusentals datapunkter över dussintals av filer. Utan automatisering talar vi om några mycket tråkiga uppgifter här.

Avvägningen mellan "tidsvärdet av pengar" mellan att bara komma igång med saker eller lägga till mer initial arbetsbelastning genom att ställa in automatisering är ett vanligt tema inom ekonomi. Jag tog ett liknande beslut med det första steget i denna process, genom att exportera data som CSV-filer. MeisterTask har, liksom många moderna webbapplikationer, ett API som kan kopplas till din Python-applikation, men tiden som går åt för att installera den skulle vida överväga tidsbesparingen för vårt användningsfall här.

Så, som du ser, är den optimala lösningen ofta att automatisera vissa steg i ett arbetsflöde och hålla andra manuella.

2. Analysera husprisstatistik med Web Scraping, Google Maps API och Excel

Ett annat exempel är något jag gjorde av personligt intresse, men jag vill lyfta fram det eftersom det innehåller några andra intressanta delar av Pythons verktyg:

  1. Skrapa data från fastighetslistor, inklusive adress, storlek, antal rum, begärt pris och andra funktioner, för ett visst område; några hundra till kanske tusen rader totalt.
  2. Spara i en Python-datastruktur.
  3. Anslut till Google Maps API och, för varje annons, hämta avståndet mellan fastigheten och viktiga landmärken som havet, stadens centrum, närmaste tågstation, närmaste flygplats, etc.
  4. Exportera data till en Excel-fil.
  5. Använd standard Excel-funktioner för att köra regressioner, beräkna statistik och skapa diagram på standardmått som pris per kvadratmeter och avstånd till landmärken.

Resultaten här kan kombineras med dina egna personliga viktningar när det gäller preferenser och ekonomiska begränsningar när du letar efter fastigheter.

Det här är bara två exempel, fokuserade på att automatisera kalkylbladsrelaterat arbete och lägga till funktioner, men möjligheterna med Python är nästan oändliga. I nästa avsnitt kommer jag att beskriva anledningarna till varför det har blivit så populärt, innan jag går vidare till en steg-för-steg självstudie för Monte Carlo-simulering i Python.

Varför Python är ett utmärkt val för finansproffs

Programmeringsspråket Python har funnits sedan 1990, men det är inte förrän på senare år som dess popularitet har exploderat.

Det finns flera anledningar till detta, låt oss titta på var och en i tur och ordning.

1. Python är ett högnivåprogrammeringsspråk

Ett programmeringsspråk på hög nivå är ett som abstraherar bort många av detaljerna i datorns inre funktioner. Ett bra exempel är minneshantering. Programmeringsspråk på lägre nivå kräver en detaljerad förståelse av komplexiteten i hur datorns minne är upplagt, allokerat och frigjort, förutom den tid som spenderas och kodraderna som krävs för att hantera uppgifter. Python abstraherar bort och hanterar många av dessa detaljer automatiskt, så att du kan fokusera på vad du vill åstadkomma.

2. Det är kortfattat

Eftersom Python är ett programmeringsspråk på hög nivå är koden mer kortfattad och nästan helt fokuserad på affärslogiken för vad du vill uppnå, snarare än tekniska implementeringsdetaljer. Val av språkdesign bidrar till detta:till exempel kräver Python inte användning av krulliga hängslen eller semikolon för att avgränsa funktioner, loopar och linjer på det sätt som många andra språk gör, vilket gör det mer kortfattat och, som vissa hävdar, förbättrar läsbarhet.

3. Lätt att lära sig och förstå

En observation som har påverkat val av språkdesign i Python är att program läses oftare än de skrivs. Python utmärker sig här eftersom dess kod ser väldigt nära vanlig engelska ut, särskilt om du namnger de olika komponenterna i ditt skript eller program på ett vettigt sätt.

4. Lämplig för snabb, iterativ utveckling

Upplyst trial and error överträffar planeringen av felfria intellekt. - David Kelley

Python är idealiskt för prototyper och snabb, iterativ utveckling (och ja, prova och missa) eftersom interaktiva tolkverktyg som Python-skalet, IPython och Jupyter-anteckningsböckerna är främsta i Python-verktygskedjan. I dessa interaktiva miljöer kan du skriva och köra varje kodrad isolerat och se resultaten (eller ett användbart felmeddelande) omedelbart. Andra språk har detta också, men i de flesta fall inte i samma grad som Python.

5. Kan användas både för prototyper och produktionskod

Förutom att vara utmärkt för prototyper är Python också ett utmärkt och kraftfullt språk för stora produktionsapplikationer. Några av de största mjukvaruföretagen i världen använder Python mycket i en mängd olika applikationer och användningsfall.

6. Levereras med "Batterier ingår:" Python Standard Library

Allt som behövs för grundläggande operationer är inbyggt direkt i språket, men utöver det har Python standardbibliotek verktyg för att arbeta med filer, media, nätverk, datum- och tidsinformation och mycket mer. Detta gör att du kan utföra en mängd olika uppgifter utan att behöva leta efter tredjepartspaket.

7. Fantastiska tredjepartsbibliotek för finansiell analys

För finansproffs, Pandas med sin DataFrame och Serier objekt och Numpy med dess ndarray är arbetshästarna för finansiell analys med Python. I kombination med matplotlib och andra visualiseringsbibliotek har du fantastiska verktyg till ditt förfogande för att underlätta produktiviteten.

8. Python är gratis!

Python är utvecklad under en öppen källkodslicens vilket gör det gratis även för kommersiellt bruk.

Steg-för-steg handledning om hur du använder Python och Finance tillsammans

Vad som följer är en steg-för-steg handledning som visar hur man skapar en förenklad version av Monte Carlo-simuleringen som beskrivs i mitt tidigare blogginlägg, men använder Python istället för @RISK-plugin för Excel.

Monte Carlo-metoder förlitar sig på slumpmässigt urval för att få numeriska resultat. En sådan tillämpning är att dra slumpmässiga urval från en sannolikhetsfördelning som representerar osäkra potentiella framtida tillstånd i världen där variabler eller antaganden kan anta en rad värden.

Det är till hjälp att göra Monte Carlo-simuleringen på en förenklad DCF-värderingsmodell istället för de vanligare exemplen du ser som visar värdering av optioner eller andra derivat, eftersom vi för detta inte behöver någon matematik utöver grunderna för att beräkna de finansiella rapporterna och diskontering av kassaflöden, vilket gör att vi kan fokusera på Python-koncepten och verktygen. Observera dock att denna grundläggande handledningsmodell är avsedd att illustrera nyckelbegreppen och inte är användbar som den är för några praktiska ändamål. Jag kommer inte heller att beröra någon av de mer akademiska aspekterna av Monte Carlo-simuleringar.

Handledningen förutsätter att du är bekant med de grundläggande byggstenarna i programmering, såsom variabler och funktioner. Om inte, kan det vara bra att ta 10 minuter för att kontrollera nyckelbegreppen i till exempel denna introduktion.

Startpunkten och det önskade resultatet

Jag börjar med samma mycket förenklade DCF-värderingsmodell som används i Monte Carlos simuleringshandledning. Den har några nyckelposter från de tre finansiella rapporterna och tre markerade indataceller, som i Excel-versionen har punktuppskattningar som vi nu vill ersätta med sannolikhetsfördelningar för att börja utforska potentiella resultatintervall.

En tvåstegsmetod för att utveckla ett litet skript

Få det att fungera, gör det rätt, gör det snabbt - Kent Beck

Avsikten med denna handledning är att ge finansproffs som är nybörjare i Python en introduktion inte bara till hur ett användbart program kan se ut, utan också en introduktion till den iterativa processen du kan använda för att utveckla det. Den har därför två delar:

  1. Först utvecklar jag en fungerande prototyp med ett enkelt tillvägagångssätt som jag tycker är lätt att följa och inte helt olikt den process man skulle kunna använda för att starta det här projektet om man skulle börja om från början.
  2. Då, efter att ha utvecklat den fungerande prototypen, går jag igenom processen att refaktorera - ändra strukturen på koden utan att ändra dess funktionalitet. Du kanske vill stanna kvar för den delen - det är en mer elegant lösning än den första, och som en bonus är den cirka 75 gånger snabbare när det gäller körningstid.

1. Utveckla en fungerande prototyp

Konfigurera Jupyter Notebook

Jupyter-anteckningsboken är ett utmärkt verktyg för att arbeta interaktivt med Python. Det är en interaktiv Python-tolk med celler som kan innehålla kod, Markdown-text, bilder eller annan data. För den här handledningen använde jag Python Quant-plattformen, men jag kan också rekommendera Colaboratory by Google, som är gratis och körs i molnet. Väl där, välj helt enkelt "New Python 3 Notebook" i "Arkiv"-menyn, och du är redo att gå.

Efter att ha gjort det är nästa steg att importera de tredjepartspaket vi behöver för datamanipulation och visualiseringar, och tala om för programmet att vi vill se diagram inline i vår anteckningsbok, istället för i separata fönster:

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
%matplotlib inline

En anteckning innan vi börjar namnge våra första variabler. Som jag redan påpekat är läsbarhet en av Pythons styrkor. Språkdesign går långt för att stödja det, men alla som skriver kod är ansvariga för att göra den läsbar och begriplig, inte bara för andra utan också för sig själva. Som Eaglesons lag säger, "Varje egen kod som helst som du inte har tittat på på sex månader eller mer kan lika gärna ha skrivits av någon annan."

En bra tumregel är att namnge komponenterna i ditt program på ett sådant sätt att du minimerar behovet av separata kommentarer som förklarar vad ditt program gör.

Med det i åtanke, låt oss gå vidare.

Skapa bokslutet

Det finns många sätt att arbeta med befintliga kalkylbladsdata i Python. Vi skulle till exempel kunna läsa in ett ark i en Pandas DataFrame med en rad kod med hjälp av read_excel kommando. Om du vill ha en snävare integration och realtidslänk mellan ditt kalkylblad och Python-kod finns det både gratis och kommersiella alternativ för att tillhandahålla den funktionen.

Eftersom modellen här är väldigt enkel, och för att fokusera oss på Python-koncepten, kommer vi att återskapa den från grunden i vårt manus. I slutet av den första delen kommer jag att visa hur du kan exportera det vi har skapat till ett kalkylblad.

Som ett första steg mot att skapa en Python-representation av de finansiella rapporterna kommer vi att behöva en lämplig datastruktur. Det finns många att välja på, några inbyggda i Python, andra från olika bibliotek, eller så kan vi skapa våra egna. För nu, låt oss använda en serie från Pandas-biblioteket för att ta en titt på dess funktionalitet:

years = ['2018A', '2019B', '2020P', '2021P', '2022P', '2023P']
sales = pd.Series(index=years)
sales['2018A'] = 31.0  
sales

Denna ingång och dess motsvarande utgång visas nedan:

Med de tre första raderna har vi skapat en datastruktur med ett index som består av år (var och en markerad för att visa om det är Faktiskt, Budget eller Prognostiserat), ett startvärde (i miljoner euro, som i den ursprungliga DCF-modellen) och tomma (NaN, "Not a Number") celler för projektionerna. Den fjärde raden skriver ut en representation av data - i allmänhet kommer du att skriva in namnet på en variabel eller andra objekt i den interaktiva tolken för att ge dig en förnuftig representation av den.

Därefter deklarerar vi en variabel som representerar den beräknade årliga försäljningstillväxten. I detta skede är det en punktuppskattning, samma siffra som i vår ursprungliga DCF-modell. Vi vill först använda samma indata och bekräfta att vår Python-version presterar samma och ger samma resultat som Excel-versionen, innan vi tittar på att ersätta punktuppskattningar med sannolikhetsfördelningar. Med den här variabeln skapar vi en loop som beräknar försäljningen under varje år av prognoserna baserat på föregående år och tillväxttakten:

growth_rate = 0.1
for year in range(1, 6):
    sales[year] = sales[year - 1] * (1 + growth_rate)
    
sales

Vi har nu prognostiserat försäljning, istället för NaN:

Med samma tillvägagångssätt fortsätter vi genom de finansiella rapporterna, deklarerar variabler när vi behöver dem och utför de nödvändiga beräkningarna för att så småningom komma fram till fritt kassaflöde. När vi väl kommer dit kan vi kontrollera att det vi har stämmer överens med vad Excel-versionen av DCF-modellen säger.

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

Detta ger oss de fria kassaflödena:

Den ena raden ovan som kanske behöver en kommentar i detta skede är den andra tax_payment referens. Här tillämpar vi en liten funktion för att säkerställa att vi i scenarier där vinsten före skatt blir negativ inte får en positiv skattebetalning. Detta visar hur effektivt du kan tillämpa anpassade funktioner på alla celler i en Pandas Series eller DataFrame. Den faktiska funktionen som tillämpas är naturligtvis en förenkling. En mer realistisk modell för en större värderingsövning skulle ha en separat skattemodell som beräknar faktisk betald kontantskatt baserat på ett antal företagsspecifika faktorer.

Utföra DCF-värderingen

Efter att ha kommit fram till prognostiserade kassaflöden kan vi nu beräkna ett enkelt terminalvärde och diskontera alla kassaflöden tillbaka till nutid för att få DCF-resultatet. Följande kod introducerar indexering och slicing, vilket gör att vi kan komma åt ett eller flera element i en datastruktur, till exempel Pandas Series-objektet.

Vi kommer åt element genom att skriva hakparenteser direkt efter namnet på strukturen. Enkel indexering ger åtkomst till element genom deras position, med början på noll, vilket betyder att free_cash_flow[1] skulle ge oss det andra elementet. [-1] är en förkortning för att komma åt det sista elementet (det senaste årets kassaflöde används för att beräkna terminalvärdet), och att använda ett kolon ger oss en del, vilket betyder att [1:] ger oss alla element utom det första, eftersom vi inte vill inkludera det historiska året 2018A i vår DCF-värdering.

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

Det avslutar den första delen av vår prototyp - vi har nu en fungerande DCF-modell, om än en mycket rudimentär sådan, i Python.

Exportera data

Innan du går vidare till den faktiska Monte Carlo-simuleringen kan detta vara ett bra tillfälle att nämna de exportmöjligheter som finns tillgängliga i Pandas-paketet. Om du har ett Pandas DataFrame-objekt kan du skriva det till en Excel-fil med en rad med hjälp av to_excel metod. Det finns liknande funktioner för att exportera till mer än ett dussin andra format och destinationer också.

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

Skapa sannolikhetsfördelningar för vår Monte Carlo-simulering

Nu är vi redo att ta oss an nästa utmaning:att ersätta några av punktskattningsingångarna med sannolikhetsfördelningar. Även om stegen fram till denna punkt kan ha verkat något besvärliga jämfört med att bygga samma modell i Excel, kommer dessa nästa rader att ge dig en glimt av hur kraftfull Python kan vara.

Vårt första steg är att bestämma hur många iterationer vi vill köra i simuleringen. Att använda 1 000 som utgångspunkt ger en balans mellan att få tillräckligt med datapunkter för att få vettiga utdatadiagram, kontra att simuleringen avslutas inom en vettig tidsram. Därefter genererar vi de faktiska distributionerna. För enkelhetens skull genererade jag tre normaldistributioner här, men NumPy-biblioteket har ett stort antal distributioner att välja mellan, och det finns andra ställen att leta efter också, inklusive Python-standardbiblioteket. Efter att ha beslutat vilken fördelning som ska användas måste vi specificera de parametrar som krävs för att beskriva deras form, såsom medelvärde och standardavvikelse, och antalet önskade utfall.

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

Här skulle man kunna argumentera för att EBITDA inte ska vara en separat slumpmässig variabel oberoende av försäljningen utan istället korrelera med försäljningen till viss del. Jag håller med om detta och tillägger att det bör drivas av en gedigen förståelse för dynamiken i kostnadsstrukturen (variabla, semivariabla och fasta kostnader) och de viktigaste kostnadsdrivkrafterna (av vilka några kan ha sina egna sannolikhetsfördelningar, som till exempel ingående råvarupriser), men jag lämnar den komplexiteten åt sidan här för utrymmets och tydlighetens skull.

Ju mindre data du har för att informera om ditt val av distribution och parametrar, desto mer kommer du att behöva förlita dig på resultatet av dina olika arbetsflöden för due diligence, kombinerat med erfarenhet, för att bilda en konsensussyn om olika möjliga scenarier. I det här exemplet, med kassaflödesprognoser, kommer det att finnas en stor subjektiv komponent, vilket gör att det blir viktigt att visualisera sannolikhetsfördelningarna. Här kan vi få en grundläggande visualisering, som visar försäljningstillväxtfördelningen, med endast två korta rader kod. På så sätt kan vi snabbt se vilken distribution som helst som bäst återspeglar lagets samlade syn.

Nu har vi alla byggstenar vi behöver för att köra simuleringen, men de är inte i ett bekvämt format för att köra simuleringen. Här är samma kod som vi har arbetat med hittills men alla samlade i en cell och omarrangerade till en funktion för bekvämlighet:

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

Vi kan nu köra hela simuleringen och plotta utdatafördelningen, som kommer att vara det diskonterade kassaflödesvärdet för detta företag i var och en av de 1 000 iterationerna, med följande kod. %time kommandot är inte Python-kod utan en anteckningsbokstavning som mäter tiden för att köra något (du kan istället använda Python-funktionen från standardbiblioteket). Det beror på vilken dator du kör den på, men den här versionen behöver 1-2 sekunder för att köra de 1 000 iterationerna och visualisera resultatet.

%time plt.hist(run_mcs(), bins=20, color='r')
plt.show()

2. Förfina prototypen

Den lurande misstanken om att något skulle kunna förenklas är världens rikaste källa till givande utmaningar. - Edsger Dijkstra

Refaktorering hänvisar till processen att skriva om befintlig kod för att förbättra dess struktur utan att ändra dess funktionalitet, och det kan vara ett av de roligaste och mest givande delarna av kodning. Det kan finnas flera anledningar till att göra detta. Det kan vara att:

  1. Ordna de olika delarna på ett mer förnuftigt sätt.
  2. Byt namn på variabler och funktioner för att göra deras syfte och funktion tydligare.
  3. Tillåt och förbered dig för framtida funktioner.
  4. Förbättra exekveringshastigheten, minnesfotavtrycket eller annan resursanvändning.

För att visa hur ett steg i den processen kan se ut, rensade jag upp prototypen som vi just gick igenom genom att samla alla initiala variabler på ett ställe, snarare än utspridda som i prototypskriptet, och optimerade dess exekveringshastighet genom en process som heter vektorisering .

Genom att använda NumPy-matriser kan du uttrycka många typer av databearbetningsuppgifter som kortfattade matrisuttryck som annars kan kräva skrivslingor. Denna praxis att ersätta explicita loopar med array-uttryck kallas vanligtvis för vektorisering. Wes McKinney

Det ser nu renare och lättare att förstå:

# 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

Företagsfinansiering
  1. Bokföring
  2. Affärsstrategi
  3. Företag
  4. Kundrelationshantering
  5. finansiera
  6. Lagerhantering
  7. Privatekonomi
  8. investera
  9. Företagsfinansiering
  10. budget
  11. Besparingar
  12. försäkring
  13. skuld
  14. avgå