Python et Finance - Boostez vos feuilles de calcul
Publié: 2022-03-11Résumé
Pourquoi Python est-il un excellent langage de programmation pour les professionnels de la finance ?
- Python est un langage de programmation de haut niveau, ce qui signifie qu'il résume et gère de nombreux aspects techniques de la programmation, tels que la gestion de la mémoire, qui doivent être explicitement gérés dans d'autres langages. Cela rend Python facile à utiliser pour ceux qui n'ont pas de connaissances techniques.
- Parce que la langue a été conçue dans un souci de lisibilité et de facilité d'utilisation, c'est l'une des langues les plus faciles à apprendre. Le code Python est concis et proche de l'anglais simple.
- Python est idéal pour le prototypage et le développement rapide et itératif. Ses outils d'interprétation interactifs fournissent des environnements dans lesquels vous pouvez écrire et exécuter chaque ligne de code de manière isolée et voir les résultats immédiatement.
- Dans le même temps, Python est robuste et performant, ce qui en fait un choix viable également pour les systèmes centraux et les applications plus importantes.
- En plus de sa grande bibliothèque standard d'outils utiles, Python dispose d'excellentes bibliothèques tierces pour l'analyse financière et l'informatique, telles que les bibliothèques Pandas et NumPy utilisées dans ce didacticiel.
Quels sont les cas d'utilisation pour implémenter Python et la finance ensemble ?
- Les scripts Python peuvent être utilisés pour automatiser les tâches et les flux de travail répétitifs, ce qui permet de gagner du temps et de réduire le risque d'erreurs manuelles.
- Les scripts permettent aux utilisateurs d'extraire facilement des données de feuilles de calcul, de bases de données et d'API, ou même de récupérer des données Web, qui peuvent ensuite être traitées et analysées à l'aide de puissants outils statistiques et analytiques.
- Divers plugins pour Excel permettent aux utilisateurs de créer des liens bidirectionnels en temps réel entre vos feuilles de calcul et le code Python.
- Python permet de nouveaux types d'analyse, tels que les simulations de Monte Carlo, qui ne sont pas facilement disponibles dans les feuilles de calcul standard.
- Le trading algorithmique n'est plus le domaine exclusif des hedge funds et des grandes banques d'investissement. Avec Python, vous pouvez développer, tester et déployer vos propres stratégies de trading en peu de temps et à moindre coût.
Pour les professions qui s'appuient depuis longtemps sur le chalutage à travers des feuilles de calcul, Python est particulièrement précieux. Citigroup, une banque américaine, a mis en place un cours accéléré sur Python pour ses analystes stagiaires. - L'économiste
Les professionnels de la finance ont depuis longtemps accès à VBA (Visual Basic pour Applications) dans Excel pour créer des fonctionnalités personnalisées et automatiser les workflows. Avec l'émergence ces dernières années de Google Sheets en tant que concurrent sérieux dans l'espace des tableurs, Google Apps Script offre désormais un choix supplémentaire.
Cependant, je voudrais attirer l'attention sur une troisième option, le langage de programmation Python, qui est devenu extrêmement populaire dans un certain nombre de domaines.
Dans cet article, je vais donner quelques exemples de ce que vous pouvez accomplir avec Python, en commençant par un aperçu du langage lui-même et pourquoi il est devenu si populaire dans une si grande variété de domaines, allant du développement Web, de l'apprentissage automatique, de la finance, la science et l'éducation, pour n'en nommer que quelques-uns. La seconde moitié consistera ensuite en un didacticiel pas à pas.
Le but de ma rédaction est de vous aider à décider si Python semble suffisamment intrigant pour que vous envisagiez de l'ajouter à votre boîte à outils financière. Si vous franchissez le pas, de nombreuses applications, cours, vidéos, articles, livres et articles de blog sont disponibles pour apprendre la langue. À la fin de l'article, j'ai énuméré quelques ressources qui m'ont aidé en cours de route.
Cas d'utilisation : exemples de ce pour quoi j'ai utilisé Python
Mon introduction à la programmation a été l'apprentissage du BASIC sur un Oric 1 au milieu des années 1980. À l'époque, le BASIC était le langage de débutant le plus courant. Les autres langages avec lesquels j'ai essayé de la fin des années 80 jusqu'au milieu des années 90 étaient le Pascal et le C, mais je ne les ai jamais utilisés à titre professionnel et je ne m'attendais pas à avoir besoin ou à utiliser des compétences en programmation. À ma connaissance à l'époque, à la fin des années 90, la finance et la programmation étaient des domaines très différents, lorsque j'ai choisi de me lancer dans une carrière en finance.
Avance rapide jusqu'en 2012, et je cherchais à reprendre la programmation comme passe-temps, alors j'ai commencé à rechercher les langages disponibles à l'époque. Il s'est avéré qu'il s'était passé pas mal de choses, et quand je suis tombé sur Python, j'étais accro, pour de nombreuses raisons que je vais exposer dans la section suivante. Depuis lors, j'ai utilisé Python pour un large éventail de tâches, des petits scripts aux projets plus importants, à la fois personnellement et professionnellement. Beaucoup, mais pas tous, ont impliqué des feuilles de calcul, l'établi de nombreux professionnels de la finance.
Voici quelques exemples de la façon dont les feuilles de calcul et Python peuvent aller ensemble :
1. Suivi de centaines d'activités au fil du temps dans une configuration PMO d'intégration M&A
Je travaille avec tous les aspects des transactions M&A, non seulement l'exécution, mais aussi l'intégration. Dans un cas récent, l'équipe du PMO a opté pour une approche hybride de gestion de programme et de projet, utilisant la planification en cascade et des diagrammes de Gantt pour les plans de haut niveau pour chacun des douze flux de travail d'intégration, en plus d'un tableau Kanban pour suivre les centaines d'activités en cours. à tout moment, dans le premier plan de 100 jours et au-delà. L'outil Kanban qui a été choisi, MeisterTask, possède un certain nombre de fonctionnalités de statistiques et de reporting, mais nos besoins allaient au-delà en termes d'analyse et de présentation, ce qui nécessitait une solution sur mesure. Voici le workflow que j'ai automatisé avec Python :
- Enregistrez le statut de l'ensemble du tableau chaque semaine sous forme de fichier CSV.
- Lire tous les fichiers CSV historiques dans un Pandas DataFrame.
- Triez, filtrez, regroupez et manipulez les données dans des formats convenus sur la façon dont nous voulons suivre les progrès (par statut d'activité, flux de travail, etc.).
- Écrivez la sortie dans un fichier Excel avec les données de chaque analyse dans sa propre feuille, formatée de telle sorte qu'elle puisse être simplement copiée et collée dans des graphiques think-cell.
- Créer des tableaux et des graphiques pour le dossier de rapport pour la réunion mensuelle du comité de pilotage.
L'élaboration du script a nécessité un investissement initial de quelques heures, mais désormais, la mise à jour du pack de reporting pour les réunions du comité de pilotage ou les analyses ad hoc ne prend que quelques minutes. Littéralement, environ 30 secondes pour aller dans le bon dossier et exécuter le script avec une commande en une ligne, puis quelques minutes pour copier-coller la sortie dans le jeu de diapositives. Avec environ 500 activités (cartes) réparties sur douze flux de travail déjà environ un mois après leur exécution, un suivi hebdomadaire de leur évolution, dans un calendrier de programme de deux ans, vous vous retrouvez rapidement à gérer des milliers, voire des dizaines de milliers de points de données sur des dizaines de fichiers. Sans automatisation, on parle ici de tâches très fastidieuses.
Le compromis « valeur temporelle de l'argent » entre le simple fait de poursuivre les choses ou l'ajout d'une charge de travail initiale supplémentaire en mettant en place l'automatisation est un thème courant dans la finance. J'ai pris une décision similaire avec la première étape de ce processus, en exportant les données sous forme de fichiers CSV. MeisterTask, comme de nombreuses applications Web modernes, possède une API, qui peut être connectée à votre application Python, mais le temps passé à la configurer dépasserait de loin le gain de temps pour notre cas d'utilisation ici.
Ainsi, comme vous le voyez, la solution optimale consiste souvent à automatiser certaines étapes d'un flux de travail et à en garder d'autres manuelles.
2. Analyser les statistiques des prix des maisons à l'aide de Web Scraping, de l'API Google Maps et d'Excel
Un autre exemple est quelque chose que j'ai fait par intérêt personnel mais je veux le souligner car il contient d'autres éléments intéressants de l'utilité de Python :
- Extrayez les données des annonces immobilières, y compris l'adresse, la taille, le nombre de pièces, le prix demandé et d'autres caractéristiques, pour une zone donnée ; quelques centaines à peut-être un millier de lignes au total.
- Enregistrez dans une structure de données Python.
- Connectez-vous à l'API Google Maps et, pour chaque annonce, récupérez la distance entre la propriété et les points de repère clés tels que la mer, le centre-ville, la gare la plus proche, l'aéroport le plus proche, etc.
- Exportez les données vers un fichier Excel.
- Utilisez les fonctionnalités Excel standard pour exécuter des régressions, calculer des statistiques et créer des graphiques sur des mesures standard telles que le prix au mètre carré et la distance aux points de repère.
Les résultats ici pourraient être combinés avec vos propres pondérations personnelles en termes de préférences et de limites financières lors de la recherche d'un bien immobilier.
Ce ne sont que deux exemples, axés sur l'automatisation du travail lié aux feuilles de calcul et l'ajout de fonctionnalités, mais les opportunités avec Python sont presque infinies. Dans la section suivante, je décrirai les raisons pour lesquelles il est devenu si populaire, avant de passer à un didacticiel de simulation Monte Carlo étape par étape en Python.
Pourquoi Python est un excellent choix pour les professionnels de la finance
Le langage de programmation Python existe depuis 1990, mais ce n'est que ces dernières années que sa popularité a explosé.
Il y a plusieurs raisons à cela, examinons chacune à son tour.
1. Python est un langage de programmation de haut niveau
Un langage de programmation de haut niveau est un langage qui fait abstraction de nombreux détails du fonctionnement interne de l'ordinateur. Un bon exemple est la gestion de la mémoire. Les langages de programmation de niveau inférieur nécessitent une compréhension détaillée de la complexité de la disposition, de l'allocation et de la libération de la mémoire de l'ordinateur, en plus du temps passé et des lignes de code nécessaires pour gérer les tâches. Python fait abstraction et gère automatiquement bon nombre de ces détails, vous laissant vous concentrer sur ce que vous voulez accomplir.
2. C'est concis
Parce que Python est un langage de programmation de haut niveau, le code est plus concis et presque entièrement axé sur la logique métier de ce que vous voulez réaliser, plutôt que sur les détails techniques de mise en œuvre. Les choix de conception du langage y contribuent : par exemple, Python ne nécessite pas l'utilisation d'accolades ou de points-virgules pour délimiter les fonctions, les boucles et les lignes comme le font de nombreux autres langages, ce qui le rend plus concis et, comme certains le prétendent, améliore lisibilité.
3. Facile à apprendre et à comprendre
Une observation qui a influencé les choix de conception de langage en Python est que les programmes sont lus plus souvent qu'ils ne sont écrits. Python excelle ici car son code ressemble beaucoup à l'anglais simple, surtout si vous nommez les différents composants de votre script ou programme de manière sensée.
4. Convient pour un développement rapide et itératif
Les essais et erreurs éclairés surpassent la planification des intellects sans faille. -David Kelley
Python est idéal pour le prototypage et le développement rapide et itératif (et, oui, par essais et erreurs) car les outils d'interprétation interactifs tels que le shell Python, IPython et les cahiers Jupyter sont au cœur de la chaîne d'outils Python. Dans ces environnements interactifs, vous pouvez écrire et exécuter chaque ligne de code de manière isolée et voir les résultats (ou un message d'erreur utile) immédiatement. D'autres langages ont cela aussi, mais dans la plupart des cas pas au même degré que Python.
5. Peut être utilisé à la fois pour le prototypage et le code de production
En plus d'être idéal pour le prototypage, Python est également un langage excellent et puissant pour les grandes applications de production. Certaines des plus grandes sociétés de logiciels au monde font un usage intensif de Python dans une variété d'applications et de cas d'utilisation.
6. Livré avec "Piles incluses :" la bibliothèque standard Python
Tout le nécessaire pour les opérations de base est intégré directement dans le langage, mais en plus de cela, la bibliothèque standard Python dispose d'outils pour travailler avec des fichiers, des médias, des réseaux, des informations de date et d'heure, et bien plus encore. Cela vous permet d'accomplir une grande variété de tâches sans avoir à rechercher des packages tiers.
7. Excellentes bibliothèques tierces pour l'analyse financière
Pour les professionnels de la finance, Pandas avec ses objets DataFrame et Series , et Numpy avec son ndarray sont les bêtes de somme de l'analyse financière avec Python. Combiné avec matplotlib et d'autres bibliothèques de visualisation, vous disposez d'excellents outils pour améliorer la productivité.
8. Python est gratuit !
Python est développé sous une licence open source, ce qui le rend également gratuit pour un usage commercial.
Tutoriel étape par étape sur l'utilisation conjointe de Python et de Finance
Ce qui suit est un didacticiel étape par étape montrant comment créer une version simplifiée de la simulation de Monte Carlo décrite dans mon article de blog précédent, mais en utilisant Python au lieu du plugin @RISK pour Excel.
Les méthodes de Monte Carlo reposent sur un échantillonnage aléatoire pour obtenir des résultats numériques. Une de ces applications consiste à tirer des échantillons aléatoires à partir d'une distribution de probabilité représentant des états futurs potentiels incertains du monde où des variables ou des hypothèses peuvent prendre une plage de valeurs.
Il est utile de faire la simulation de Monte Carlo sur un modèle d'évaluation DCF simplifié au lieu des exemples les plus courants que vous voyez montrant l'évaluation d'options ou d'autres dérivés, car pour cela, nous n'avons pas besoin de calculs au-delà des bases du calcul des états financiers et actualiser les flux de trésorerie, ce qui nous permet de nous concentrer sur les concepts et outils Python. Veuillez noter cependant que ce modèle de didacticiel de base est destiné à illustrer les concepts clés et n'est pas utile tel quel à des fins pratiques. Je n'aborderai pas non plus les aspects plus académiques des simulations de Monte Carlo.
Le didacticiel suppose que vous êtes familiarisé avec les blocs de construction de base de la programmation, tels que les variables et les fonctions. Si ce n'est pas le cas, il peut être utile de prendre 10 minutes pour vérifier les concepts clés, par exemple dans cette introduction.
Le point de départ et le résultat souhaité
Je commence avec le même modèle d'évaluation DCF très simplifié utilisé dans le tutoriel de simulation de Monte Carlo. Il contient des éléments clés des trois états financiers et trois cellules d'entrée en surbrillance qui, dans la version Excel, contiennent des estimations ponctuelles que nous souhaitons maintenant remplacer par des distributions de probabilité pour commencer à explorer les plages potentielles de résultats.
Une approche en deux étapes pour développer un petit script
Faites-le fonctionner, faites-le bien, faites-le vite - Kent Beck
L'intention de ce tutoriel est de donner aux professionnels de la finance qui découvrent Python une introduction non seulement à ce à quoi un programme utile pourrait ressembler, mais aussi une introduction au processus itératif que vous pouvez utiliser pour le développer. Il comporte donc deux parties :
- Tout d'abord, je développe un prototype fonctionnel en utilisant une approche simple qui, je pense, est facile à suivre et pas complètement différente du processus que l'on pourrait utiliser pour démarrer ce projet si vous deviez partir de zéro.
- Ensuite, après avoir développé le prototype fonctionnel, je parcoure le processus de refactoring - en modifiant la structure du code sans changer sa fonctionnalité. Vous voudrez peut-être rester pour cette partie - c'est une solution plus élégante que la première et, en prime, elle est environ 75 fois plus rapide en termes de temps d'exécution.
1. Développer un prototype de travail
Configuration du bloc-notes Jupyter
Le notebook Jupyter est un excellent outil pour travailler avec Python de manière interactive. Il s'agit d'un interpréteur Python interactif avec des cellules pouvant contenir du code, du texte Markdown, des images ou d'autres données. Pour ce tutoriel, j'ai utilisé la plate-forme Python Quant, mais je peux également recommander Colaboratory de Google, qui est gratuit et fonctionne dans le cloud. Une fois là-bas, sélectionnez simplement "New Python 3 Notebook" dans le menu "File", et vous êtes prêt à partir.
Cela fait, l'étape suivante consiste à importer les packages tiers dont nous avons besoin pour la manipulation et la visualisation des données, et à indiquer au programme que nous voulons voir les graphiques en ligne dans notre bloc-notes, plutôt que dans des fenêtres séparées :
import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline
Une note avant de commencer à nommer nos premières variables. Comme je l'ai déjà souligné, la lisibilité est l'une des forces de Python. La conception du langage contribue grandement à cela, mais chaque auteur de code est responsable de le rendre lisible et compréhensible, non seulement pour les autres mais aussi pour lui-même. Comme le stipule la loi d'Eagleson, "tout code qui vous est propre et que vous n'avez pas consulté depuis six mois ou plus pourrait tout aussi bien avoir été écrit par quelqu'un d'autre".
Une bonne règle empirique consiste à nommer les composants de votre programme de manière à minimiser le besoin de commentaires séparés expliquant ce que fait votre programme.

Dans cet esprit, passons à autre chose.
Création des états financiers
Il existe de nombreuses façons de travailler avec des données de feuille de calcul existantes en Python. Nous pourrions, par exemple, lire une feuille dans un Pandas DataFrame avec une ligne de code en utilisant la commande read_excel
. Si vous souhaitez une intégration plus étroite et un lien en temps réel entre votre feuille de calcul et le code Python, des options gratuites et commerciales sont disponibles pour fournir cette fonctionnalité.
Puisque le modèle ici est très simple, et pour nous concentrer sur les concepts Python, nous allons le recréer à partir de zéro dans notre script. À la fin de la première partie, je montrerai comment vous pouvez exporter ce que nous avons créé vers une feuille de calcul.
Comme première étape vers la création d'une représentation Python des états financiers, nous aurons besoin d'une structure de données appropriée. Il y en a beaucoup parmi lesquels choisir, certains intégrés à Python, d'autres provenant de diverses bibliothèques, ou nous pouvons créer les nôtres. Pour l'instant, utilisons une série de la bibliothèque Pandas pour jeter un œil à ses fonctionnalités :
years = ['2018A', '2019B', '2020P', '2021P', '2022P', '2023P'] sales = pd.Series(index=years) sales['2018A'] = 31.0 sales
Cette entrée et sa sortie correspondante sont illustrées ci-dessous :
Avec les trois premières lignes, nous avons créé une structure de données avec un index composé d'années (chacune marquée pour indiquer si elle est réelle, budgétaire ou projetée), une valeur de départ (en millions d'euros, comme dans le modèle DCF original), et cellules vides (NaN, "Pas un nombre") pour les projections. La quatrième ligne imprime une représentation des données - en général, taper le nom d'une variable ou d'autres objets dans l'interpréteur interactif vous en donnera généralement une représentation sensible.
Ensuite, nous déclarons une variable pour représenter la croissance annuelle prévue des ventes. A ce stade, il s'agit d'une estimation ponctuelle, le même chiffre que dans notre modèle DCF original. Nous voulons d'abord utiliser ces mêmes entrées et confirmer que notre version Python fonctionne de la même manière et donne le même résultat que la version Excel, avant d'envisager de remplacer les estimations ponctuelles par des distributions de probabilité. À l'aide de cette variable, nous créons une boucle qui calcule les ventes de chaque année des projections en fonction de l'année précédente et du taux de croissance :
growth_rate = 0.1 for year in range(1, 6): sales[year] = sales[year - 1] * (1 + growth_rate) sales
Nous avons maintenant des ventes projetées, au lieu de NaN :
En utilisant la même approche, nous continuons à travers les états financiers, en déclarant les variables au fur et à mesure que nous en avons besoin et en effectuant les calculs nécessaires pour finalement arriver au flux de trésorerie disponible. Une fois sur place, nous pouvons vérifier que ce que nous avons correspond à ce que dit la version Excel du modèle DCF.
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
Cela nous donne les flux de trésorerie disponibles :
La seule ligne ci-dessus qui nécessite peut-être un commentaire à ce stade est la deuxième référence tax_payment
. Ici, nous appliquons une petite fonction pour nous assurer que dans les scénarios où le bénéfice avant impôt devient négatif, nous n'aurons pas alors un paiement d'impôt positif. Cela montre à quel point vous pouvez appliquer efficacement des fonctions personnalisées à toutes les cellules d'une série Pandas ou d'un DataFrame. La fonction réelle appliquée est, bien sûr, une simplification. Un modèle plus réaliste pour un exercice d'évaluation plus important aurait un modèle fiscal distinct qui calcule les impôts en espèces réels payés en fonction d'un certain nombre de facteurs spécifiques à l'entreprise.
Réalisation de l'évaluation DCF
Une fois arrivés aux flux de trésorerie projetés, nous pouvons maintenant calculer une valeur terminale simple et actualiser tous les flux de trésorerie jusqu'au présent pour obtenir le résultat DCF. Le code suivant introduit l'indexation et le découpage, ce qui nous permet d'accéder à un ou plusieurs éléments dans une structure de données, comme l'objet Pandas Series.
On accède aux éléments en écrivant des crochets directement après le nom de la structure. L'indexation simple accède aux éléments par leur position, en commençant par zéro, ce qui signifie que free_cash_flow[1]
nous donnerait le deuxième élément. [-1]
est un raccourci pour accéder au dernier élément (le flux de trésorerie de l'année dernière est utilisé pour calculer la valeur terminale), et l'utilisation de deux-points nous donne une tranche, ce qui signifie que [1:]
nous donne tous les éléments sauf le premier, puisque nous ne voulons pas inclure l'année historique 2018A
dans notre valorisation DCF.
cost_of_capital = 0.12 terminal_growth = 0.02 terminal_value = ((free_cash_flow[-1] * (1 + terminal_growth)) / (cost_of_capital - terminal_growth)) discount_factors = [(1 / (1 + cost_of_capital)) ** i for i in range (1,6)] dcf_value = (sum(free_cash_flow[1:] * discount_factors) + terminal_value * discount_factors[-1]) dcf_value
Cela conclut la première partie de notre prototype - nous avons maintenant un modèle DCF fonctionnel, bien que très rudimentaire, en Python.
Exportation des données
Avant de passer à la simulation de Monte Carlo proprement dite, il est peut-être temps de mentionner les capacités d'exportation disponibles dans le package Pandas. Si vous avez un objet Pandas DataFrame, vous pouvez l'écrire dans un fichier Excel avec une ligne en utilisant la méthode to_excel
. Il existe également une fonctionnalité similaire pour exporter vers plus d'une douzaine d'autres formats et destinations.
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
Création de distributions de probabilité pour notre simulation de Monte Carlo
Nous sommes maintenant prêts à relever le défi suivant : remplacer certaines des entrées d'estimation ponctuelle par des distributions de probabilité. Bien que les étapes jusqu'à ce point aient pu sembler quelque peu lourdes par rapport à la construction du même modèle dans Excel, ces quelques lignes vous donneront un aperçu de la puissance de Python.
Notre première étape consiste à décider du nombre d'itérations que nous voulons exécuter dans la simulation. L'utilisation de 1 000 comme point de départ établit un équilibre entre l'obtention de suffisamment de points de données pour obtenir des tracés de sortie sensibles et la fin de la simulation dans un délai raisonnable. Ensuite, nous générons les distributions réelles. Par souci de simplicité, j'ai généré ici trois distributions normales, mais la bibliothèque NumPy propose un grand nombre de distributions, et il existe également d'autres endroits où chercher, y compris la bibliothèque standard Python. Après avoir décidé quelle distribution utiliser, nous devons spécifier les paramètres requis pour décrire leur forme, tels que la moyenne et l'écart type, et le nombre de résultats souhaités.
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()
Ici, vous pourriez soutenir que l'EBITDA ne devrait pas être une variable aléatoire distincte indépendante des ventes, mais plutôt corrélée avec les ventes dans une certaine mesure. Je suis d'accord avec cela et j'ajoute qu'il devrait être motivé par une solide compréhension de la dynamique de la structure des coûts (coûts variables, semi-variables et fixes) et des principaux facteurs de coût (dont certains peuvent avoir leurs propres distributions de probabilité, comme par exemple les prix des matières premières), mais je laisse ces complexités de côté ici par souci d'espace et de clarté.
Moins vous disposez de données pour éclairer votre choix de distribution et de paramètres, plus vous devrez vous fier aux résultats de vos divers flux de travail de diligence raisonnable, combinés à votre expérience, pour former un consensus sur les gammes de scénarios probables. Dans cet exemple, avec des projections de flux de trésorerie, il y aura une grande composante subjective, ce qui signifie que la visualisation des distributions de probabilité devient importante. Ici, nous pouvons obtenir une visualisation de base, montrant la distribution de la croissance des ventes, avec seulement deux courtes lignes de code. De cette façon, nous pouvons visualiser rapidement n'importe quelle distribution pour voir celle qui reflète le mieux la vision collective de l'équipe.
Nous avons maintenant tous les blocs de construction dont nous avons besoin pour exécuter la simulation, mais ils ne sont pas dans un format pratique pour exécuter la simulation. Voici le même code avec lequel nous avons travaillé jusqu'à présent, mais tous rassemblés dans une cellule et réorganisés en une fonction pour plus de commodité :
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
Nous pouvons maintenant exécuter toute la simulation et tracer la distribution de la production, qui sera la valeur actualisée des flux de trésorerie de cette entreprise à chacune des 1 000 itérations, avec le code suivant. La commande %time
n'est pas du code Python mais un raccourci de bloc-notes qui mesure le temps nécessaire pour exécuter quelque chose (vous pouvez à la place utiliser la fonction Python de la bibliothèque standard). Cela dépend de l'ordinateur sur lequel vous l'exécutez, mais cette version a besoin de 1 à 2 secondes pour exécuter les 1 000 itérations et visualiser le résultat.
%time plt.hist(run_mcs(), bins=20, color='r') plt.show()
2. Affiner le prototype
Le soupçon qui se cache que quelque chose pourrait être simplifié est la source la plus riche au monde de défis enrichissants. - Edsger Dijkstra
La refactorisation fait référence au processus de réécriture du code existant pour améliorer sa structure sans modifier sa fonctionnalité, et cela peut être l'un des éléments les plus amusants et les plus gratifiants du codage. Il peut y avoir plusieurs raisons de le faire. Il peut s'agir de :
- Organisez les différentes parties de manière plus sensée.
- Renommez les variables et les fonctions pour clarifier leur objectif et leur fonctionnement.
- Autoriser et préparer les futures fonctionnalités.
- Améliorez la vitesse d'exécution, l'empreinte mémoire ou l'utilisation d'autres ressources.
Pour montrer à quoi pourrait ressembler une étape de ce processus, j'ai nettoyé le prototype que nous venons de parcourir en rassemblant toutes les variables initiales en un seul endroit, plutôt que dispersées comme dans le script du prototype, et j'ai optimisé sa vitesse d'exécution grâce à un processus appelé vectorisation .
L'utilisation de tableaux NumPy vous permet d'exprimer de nombreux types de tâches de traitement de données sous forme d'expressions de tableau concises qui pourraient autrement nécessiter des boucles d'écriture. Cette pratique consistant à remplacer les boucles explicites par des expressions de tableau est communément appelée vectorisation. Wes McKinney
Il semble maintenant plus propre et plus facile à comprendre :
# 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
La principale différence que vous remarquerez entre cette version et la précédente est l'absence de la boucle for i in range(iterations)
. En utilisant l'opération de tableau de NumPy, cette version s'exécute en 18 millisecondes contre 1,35 seconde pour la version prototype - environ 75 fois plus rapide.
%time plt.hist(run_mcs(), bins=20, density=True, color="r") plt.show()
Je suis sûr qu'une optimisation supplémentaire est possible, car j'ai assemblé à la fois le prototype et la version raffinée en peu de temps uniquement dans le cadre de ce didacticiel.
Aller plus loin
Ce didacticiel a montré certaines des fonctionnalités puissantes de Python, et si vous deviez le développer davantage, les opportunités sont presque infinies. Vous pourriez par exemple :
- Extrayez ou téléchargez des statistiques pertinentes sur l'entreprise ou le secteur à partir de pages Web ou d'autres sources de données, pour vous aider à éclairer votre choix d'hypothèses et de distributions de probabilité.
- Utilisez Python dans des applications de finance quantitative, comme dans un algorithme de trading automatisé basé sur des facteurs fondamentaux et/ou macroéconomiques.
- Créez des capacités d'exportation qui génèrent une sortie dans un format de feuille de calcul et/ou de présentation, à utiliser dans le cadre de votre processus interne d'examen et d'approbation des transactions, ou pour des présentations externes.
Je n'ai même pas abordé ce que vous pourriez également faire avec les diverses applications Web, de science des données et d'apprentissage automatique qui ont contribué au succès de Python.
En résumé : un langage utile pour votre boîte à outils financière
Cet article a donné une introduction au langage de programmation Python, a énuméré certaines des raisons pour lesquelles il est devenu si populaire dans la finance et a montré comment créer un petit script Python. Dans un didacticiel étape par étape, j'ai expliqué comment Python peut être utilisé pour le prototypage itératif, l'analyse financière interactive et le code d'application pour les modèles d'évaluation, les programmes de trading algorithmique, etc.
Pour moi, en fin de compte, la principale caractéristique de la technologie Python est qu'il est tout simplement amusant de travailler avec ! Si vous aimez résoudre des problèmes, construire des choses et rendre les flux de travail plus efficaces, je vous encourage à l'essayer. J'aimerais savoir ce que vous en avez fait ou aimeriez en faire.
Ressources recommandées pour les professionnels de la finance pour apprendre Python
- Les livres d'O'Reilly. Je peux notamment recommander :
- Python for Finance by Yves Hilpisch
- Learning Python by Mark Lutz
- Fluent Python by Luciano Ramalho
- The Python Quants
- PyCon talks on YouTube
- Udemy