Python y finanzas: potencia tus hojas de cálculo
Publicado: 2022-03-11Resumen ejecutivo
¿Por qué Python es un gran lenguaje de programación para que aprendan los profesionales de las finanzas?
- Python es un lenguaje de programación de alto nivel, lo que significa que abstrae y maneja muchos de los aspectos técnicos de la programación, como la gestión de la memoria, que deben manejarse explícitamente en otros lenguajes. Esto hace que Python sea fácil de usar para aquellos sin conocimientos técnicos.
- Debido a que el lenguaje se diseñó teniendo en cuenta la legibilidad y la facilidad de uso, es uno de los lenguajes más fáciles de aprender. El código de Python es conciso y cercano al inglés simple.
- Python es ideal para la creación de prototipos y el desarrollo rápido e iterativo. Sus herramientas de interpretación interactivas proporcionan entornos en los que puede escribir y ejecutar cada línea de código de forma aislada y ver los resultados de forma inmediata.
- Al mismo tiempo, Python es robusto y eficaz, lo que lo convierte en una opción viable también para sistemas centrales y aplicaciones más grandes.
- Además de su gran biblioteca estándar de herramientas útiles, Python tiene excelentes bibliotecas de terceros para el análisis financiero y la computación, como las bibliotecas Pandas y NumPy que se usan en este tutorial.
¿Cuáles son algunos casos de uso para implementar Python y finanzas juntos?
- Los scripts de Python se pueden usar para automatizar tareas y flujos de trabajo repetitivos, lo que ahorra tiempo y reduce el riesgo de errores manuales.
- Los scripts permiten a los usuarios extraer fácilmente datos de hojas de cálculo, bases de datos y API, o incluso raspar datos web, que luego pueden procesarse y analizarse utilizando poderosas herramientas estadísticas y analíticas.
- Varios complementos para Excel permiten a los usuarios crear enlaces bidireccionales en tiempo real entre sus hojas de cálculo y el código de Python.
- Python permite nuevos tipos de análisis, como las simulaciones de Monte Carlo, que no están disponibles en las hojas de cálculo estándar.
- El comercio algorítmico ya no es dominio exclusivo de los fondos de cobertura y los grandes bancos de inversión. Con Python, puede desarrollar, realizar pruebas retrospectivas e implementar sus propias estrategias comerciales en poco tiempo y a bajo costo.
Para las profesiones que han dependido durante mucho tiempo de la búsqueda en hojas de cálculo, Python es especialmente valioso. Citigroup, un banco estadounidense, ha introducido un curso intensivo de Python para sus analistas en formación. - El economista
Los profesionales de finanzas han tenido acceso durante mucho tiempo a VBA (Visual Basic para aplicaciones) en Excel para crear funciones personalizadas y automatizar flujos de trabajo. Con el surgimiento en los últimos años de Google Sheets como un competidor serio en el espacio de las hojas de cálculo, Google Apps Script ahora ofrece una opción adicional.
Sin embargo, me gustaría llamar la atención sobre una tercera opción, el lenguaje de programación Python, que se ha vuelto tremendamente popular en varios campos.
En este artículo, proporcionaré algunos ejemplos de lo que puede lograr con Python, comenzando con una descripción general del lenguaje en sí y por qué se ha vuelto tan popular en una variedad tan amplia de campos, que van desde el desarrollo web, aprendizaje automático, finanzas, ciencia y educación, solo por nombrar algunos. La segunda mitad consistirá en un tutorial paso a paso.
El objetivo de escribir esto es ayudarlo a decidir si Python parece lo suficientemente intrigante como para considerar agregarlo a su caja de herramientas financieras. Si das el salto, hay muchas aplicaciones, cursos, videos, artículos, libros y publicaciones de blog disponibles para aprender el idioma. Al final del artículo, he enumerado algunos recursos que me han ayudado en el camino.
Casos de uso: ejemplos de para qué he usado Python
Mi introducción a la programación fue aprender BASIC en un Oric 1 a mediados de la década de 1980. En aquel entonces, BASIC era el lenguaje para principiantes más común. Otros lenguajes con los que incursioné a finales de los 80 hasta mediados de los 90 fueron Pascal y C, pero nunca los usé de manera profesional y no esperaba necesitar o usar habilidades de programación. Según mi conocimiento en ese momento, a finales de los 90, las finanzas y la programación eran campos muy diferentes, cuando elegí embarcarme en una carrera en finanzas.
Avance rápido hasta 2012, y estaba buscando retomar la programación como un pasatiempo, así que comencé a investigar los idiomas disponibles en ese momento. Resultó que habían pasado bastantes cosas, y cuando me encontré con Python me enganché, por muchas de las razones que describiré en la siguiente sección. Desde entonces, he usado Python para una amplia gama de tareas, desde pequeños scripts hasta proyectos más grandes, tanto a nivel personal como profesional. Muchos, pero no todos, han involucrado hojas de cálculo, el banco de trabajo de muchos profesionales de las finanzas.
Estos son algunos ejemplos de lo bien que pueden combinarse las hojas de cálculo y Python:
1. Seguimiento de cientos de actividades a lo largo del tiempo en una configuración de PMO de integración de fusiones y adquisiciones
Trabajo con todos los aspectos de las transacciones de M&A, no solo la ejecución, sino también la integración. En un caso reciente, el equipo de la PMO se decidió por un enfoque híbrido de gestión de programas y proyectos, utilizando la planificación en cascada y diagramas de Gantt para planes de alto nivel para cada uno de los doce flujos de trabajo de integración, además de un tablero Kanban para realizar un seguimiento de los cientos de actividades que se llevan a cabo. en cualquier momento dado, en el primer plan de 100 días y más allá. La herramienta Kanban que se eligió, MeisterTask, tiene varias funciones estadísticas y de generación de informes, pero nuestras necesidades iban más allá en términos de análisis y presentación, lo que requería una solución personalizada. Este es el flujo de trabajo que automaticé usando Python:
- Guarde el estado de todo el tablero semanalmente como un archivo CSV.
- Lea todos los archivos CSV históricos en un Pandas DataFrame.
- Ordene, filtre, agrupe y manipule los datos en formatos acordados de cómo queremos seguir el progreso (por estado de actividad, flujo de trabajo, etc.).
- Escriba el resultado en un archivo de Excel con los datos de cada análisis dentro de su propia hoja, formateado de tal manera que pueda copiarse y pegarse fácilmente en los gráficos de think-cell.
- Cree tablas y gráficos para el paquete de informes para la reunión mensual del comité directivo.
Desarrollar el guión requirió una inversión inicial de unas pocas horas, pero ahora, actualizar el paquete de informes para las reuniones del comité directivo o el análisis ad hoc es cuestión de minutos. Literalmente, unos 30 segundos para ir a la carpeta correcta y ejecutar el script con un comando de una línea, y luego unos minutos para copiar y pegar el resultado en la plataforma de diapositivas. Con alrededor de 500 actividades (tarjetas) en doce flujos de trabajo que ya tienen aproximadamente un mes de ejecución, seguimiento semanal de cómo se mueven, dentro de una línea de tiempo del programa de dos años, rápidamente se encuentra lidiando con miles y eventualmente con decenas de miles de puntos de datos en docenas. de archivos Sin automatización, estamos hablando de algunas tareas muy tediosas aquí.
La compensación del "valor del dinero en el tiempo" entre simplemente continuar con las cosas o agregar más carga de trabajo inicial mediante la configuración de la automatización es un tema común en las finanzas. Tomé una decisión similar con el primer paso de este proceso, exportando los datos como archivos CSV. MeisterTask, como muchas aplicaciones web modernas, tiene una API, que se puede conectar a su aplicación de Python, pero el tiempo dedicado a configurarla superaría con creces el ahorro de tiempo para nuestro caso de uso aquí.
Entonces, como puede ver, muchas veces la solución óptima es automatizar ciertos pasos de un flujo de trabajo y mantener otros manuales.
2. Análisis de las estadísticas de precios de la vivienda mediante Web Scraping, API de Google Maps y Excel
Otro ejemplo es algo que hice por interés personal pero quiero resaltarlo porque contiene algunos otros elementos interesantes de la utilidad de Python:
- Raspe los datos de los listados de bienes raíces, incluida la dirección, el tamaño, la cantidad de habitaciones, el precio de venta y otras características, para un área determinada; unos pocos cientos a quizás mil líneas en total.
- Guardar en una estructura de datos de Python.
- Conéctese a la API de Google Maps y, para cada listado, recupere la distancia entre la propiedad y puntos de referencia clave como el mar, el centro de la ciudad, la estación de tren más cercana, el aeropuerto más cercano, etc.
- Exporte los datos a un archivo de Excel.
- Utilice la funcionalidad estándar de Excel para ejecutar regresiones, calcular estadísticas y crear gráficos sobre métricas estándar, como el precio por metro cuadrado y la distancia a puntos de referencia.
Los resultados aquí podrían combinarse con sus propias ponderaciones personales en términos de preferencias y limitaciones financieras al buscar bienes raíces.
Estos son solo dos ejemplos, centrados en la automatización del trabajo relacionado con hojas de cálculo y la adición de funciones, pero las oportunidades con Python son casi infinitas. En la siguiente sección, describiré las razones por las que se ha vuelto tan popular, antes de pasar a un tutorial paso a paso de simulación de Monte Carlo en Python.
Por qué Python es una excelente opción para los profesionales de las finanzas
El lenguaje de programación Python existe desde 1990, pero no es hasta los últimos años que su popularidad se ha disparado.
Hay varias razones para esto, veamos cada una por separado.
1. Python es un lenguaje de programación de alto nivel
Un lenguaje de programación de alto nivel es aquel que abstrae muchos de los detalles del funcionamiento interno de la computadora. Un buen ejemplo es la gestión de la memoria. Los lenguajes de programación de nivel inferior requieren una comprensión detallada de las complejidades de cómo se distribuye, asigna y libera la memoria de la computadora, además del tiempo empleado y las líneas de código necesarias para manejar las tareas. Python abstrae y maneja muchos de estos detalles automáticamente, lo que le permite concentrarse en lo que desea lograr.
2. Es conciso
Debido a que Python es un lenguaje de programación de alto nivel, el código es más conciso y se centra casi por completo en la lógica comercial de lo que desea lograr, en lugar de los detalles técnicos de implementación. Las opciones de diseño del lenguaje contribuyen a esto: por ejemplo, Python no requiere el uso de llaves o punto y coma para delinear funciones, bucles y líneas como lo hacen muchos otros lenguajes, lo que lo hace más conciso y, como algunos argumentan, mejora legibilidad.
3. Fácil de aprender y entender
Una observación que ha influido en las opciones de diseño del lenguaje en Python es que los programas se leen con más frecuencia de lo que se escriben. Python sobresale aquí ya que su código se parece mucho al inglés simple, especialmente si nombra los diferentes componentes de su script o programa de manera sensata.
4. Adecuado para un desarrollo rápido e iterativo
El ensayo y error ilustrado supera la planificación de intelectos impecables. -David Kelley
Python es ideal para la creación de prototipos y el desarrollo rápido e iterativo (y, sí, prueba y error) porque las herramientas de interpretación interactivas, como el shell de Python, IPython y los cuadernos de Jupyter, están al frente y en el centro de la cadena de herramientas de Python. En estos entornos interactivos, puede escribir y ejecutar cada línea de código de forma aislada y ver los resultados (o un mensaje de error útil) de inmediato. Otros lenguajes también tienen esto, pero en la mayoría de los casos no en la misma medida que Python.
5. Se puede utilizar tanto para la creación de prototipos como para el código de producción
Además de ser excelente para la creación de prototipos, Python también es un lenguaje excelente y poderoso para aplicaciones de producción de gran tamaño. Algunas de las compañías de software más grandes del mundo hacen un uso intensivo de Python en una variedad de aplicaciones y casos de uso.
6. Viene con "Baterías incluidas:" La biblioteca estándar de Python
Todo lo necesario para las operaciones básicas está integrado directamente en el lenguaje, pero además de eso, la biblioteca estándar de Python tiene herramientas para trabajar con archivos, medios, redes, información de fecha y hora, y mucho más. Esto le permite realizar una amplia variedad de tareas sin tener que buscar paquetes de terceros.
7. Grandes bibliotecas de terceros para análisis financiero
Para los profesionales de las finanzas, Pandas con sus objetos DataFrame y Series , y Numpy con su ndarray son los caballos de batalla del análisis financiero con Python. En combinación con matplotlib y otras bibliotecas de visualización, tiene excelentes herramientas a su disposición para ayudar a la productividad.
8. ¡Python es gratis!
Python está desarrollado bajo una licencia de código abierto, lo que lo hace gratuito también para uso comercial.
Tutorial paso a paso sobre el uso conjunto de Python y Finance
Lo que sigue es un tutorial paso a paso que muestra cómo crear una versión simplificada de la simulación de Monte Carlo descrita en mi publicación de blog anterior, pero utilizando Python en lugar del complemento @RISK para Excel.
Los métodos de Monte Carlo se basan en el muestreo aleatorio para obtener resultados numéricos. Una de esas aplicaciones es extraer muestras aleatorias de una distribución de probabilidad que represente posibles estados futuros inciertos del mundo donde las variables o suposiciones pueden tomar un rango de valores.
Es útil hacer la simulación de Monte Carlo en un modelo de valoración DCF simplificado en lugar de los ejemplos más comunes que ve que muestran la valoración de opciones u otros derivados, ya que para esto no necesitamos matemáticas más allá de los conceptos básicos de cálculo de los estados financieros y descontar los flujos de caja, lo que nos permite centrarnos en los conceptos y herramientas de Python. Sin embargo, tenga en cuenta que este modelo de tutorial básico está destinado a ilustrar los conceptos clave y no es útil tal como está para fines prácticos. Tampoco tocaré ninguno de los aspectos más académicos de las simulaciones de Monte Carlo.
El tutorial asume que está familiarizado con los componentes básicos de la programación, como variables y funciones. De lo contrario, podría ser útil tomarse 10 minutos para revisar los conceptos clave, por ejemplo, en esta introducción.
El punto de partida y el resultado deseado
Comienzo con el mismo modelo de valoración DCF muy simplificado que se usa en el tutorial de simulación de Monte Carlo. Tiene algunos elementos de línea clave de los tres estados financieros y tres celdas de entrada resaltadas, que en la versión de Excel tienen estimaciones puntuales que ahora queremos reemplazar con distribuciones de probabilidad para comenzar a explorar posibles rangos de resultados.
Un enfoque de dos pasos para desarrollar un guión pequeño
Haz que funcione, hazlo bien, hazlo rápido - Kent Beck
La intención de este tutorial es brindarles a los profesionales financieros nuevos en Python una introducción no solo a cómo podría verse un programa útil, sino también una introducción al proceso iterativo que puede usar para desarrollarlo. Tiene, por tanto, dos partes:
- Primero, desarrollo un prototipo funcional utilizando un enfoque sencillo que creo que es fácil de seguir y no muy diferente del proceso que se podría usar para comenzar este proyecto si tuviera que comenzar desde cero.
- Luego, después de haber desarrollado el prototipo funcional, paso por el proceso de refactorización: cambiar la estructura del código sin cambiar su funcionalidad. Es posible que desee quedarse con esa parte: es una solución más elegante que la primera y, como beneficio adicional, es aproximadamente 75 veces más rápida en términos de tiempo de ejecución.
1. Desarrollo de un prototipo de trabajo
Configuración del cuaderno Jupyter
El cuaderno Jupyter es una gran herramienta para trabajar con Python de forma interactiva. Es un intérprete interactivo de Python con celdas que pueden contener código, texto Markdown, imágenes u otros datos. Para este tutorial utilicé Python Quant Platform, pero también puedo recomendar Colaboratory de Google, que es gratuito y se ejecuta en la nube. Una vez allí, simplemente seleccione "Nuevo cuaderno de Python 3" en el menú "Archivo" y estará listo para comenzar.
Habiendo hecho eso, el siguiente paso es importar los paquetes de terceros que necesitamos para la manipulación y visualización de datos, y decirle al programa que queremos ver los gráficos en línea en nuestro cuaderno, en lugar de en ventanas separadas:
import numpy as np import pandas as pd import matplotlib.pyplot as plt %matplotlib inline
Una nota antes de comenzar a nombrar nuestras primeras variables. Como ya destaqué, la legibilidad es una de las fortalezas de Python. El diseño del lenguaje contribuye en gran medida a respaldar eso, pero todos los que escriben código son responsables de hacerlo legible y comprensible, no solo para los demás sino también para ellos mismos. Como establece la Ley de Eagleson, “cualquier código propio que no hayas mirado durante seis meses o más bien podría haber sido escrito por otra persona”.
Una buena regla general es nombrar los componentes de su programa de tal manera que minimice la necesidad de comentarios separados que expliquen lo que hace su programa.

Con eso en mente, sigamos adelante.
Creación de los estados financieros
Hay muchas maneras en que podemos trabajar con datos de hojas de cálculo existentes en Python. Podríamos, por ejemplo, leer una hoja en un Pandas DataFrame con una línea de código usando el comando read_excel
. Si desea una integración más estrecha y un vínculo en tiempo real entre su hoja de cálculo y el código de Python, existen opciones comerciales y gratuitas disponibles para proporcionar esa funcionalidad.
Dado que el modelo aquí es muy simple y para centrarnos en los conceptos de Python, lo recrearemos desde cero en nuestro script. Al final de la primera parte, mostraré cómo puedes exportar lo que hemos creado a una hoja de cálculo.
Como primer paso para crear una representación en Python de los estados financieros, necesitaremos una estructura de datos adecuada. Hay muchos para elegir, algunos integrados en Python, otros de varias bibliotecas, o podemos crear los nuestros. Por ahora, usemos una serie de la biblioteca Pandas para ver su funcionalidad:
years = ['2018A', '2019B', '2020P', '2021P', '2022P', '2023P'] sales = pd.Series(index=years) sales['2018A'] = 31.0 sales
Esta entrada y su salida correspondiente se muestra a continuación:
Con las tres primeras líneas hemos creado una estructura de datos con un índice que consta de años (cada uno marcado para mostrar si es real, presupuestado o proyectado), un valor inicial (en millones de euros, como en el modelo DCF original) y celdas vacías (NaN, "No es un número") para las proyecciones. La cuarta línea imprime una representación de los datos; en general, escribir el nombre de una variable u otros objetos en el intérprete interactivo generalmente le dará una representación sensata de la misma.
A continuación, declaramos una variable para representar el crecimiento anual de ventas proyectado. En esta etapa, es una estimación puntual, la misma cifra que en nuestro modelo DCF original. Primero queremos usar esas mismas entradas y confirmar que nuestra versión de Python realiza lo mismo y da el mismo resultado que la versión de Excel, antes de reemplazar las estimaciones puntuales con distribuciones de probabilidad. Usando esta variable, creamos un bucle que calcula las ventas en cada año de las proyecciones en función del año anterior y la tasa de crecimiento:
growth_rate = 0.1 for year in range(1, 6): sales[year] = sales[year - 1] * (1 + growth_rate) sales
Ahora tenemos ventas proyectadas, en lugar de NaN:
Usando el mismo enfoque, continuamos a través de los estados financieros, declarando las variables según las necesitamos y realizando los cálculos necesarios para finalmente llegar al flujo de caja libre. Una vez que lleguemos podemos comprobar que lo que tenemos corresponde a lo que dice la versión de Excel del modelo 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
Esto nos da los flujos de efectivo libres:
La única línea de arriba que quizás necesite un comentario en esta etapa es la segunda referencia tax_payment
. Aquí, aplicamos una pequeña función para garantizar que, en escenarios en los que el beneficio antes de impuestos se vuelve negativo, no tengamos un pago de impuestos positivo. Esto muestra la eficacia con la que puede aplicar funciones personalizadas a todas las celdas de una serie Pandas o DataFrame. La función real aplicada es, por supuesto, una simplificación. Un modelo más realista para un ejercicio de valoración más grande tendría un modelo fiscal separado que calcula los impuestos en efectivo reales pagados en función de una serie de factores específicos de la empresa.
Realización de la valoración DCF
Habiendo llegado a los flujos de efectivo proyectados, ahora podemos calcular un valor terminal simple y descontar todos los flujos de efectivo hasta el presente para obtener el resultado DCF. El siguiente código introduce la indexación y el corte, lo que nos permite acceder a uno o más elementos en una estructura de datos, como el objeto Serie Pandas.
Accedemos a los elementos escribiendo corchetes directamente después del nombre de la estructura. La indexación simple accede a los elementos por su posición, comenzando con cero, lo que significa que free_cash_flow[1]
nos daría el segundo elemento. [-1]
es una forma abreviada de acceder al último elemento (el flujo de caja del último año se usa para calcular el valor final), y el uso de dos puntos nos da una porción, lo que significa que [1:]
nos da todos los elementos excepto el primero, ya que no queremos incluir el año histórico 2018A
en nuestra valoración 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
Con esto concluye la primera parte de nuestro prototipo: ahora tenemos un modelo DCF funcional, aunque muy rudimentario, en Python.
Exportación de los datos
Antes de pasar a la simulación real de Monte Carlo, este podría ser un buen momento para mencionar las capacidades de exportación disponibles en el paquete Pandas. Si tiene un objeto Pandas DataFrame, puede escribirlo en un archivo de Excel con una línea usando el método to_excel
. También hay una funcionalidad similar para exportar a más de una docena de otros formatos y destinos.
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
Creación de distribuciones de probabilidad para nuestra simulación Monte Carlo
Ahora estamos listos para enfrentar el próximo desafío: reemplazar algunas de las entradas de estimación puntual con distribuciones de probabilidad. Si bien los pasos hasta este punto pueden haber parecido algo engorrosos en comparación con la creación del mismo modelo en Excel, las siguientes líneas le darán una idea de lo poderoso que puede ser Python.
Nuestro primer paso es decidir cuántas iteraciones queremos ejecutar en la simulación. El uso de 1000 como punto de partida logra un equilibrio entre obtener suficientes puntos de datos para obtener gráficos de salida sensatos y terminar la simulación dentro de un marco de tiempo sensato. A continuación, generamos las distribuciones reales. En aras de la simplicidad, generé tres distribuciones normales aquí, pero la biblioteca NumPy tiene una gran cantidad de distribuciones para elegir, y también hay otros lugares para buscar, incluida la biblioteca estándar de Python. Después de decidir qué distribución utilizar, debemos especificar los parámetros necesarios para describir su forma, como la media y la desviación estándar, y el número de resultados deseados.
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()
Aquí se podría argumentar que el EBITDA no debe ser una variable aleatoria independiente de las ventas, sino que debe estar correlacionada con las ventas hasta cierto punto. Estoy de acuerdo con esto y agregaría que debe estar impulsado por una sólida comprensión de la dinámica de la estructura de costos (costos variables, semivariables y fijos) y los factores clave de costos (algunos de los cuales pueden tener sus propias distribuciones de probabilidad, como, por ejemplo, los precios de las materias primas), pero dejo esas complejidades de lado aquí por razones de espacio y claridad.
Cuantos menos datos tenga para informar su elección de distribución y parámetros, más tendrá que confiar en el resultado de sus diversos flujos de trabajo de diligencia debida, combinados con la experiencia, para formar una opinión consensuada sobre rangos de escenarios probables. En este ejemplo, con las proyecciones de flujo de efectivo, habrá un gran componente subjetivo, lo que significa que la visualización de las distribuciones de probabilidad se vuelve importante. Aquí, podemos obtener una visualización básica, que muestra la distribución del crecimiento de las ventas, con solo dos líneas cortas de código. De esta manera, podemos ver rápidamente cualquier distribución a ojo que mejor refleja la vista colectiva del equipo.
Ahora tenemos todos los componentes básicos que necesitamos para ejecutar la simulación, pero no están en un formato conveniente para ejecutar la simulación. Este es el mismo código con el que hemos trabajado hasta ahora, pero todo reunido en una celda y reorganizado en una función por conveniencia:
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
Ahora podemos ejecutar toda la simulación y trazar la distribución de salida, que será el valor de flujo de caja descontado de esta empresa en cada una de las 1000 iteraciones, con el siguiente código. El comando %time
no es código de Python, sino una abreviatura de cuaderno que mide el tiempo para ejecutar algo (en su lugar, podría usar la función de Python de la biblioteca estándar). Depende de la computadora en la que lo ejecute, pero esta versión necesita de 1 a 2 segundos para ejecutar las 1000 iteraciones y visualizar el resultado.
%time plt.hist(run_mcs(), bins=20, color='r') plt.show()
2. Refinando el prototipo
La sospecha latente de que algo podría simplificarse es la fuente más rica del mundo de desafíos gratificantes. -Edsger Dijkstra
La refactorización se refiere al proceso de reescribir el código existente para mejorar su estructura sin cambiar su funcionalidad, y puede ser uno de los elementos más divertidos y gratificantes de la codificación. Puede haber varias razones para hacer esto. Podría ser para:
- Organiza las diferentes partes de una manera más sensata.
- Cambie el nombre de variables y funciones para que su propósito y funcionamiento sean más claros.
- Permita y prepárese para funciones futuras.
- Mejore la velocidad de ejecución, la huella de memoria u otra utilización de recursos.
Para mostrar cómo se vería un paso en ese proceso, limpié el prototipo que acabamos de recorrer al recopilar todas las variables iniciales en un solo lugar, en lugar de estar dispersas como en el script del prototipo, y optimicé su velocidad de ejecución a través de un proceso llamado vectorización
El uso de matrices NumPy le permite expresar muchos tipos de tareas de procesamiento de datos como expresiones de matriz concisas que, de lo contrario, podrían requerir bucles de escritura. Esta práctica de reemplazar bucles explícitos con expresiones de matriz se conoce comúnmente como vectorización. wes mckinney
Ahora se ve más limpio y fácil de entender:
# 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 principal diferencia que notará entre esta versión y la anterior es la ausencia del bucle for i in range(iterations)
. Usando la operación de matriz de NumPy, esta versión se ejecuta en 18 milisegundos en comparación con los 1,35 segundos de la versión prototipo, aproximadamente 75 veces más rápido.
%time plt.hist(run_mcs(), bins=20, density=True, color="r") plt.show()
Estoy seguro de que es posible una mayor optimización, ya que armé tanto el prototipo como la versión refinada en poco tiempo únicamente para el propósito de este tutorial.
Llevándolo más lejos
Este tutorial mostró algunas de las poderosas características de Python, y si tuviera que desarrollar esto más, las oportunidades son casi infinitas. Podrías, por ejemplo:
- Extraiga o descargue estadísticas relevantes de empresas o sectores de páginas web u otras fuentes de datos, para ayudar a informar su elección de suposiciones y distribuciones de probabilidad.
- Use Python en aplicaciones de finanzas cuantitativas, como en un algoritmo comercial automatizado basado en factores fundamentales y/o macroeconómicos.
- Desarrolle capacidades de exportación que generen resultados en una hoja de cálculo y/o formato de presentación, para usar como parte de su proceso interno de revisión y aprobación de transacciones, o para presentaciones externas.
Ni siquiera he mencionado lo que también podría hacer con las diversas aplicaciones web, de ciencia de datos y de aprendizaje automático que han contribuido al éxito de Python.
En resumen: un lenguaje útil para su caja de herramientas financieras
Este artículo brindó una introducción al lenguaje de programación Python, enumeró algunas de las razones por las que se ha vuelto tan popular en las finanzas y mostró cómo crear un pequeño script de Python. En un tutorial paso a paso, expliqué cómo se puede usar Python para la creación de prototipos iterativos, el análisis financiero interactivo y el código de aplicación para modelos de valoración, programas de negociación algorítmica y más.
Para mí, al final del día, la característica principal de la tecnología Python es que es simplemente divertido trabajar con ella. Si te gusta resolver problemas, construir cosas y hacer que los flujos de trabajo sean más eficientes, te animo a que lo pruebes. Me encantaría saber qué has hecho con él o te gustaría hacer con él.
Recursos recomendados para que los profesionales de las finanzas aprendan Python
- Libros de O´Reilly. Puedo recomendar especialmente:
- Python for Finance by Yves Hilpisch
- Learning Python by Mark Lutz
- Fluent Python by Luciano Ramalho
- The Python Quants
- PyCon talks on YouTube
- Udemy