Revista Economía & Negocios

Vol. 7 Núm. 2, 2025

Artículo original

Análisis de portafolios de inversión mediante simulación de Monte Carlo en Python: evaluación del riesgo y rendimiento con acciones mexicanas

Portfolio investment analysis using Monte Carlo simulation in Python: Risk and return assessment with Mexican stocks

José Gerardo De La Vega-Meneses*

*Autor de correspondencia: josegerardo.delavega@upaep.mx, https://orcid.org/0000-0001-6748-5901

Universidad Popular Autónoma del Estado de Puebla. Puebla, México

Recepción: 09/01/2025

Aprobación: 06/03/2025

Publicación: 30/10/2025

JEL CODE: G11, G17, C15

Esta obra está bajo una Licencia Creative Commons Atribución 4.0 Internacional.

Como citar: De La Vega-Meneses J. G. (2025). Análisis de portafolios de inversión mediante simulación de Monte Carlo en Python: evaluación del riesgo y rendimiento con acciones mexicanas. Economía & Negocios, 7(2), 14-36. https://www.doi.org/10.33326/27086062.2025.2.2218

RESUMEN

Este estudio utiliza la simulación de Monte Carlo para analizar portafolios de inversión, evaluando el riesgo y rendimiento de diez acciones mexicanas seleccionadas de diversas industrias. Generando 1000 combinaciones aleatorias de ponderaciones, la simulación mostró una amplia gama de escenarios de desempeño para las carteras. Los resultados destacaron la importancia del índice de Sharpe para identificar portafolios óptimos, revelando que mayores rendimientos suelen implicar mayor volatilidad, mientras que las carteras estables ofrecen un mejor balance riesgo-retorno. La frontera eficiente visualizó esta relación. Este análisis demuestra el valor de la simulación Monte Carlo para optimizar asignaciones de activos y apoyar decisiones informadas.

Palabras clave: simulación Monte Carlo, portafolios de inversión, Sharpe ratio

ABSTRACT

This study applies Monte Carlo simulation to analyze investment portfolios, focusing on the risk and return of ten selected Mexican stocks from diverse industries. By generating 1,000 random weight combinations, the simulation revealed a wide range of portfolio performance scenarios. Results highlighted the importance of the Sharpe ratio in identifying optimal portfolios, showing that higher returns often come with greater volatility, while stable portfolios provide better risk-return balance. The efficient frontier visualized the relationship between volatility and expected returns. This analysis demonstrates the value of Monte Carlo simulation as a tool for optimizing asset allocation and supporting informed investment decisions.

Keywords: Monte Carlo simulation, investment portfolios, Sharpe ratio

INTRODUCCIÓN

La simulación de Monte Carlo es una herramienta poderosa utilizada para modelar el comportamiento de sistemas complejos a través de la generación de escenarios aleatorios (Mongid et al., 2023). En el contexto de la inversión, permite simular diferentes combinaciones de activos dentro de un portafolio, proporcionando una visión más amplia de los posibles rendimientos y riesgos bajo distintas condiciones del mercado. Esta simulación es particularmente útil para optimizar decisiones de inversión, ya que ayuda a identificar las combinaciones más eficientes de activos según los objetivos del inversionista (Sánchez, et al., 2021). Un portafolio de inversión es una colección de activos, como acciones, bonos u otros instrumentos financieros, cuyo rendimiento total se ve afectado por las fluctuaciones de cada uno de los componentes (Zhang et al., 2022). A través de la simulación, se pueden probar diferentes combinaciones de estos activos, evaluando su rendimiento y riesgo asociados. El objetivo es maximizar el rendimiento esperado, minimizando al mismo tiempo la exposición al riesgo. El índice de Sharpe es una métrica clave utilizada para evaluar la eficiencia de un portafolio, comparando el rendimiento ajustado por riesgo (Kourtis, 2016; Pav, 2016). Este indicador mide cuánto retorno adicional se obtiene por cada unidad de riesgo asumido. Un Sharpe ratio más alto indica que el portafolio está generando más rendimiento en relación con el riesgo que se está tomando. En conjunto, la simulación de Monte Carlo y el índice de Sharpe permiten a los inversionistas tomar decisiones más informadas y optimizar sus portafolios.

Objetivo general

Aplicar la simulación de Monte Carlo en Python para analizar portafolios de inversión en acciones mexicanas, evaluando su rendimiento y riesgo y proporcionando herramientas para optimizar la asignación de activos ajustada al riesgo.

Objetivos específicos

El primero es descargar y procesar datos históricos de acciones mexicanas a precios de cierre de diez acciones mexicanas representativas de diferentes sectores desde 2014 hasta 2024, y preparar la información para su análisis. El segundo se refiere a generar combinaciones aleatorias de ponderaciones para la simulación de Monte Carlo mediante programación en Python, con 1000 combinaciones aleatorias de ponderaciones para las acciones seleccionadas, calculando el rendimiento y riesgo de cada combinación en diferentes escenarios aleatorios. El tercero se refiere a calcular métricas de rendimiento y riesgo, utilizando el Sharpe ratio para evaluar la relación riesgo-rendimiento de cada combinación de portafolio, destacando aquellos con un mayor Sharpe ratio como las opciones más eficientes, y comparar la rentabilidad esperada con la volatilidad. El cuarto se refiere a visualizar y analizar los resultados, graficando la frontera eficiente para mostrar la relación entre rendimiento esperado y volatilidad, e identificar la cartera óptima con el mejor Sharpe ratio, proporcionando herramientas visuales para facilitar la toma de decisiones informadas en la construcción de portafolios.

Marco teórico

El análisis de portafolios de inversión es un aspecto fundamental de la gestión financiera moderna, con el objetivo principal de maximizar el rendimiento ajustado por riesgo (Bhutto, et al., 2020). A lo largo de las últimas décadas, la teoría económica y financiera ha desarrollado herramientas sofisticadas para medir y gestionar los riesgos asociados con las inversiones, así como para optimizar los rendimientos de los portafolios. Entre estos enfoques, la simulación de Monte Carlo, el índice de Sharpe y el uso de Python para el análisis de datos son técnicas clave que permiten a los inversionistas tomar decisiones más informadas y robustas (Hu, 2024; Zhang, 2023). Un portafolio de inversión se refiere a un conjunto de activos financieros que un inversor selecciona con el objetivo de alcanzar una rentabilidad específica, manteniendo un nivel de riesgo controlado. La teoría moderna de portafolios, desarrollada por Harry Markowitz en 1952, introdujo el concepto de diversificación como la clave para reducir el riesgo global de una inversión (Hali, & Yuliati, 2020; Mittal et al., 2022). Según Markowitz, la diversificación permite a los inversores combinar activos con diferentes características de riesgo y rendimiento, reduciendo la volatilidad general del portafolio sin necesariamente sacrificar el retorno esperado. Esta idea revolucionó la manera en que los inversionistas piensan sobre la relación entre riesgo y rendimiento (Dimand, 2024).

El rendimiento de un portafolio se mide típicamente a través del rendimiento ponderado de los activos que lo componen. Cada activo tiene un peso específico dentro del portafolio, y estos pesos determinan la contribución de cada uno al rendimiento total. Un portafolio bien construido no solo busca maximizar el rendimiento, sino también controlar el riesgo asociado a ese rendimiento, lo que nos lleva al siguiente análisis: el riesgo en los portafolios (Thakkar, & Chaudhari, 2021). El riesgo en un contexto de inversión se refiere a la variabilidad de los rendimientos de un activo o portafolio (Moslehpour et al., 2022). Este concepto de riesgo no es estático y puede tomar diferentes formas, tales como el riesgo sistemático y el riesgo no sistemático. El riesgo sistemático es el que afecta a todo el mercado, como las fluctuaciones económicas, las políticas gubernamentales y la situación geopolítica (Brunnermeier et al., 2020). Es imposible de eliminar a través de la diversificación y solo puede ser gestionado en parte mediante la asignación estratégica de activos. Por otro lado, el riesgo no sistemático, también conocido como riesgo específico o diversificable, está relacionado con factores internos de una empresa o sector y puede ser reducido a través de la diversificación (Lo, 2020; Moradi et al., 2024). El rendimiento, por su parte, es la medida de la ganancia o pérdida generada por una inversión durante un periodo específico, generalmente expresado como un porcentaje. En un portafolio de inversión, el rendimiento total es la suma de los rendimientos ponderados de los activos que lo componen, considerando sus respectivos pesos en el portafolio. Sin embargo, la relación entre el rendimiento y el riesgo es compleja y es esencial para los inversionistas comprender cómo se equilibran estos dos factores en la construcción de portafolios. Un concepto central en este equilibrio es la frontera eficiente, la cual muestra la mejor combinación de riesgo y rendimiento para un portafolio dado (Jensen et al., 2024; Agarwal, & Muppalaneni, 2022).

Para evaluar esta relación, se utilizan herramientas estadísticas como la desviación estándar y la covarianza. La desviación estándar mide la dispersión de los rendimientos de un activo respecto a su rendimiento promedio, mientras que la covarianza mide cómo dos activos se mueven en relación entre sí. La combinación adecuada de activos con baja correlación puede reducir significativamente el riesgo global del portafolio, maximizando al mismo tiempo el rendimiento esperado (Barillas et al., 2020; Mistry, & Khatwani, 2023). En este contexto, la simulación de Monte Carlo es una técnica estadística utilizada para modelar situaciones que involucran incertidumbre y variabilidad. En el contexto de los portafolios de inversión, se emplea para generar una serie de posibles escenarios para el rendimiento de los activos, utilizando variables aleatorias para simular el comportamiento de los mercados (Shadabfar, & Cheng, 2020). Esta simulación es especialmente útil cuando se analizan portafolios compuestos por múltiples activos, ya que permite explorar una amplia gama de combinaciones de rendimientos y riesgos bajo diferentes condiciones del mercado (Jeong et al., 2019). La simulación de Monte Carlo funciona generando una gran cantidad de cambio aleatorio de los precios de los activos, basado en ciertas distribuciones estadísticas, como la normalidad de los rendimientos. Al generar 1000 o más trayectorias posibles para los precios de los activos, los inversionistas pueden obtener una distribución de posibles resultados para el rendimiento total de un portafolio, lo que permite visualizar los rangos de rentabilidad y riesgo. Esto permite a los inversionistas tener una visión más realista de los posibles resultados, especialmente en escenarios de alta volatilidad y riesgo (Bottasso et al., 2023). El uso de Monte Carlo en la optimización de portafolios es particularmente ventajoso porque permite incorporar la incertidumbre inherente a los mercados financieros y realizar un análisis más profundo de las decisiones de inversión. De este modo, se pueden identificar las combinaciones de activos que mejor se ajustan a un perfil de riesgo específico, optimizando la asignación de activos en un portafolio (Mnif et al., 2020).

El índice de Sharpe es una de las métricas más utilizadas para evaluar la eficiencia de un portafolio en términos de la relación entre riesgo y rendimiento. Fue introducido por William Sharpe en 1966 y se calcula como el rendimiento esperado de un portafolio menos la tasa libre de riesgo, dividido entre la desviación estándar del portafolio (Zhang et al., 2023). Este índice proporciona una medida de cuánto rendimiento adicional genera un portafolio por cada unidad de riesgo asumido, lo que permite a los inversionistas comparar diferentes portafolios y seleccionar aquellos que logran el mejor retorno ajustado por riesgo (Kahramonovich, 2023). Un valor más alto del índice de Sharpe indica que un portafolio está generando un mejor retorno por unidad de riesgo. Es importante destacar que un portafolio con un alto índice de Sharpe no necesariamente es el de mayor rendimiento absoluto, pero sí el que ofrece el mejor rendimiento en relación al riesgo asumido. Esto lo convierte en una herramienta clave para la toma de decisiones en la construcción de portafolios de inversión (Pav, 2021).

Python se ha convertido en una de las herramientas más utilizadas para el análisis y modelado de datos financieros, gracias a su flexibilidad, facilidad de uso y disponibilidad de potentes bibliotecas estadísticas y de visualización (Lubanovic, 2019). En el análisis de portafolios, Python ofrece una serie de bibliotecas que permiten descargar datos financieros, realizar cálculos estadísticos y simular escenarios de inversión de manera eficiente. La biblioteca Pandas es esencial para manejar datos de series temporales y realizar cálculos sobre los rendimientos de los activos, mientras que NumPy facilita las operaciones matemáticas necesarias para calcular estadísticas como la media, la varianza y la covarianza (Fuhrer et al., 2021). Además, Matplotlib y Seaborn son útiles para la visualización de los resultados, incluyendo gráficos de la frontera eficiente y otras métricas clave del portafolio (Sial et al., 2021). Por otro lado, bibliotecas como SciPy permiten realizar optimizaciones numéricas complejas, como la optimización de portafolios mediante técnicas de optimización no lineales (Virtanen et al., 2020). Además, existen bibliotecas específicas para la simulación de Monte Carlo, como PyMC3 y SimDK, que hacen posible generar múltiples escenarios de inversión y evaluar los resultados en términos de rendimiento y riesgo (Anderson et al., 2020). En resumen, el uso de Python en el análisis de portafolios de inversión no solo facilita la realización de cálculos complejos, sino que también proporciona una forma eficiente de simular y visualizar los posibles resultados de diferentes estrategias de inversión.

El análisis de portafolios de inversión es una disciplina compleja que involucra la evaluación del rendimiento y riesgo de diferentes activos en un portafolio. La teoría de portafolios moderna y el uso de técnicas estadísticas como la simulación de Monte Carlo y el índice de Sharpe son fundamentales para la toma de decisiones informadas en este campo. El uso de Python como herramienta de análisis potencia la capacidad de los inversionistas para modelar diferentes escenarios y optimizar la asignación de activos en función del perfil de riesgo. Estas herramientas combinadas permiten no solo mejorar el rendimiento de los portafolios, sino también gestionar el riesgo de manera más efectiva, lo que resulta en decisiones más acertadas y alineadas con los objetivos financieros del inversionista.

METODOLOGÍA

El proceso que se estableció para realizar la presente investigación con el fin de alcanzar el objetivo propuesto se desarrolló mediante cuatro etapas:

  1. Descargar y procesar datos históricos de precios de cierre de diez acciones mexicanas desde 2014 hasta 2024, preparando la información para el análisis.
  2. Generar 1000 combinaciones aleatorias de ponderaciones para la simulación de Monte Carlo en Python, calculando el rendimiento y riesgo de cada una.
  3. Calcular métricas de rendimiento y riesgo utilizando el Sharpe ratio, evaluando la relación riesgo-rendimiento y destacando los portafolios más eficientes.
  4. Visualizar y analizar resultados graficando la frontera eficiente, identificando la cartera óptima con el mejor Sharpe ratio para la toma de decisiones.

A continuación, se presentan las características con las que se diseñó esta investigación (tabla 1).

Tabla 1

Diseño de la investigación

Metodología

Descripción

Nivel de investigación

Propósito de investigación

Muestreo utilizado

Variables utilizadas

Investigación cuantitativa y descriptiva. Esta investigación se centra en el análisis cuantitativo de los portafolios de inversión mediante simulación de Monte Carlo, utilizando datos históricos de acciones mexicanas para modelar el rendimiento y riesgo.

Investigación pura o básica. El estudio tiene como objetivo contribuir al conocimiento académico mediante el análisis del rendimiento y riesgo de portafolios de inversión utilizando la simulación de Monte Carlo.

Deliberado. Se seleccionaron diez acciones representativas de distintos sectores de la Bolsa Mexicana de Valores, con el fin de realizar una simulación que cubra una variedad de activos y escenarios.

Investigación no experimental. Se recopilaron datos históricos de precios de cierre de las acciones seleccionadas, desde 2014 hasta 2024, para analizar el rendimiento y riesgo con base en ponderaciones aleatorias generadas en la simulación de Monte Carlo.

RESULTADOS

En este trabajo de investigación se desarrolló un código en Python, que se muestra en el anexo 1, para realizar el análisis de portafolios de inversión mediante simulación de Monte Carlo, enfocado en acciones mexicanas. El objetivo fue evaluar el riesgo y el rendimiento de un conjunto de activos seleccionados a través de métodos numéricos y simulaciones. El código permite descargar datos financieros de acciones mexicanas, procesar precios de cierre, asignar ponderaciones aleatorias a un portafolio de inversión, y calcular indicadores clave como el rendimiento esperado, la volatilidad y el índice de Sharpe. Utilizando Python y la simulación de Monte Carlo, se generaron 1000 combinaciones aleatorias de ponderaciones, proporcionando un amplio rango de escenarios de rendimiento y riesgo. Los resultados, procesados con herramientas como Pandas y NumPy, destacaron el índice de Sharpe para identificar portafolios óptimos y evidenciaron el balance entre riesgo y retorno. El análisis realizado con Python, utilizando simulación de Monte Carlo, se aplicó a un portafolio significativo compuesto por las diez acciones mexicanas de mayor valor de mercado a diciembre de 2024. Estas acciones representan grandes empresas como Walmart de México, América Móvil, Grupo México, Cemex, Banorte, Fomento Económico Mexicano, Arca Continental, Grupo Financiero Inbursa, Grupo Carso y Bimbo. Los resultados destacaron la relación entre el riesgo y el retorno, con la frontera eficiente mostrando los portafolios óptimos. Este enfoque permite optimizar las asignaciones de activos y tomar decisiones informadas. A continuación, se muestran los principales resultados y sus interpretaciones.

Rendimiento diario del portafolio

La figura 1 muestra que de 2014 a 2024 el portafolio representativo del mercado accionario mexicano registró rendimientos diarios máximos de 4 % en los años 2014, 2020 y 2024, mientras que los rendimientos diarios mínimos se ubicaron en niveles alrededor de -6 % en los años 2019, 2020 y 2024.

Figura 1

Rendimiento diario del portafolio representativo del mercado accionario mexicano

Nota. Realizado con Python

Evolución de cada acción dentro del portafolio

La figura 2 muestra como resultado de la simulación, la evolución de cada acción dentro del portafolio representativo del mercado accionario mexicano a lo largo del tiempo, identificándose del periodo 2014 a 2024 a las acciones de Arca Continental, Grupo Financiero Banorte y Walmart de México con las mejores evoluciones dentro del portafolio simulado, mientras que, en contraparte, las tres acciones con la menos eficiente evolución fueron Cemex, Bimbo y América Móvil.

Figura 2

Evolución de cada acción dentro del portafolio representativo del mercado accionario mexicano

Nota. Realizado con Python

Valor total del portafolio a lo largo del tiempo

La figura 3 presenta la evolución del valor total del portafolio representativo del mercado mexicano a lo largo del tiempo. Este valor se calcula como la suma de las posiciones individuales de las acciones en el portafolio, con una inversión inicial de un millón de pesos mexicanos. La gráfica muestra cómo el portafolio experimentó un notable crecimiento, duplicando su valor entre 2014 y 2024. Este rendimiento se obtuvo a partir de una asignación de ponderaciones aleatorias y utilizando las diez empresas con mayor capitalización de mercado al cierre de 2024. La visualización resalta la tendencia positiva del portafolio durante este período.

Figura 3

Valor total del portafolio representativo del mercado accionario mexicano a lo largo del tiempo

Nota. Realizado con Python

Identificación del portafolio óptimo

La figura 4 presenta la frontera eficiente del portafolio con el resultado de la simulación de Monte Carlo para evaluar un portafolio de inversión compuesto por múltiples activos, ejecutándose 1000 simulaciones y generando pesos aleatorios para las acciones representativas del mercado accionario mexicano, calculando el rendimiento esperado, la volatilidad y el Sharpe ratio de cada combinación, con la finalidad de identificar el portafolio con el mejor rendimiento ajustado por riesgo, representado por el Sharpe ratio más alto, considerando una tasa libre de riesgo del 10 %. Se visualiza la frontera eficiente mostrando la relación entre la volatilidad y el rendimiento esperado de los diferentes portafolios simulados, destacando el portafolio óptimo con una volatilidad de 18,45 %, rendimiento de 11,52 % y Sharpe ratio de 0,082. Esta representación gráfica es clave para los inversores, ya que proporciona una visualización clara de las posibles combinaciones de activos y su impacto en la relación riesgo-retorno. La frontera eficiente permite seleccionar el portafolio que maximiza el rendimiento ajustado por riesgo dentro de un conjunto de alternativas, lo que optimiza la toma de decisiones en cuanto a la asignación de activos en el mercado accionario mexicano, ajustado a las preferencias y restricciones del inversor.

Figura 4

Portafolio óptimo resultado de la simulación Monte Carlo aplicada al mercado accionario mexicano

Nota. Realizado con Python

CONCLUSIÓN Y DISCUSIÓN

En el presente trabajo se desarrolla una simulación para analizar el comportamiento de un portafolio de inversión utilizando el método de Monte Carlo, un enfoque poderoso que permite modelar la incertidumbre y explorar diversas combinaciones de activos dentro de un portafolio. A continuación, se explica en detalle el proceso que sigue el código y los resultados que se obtienen mediante este análisis. El primer paso en la simulación es la obtención de datos históricos de diez acciones de la Bolsa Mexicana de Valores. Para ello, se utiliza la librería “yfinance”, que facilita la descarga de precios de cierre de las acciones seleccionadas, desde 2014 hasta 2024. Esta fuente de datos permite disponer de información precisa y actualizada para el análisis. Tras la descarga, se procede a limpiar los datos, manejando los valores faltantes (NaN) reemplazándolos por 0 y utilizando una técnica de “forward fill” (llenado hacia adelante) para completar cualquier valor ausente, asegurando así la integridad de la serie temporal de precios. Una vez obtenidos los precios de cierre de las acciones, se realiza un ajuste importante: los precios se escalan para que todos comiencen con un valor de 1. Este paso permite comparar los rendimientos relativos de cada acción, eliminando la distorsión que podría generar la diferencia en los precios absolutos de las acciones. Posteriormente, se asignan ponderaciones aleatorias a cada acción dentro del portafolio, representando una posible distribución de recursos en el portafolio. Con estas ponderaciones, se calcula el valor total del portafolio para cada día, lo que permite observar cómo se comporta el conjunto de las inversiones a lo largo del tiempo. El rendimiento diario del portafolio se calcula tomando la variación porcentual del valor total del portafolio con respecto al día anterior. Este cálculo proporciona una visión detallada de la evolución del portafolio. A continuación, se ejecuta la simulación de Monte Carlo, realizando 1000 simulaciones con diferentes combinaciones de ponderaciones aleatorias para las acciones seleccionadas. Para cada una de estas simulaciones, se calculan el rendimiento esperado, la volatilidad (riesgo) y el Sharpe ratio, un indicador clave que mide el rendimiento ajustado por el riesgo. El Sharpe ratio más alto indica una mejor relación entre rendimiento y riesgo. Para facilitar la interpretación de los resultados, el código genera diversas visualizaciones. Entre ellas se incluyen gráficos que muestran el rendimiento diario del portafolio, la evolución de su valor total y las posiciones individuales de las acciones a lo largo del tiempo. Además, se crea una gráfica de dispersión que ilustra la frontera eficiente, es decir, la relación entre rendimiento esperado y volatilidad para todas las simulaciones. Esta visualización permite identificar las combinaciones óptimas de riesgo y rendimiento. También se utilizan gráficos interactivos generados con la librería “plotly”, lo que permite explorar cómo varían la volatilidad, el rendimiento y el Sharpe ratio en función de las diferentes combinaciones de pesos. Por tanto, los resultados de la simulación incluyen el rendimiento esperado anual del portafolio, la volatilidad estimada y el Sharpe Ratio de cada simulación. Estas métricas ofrecen una evaluación clara del comportamiento del portafolio bajo diversas condiciones de mercado. La simulación de Monte Carlo genera un conjunto robusto de resultados, lo que proporciona una visión amplia de las posibles variaciones en el comportamiento del portafolio, dependiendo de las distintas combinaciones de activos. El análisis muestra que el Sharpe Ratio es un indicador fundamental para evaluar la eficiencia de un portafolio en términos de la relación entre riesgo y rendimiento. Los portafolios con un Sharpe ratio más alto son preferibles, ya que indican un retorno superior por cada unidad de riesgo asumido. Además, la simulación de Monte Carlo permite explorar diversas combinaciones de ponderaciones, ofreciendo una distribución amplia de posibles resultados. La visualización de la frontera eficiente resalta cómo las diferentes composiciones del portafolio afectan el equilibrio entre riesgo y rendimiento, proporcionando una herramienta valiosa para optimizar las decisiones de inversión. El objetivo final de este análisis es identificar la combinación de activos que maximice el rendimiento ajustado por riesgo y ofrecer una visión completa de la variabilidad del rendimiento y el riesgo en el proceso de toma de decisiones.

REFERENCIAS

Anderson, J. A., Glaser, J., & Glotzer, S. C. (2020). HOOMD-blue: A Python package for high-performance molecular dynamics and hard particle Monte Carlo simulations. Computational Materials Science, 173, 109363. https://www.sciencedirect.com/science/article/abs/pii/S0927025619306627

Agarwal, S., & Muppalaneni, N. B. (2022). Portfolio optimization in stocks using mean–variance optimization and the efficient frontier. International Journal of Information Technology, 14(6), 2917-2926. https://link.springer.com/article/10.1007/s41870-022-01052-2

Barillas, F., Kan, R., Robotti, C., & Shanken, J. (2020). Model comparison with Sharpe ratios. Journal of Financial and Quantitative Analysis, 55(6), 1840-1874. https://doi.org/10.1017/S0022109019000589

Bhutto, S. A., Ahmed, R. R., Streimikiene, D., Shaikh, S., & Streimikis, J. (2020). Portfolio Investment diversification at Global stock market: A Cointegration Analysis of Emerging BRICS (P) Group. Acta Montanistica Slovaca, 25(1). https://portalcris.vdu.lt/server/api/core/bitstreams/1a444b30-7703-47a1-bdca-935a3d9d292c/content

Bottasso, A., Fusaro, M., Giribone, P. G., & Tissone, A. (2023). Investment certificates pricing using a Quasi-Monte Carlo framework: Case-studies based on the Italian market. International Journal of Financial Engineering, 10(03), 2350021. https://doi.org/10.1142/S2424786323500214

Brunnermeier, M., Rother, S., & Schnabel, I. (2020). Asset price bubbles and systemic risk. The Review of Financial Studies, 33(9), 4272-4317. https://academic.oup.com/rfs/article-abstract/33/9/4272/5732666

Dimand, R. W. (2024). Harry Markowitz, the Cowles Commission, and portfolio theory. Annals of Operations Research, 1-13. https://link.springer.com/article/10.1007/s10479-024-06223-x

Fuhrer, C., Solem, J. E., & Verdier, O. (2021). Scientific Computing with Python: High-performance scientific computing with NumPy, SciPy, and pandas. Packt Publishing Ltd.

Hali, N. A., & Yuliati, A. (2020). Markowitz model investment portfolio optimization: a review theory. International Journal of Research in Community Services, 1(3), 14-18. https://journal.rescollacomm.com/index.php/ijrcs/article/view/104

Hu, X. (2024). Bayesian Optimization and Monte Carlo Simulation in Technology Sector Portfolio Allocation: A Comparative Analysis Using the Sharpe Ratio. Highlights in Science, Engineering and Technology, 88, 300-310. https://drpress.org/ojs/index.php/HSET/article/view/18870

Jensen, T. I., Kelly, B. T., Malamud, S., & Pedersen, L. H. (2024). Machine learning and the implementable efficient frontier. Swiss Finance Institute Research Paper, (22-63). https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4187217

Jeong, D., Yoo, M., Yoo, C., & Kim, J. (2019). A hybrid Monte Carlo and finite difference method for option pricing. Computational Economics, 53, 111-124. https://link.springer.com/article/10.1007/s10614-017-9730-4

Kahramonovich, S. F. (2023). Analysis of Efficient Portfolio based on Modern Portfolio Theory. World Bulletin of Management and Law, 24, 47-51. https://www.scholarexpress.net/index.php/wbml/article/view/2998

Kourtis, A. (2016). The Sharpe ratio of estimated efficient portfolios. Finance Research Letters, 17, 72-78. https://www.sciencedirect.com/science/article/abs/pii/S1544612316000106

Lo, A. W. (2020). Robert C. Merton: The First Financial Engineer. Annual Review of Financial Economics, 12, 1-18. https://www.annualreviews.org/content/journals/10.1146/annurev-financial-042720-055018

Lubanovic, B. (2019). Introducing Python: Modern Computing in Simple Packages. O’Reilly Media, Inc.

Mistry, J., & Khatwani, R. A. (2023). Examining the superiority of the Sharpe single-index model of portfolio selection: A study of the Indian mid-cap sector. Humanities and Social Sciences Communications, 10(1), 1-9. https://www.nature.com/articles/s41599-023-01686-y

Mittal, S., Bhattacharya, S., & Mandal, S. (2022). Characteristics analysis of behavioural portfolio theory in the Markowitz portfolio theory framework. Managerial finance, 48(2), 277-288. https://www.emerald.com/insight/content/doi/10.1108/mf-05-2021-0208/full/html

Mnif, E., Jarboui, A., Hassan, M. K., & Mouakhar, K. (2020). Big data tools for Islamic financial analysis. Intelligent Systems in Accounting, Finance and Management, 27(1), 10-21. https://onlinelibrary.wiley.com/doi/abs/10.1002/isaf.1463

Mongid, A., Suhartono, S., Sistiyarini, E., & Hidayat, S. E. (2023). Historical stress test of credit risk using Monte Carlo simulation: Indonesia Islamic banking. International Journal of Business and Society, 24(2), 608-619. https://publisher.unimas.my/ojs/index.php/IJBS/article/view/5947

Moradi, M., Oskou, V., Talebi, R., & Namdar, F. (2024). Unsystematic risk, financing policy and financing behavior of companies in the TSE. New Applied Studies in Management, Economics & Accounting, 7(2), 60-71. https://www.nasme-journal.ir/article_186977.html

Moslehpour, M., Al-Fadly, A., Ehsanullah, S., Chong, K. W., Xuyen, N. T. M., & Tan, L. P. (2022). Assessing financial risk spillover and panic impact of Covid-19 on European and Vietnam stock market. Environmental Science and Pollution Research, 29(19), 28226-28240. https://link.springer.com/article/10.1007/s11356-021-18170-2

Pav, S. E. (2016). Notes on the Sharpe ratio. Semantic Scholar, 1-49. https://cran.uni-muenster.de/web/packages/SharpeR/vignettes/SharpeRatio.pdf

Pav, S. E. (2021). The Sharpe Ratio: Statistics and Applications. Chapman and Hall/CRC.

Sánchez-Serna, A., Camacho-Zabala, E. A., Rueda Varon, M. J., & Carvajal Sandoval, A. R. (2021). Impairment model applying Monte Carlo simulation: Expected loss approach for companies in the real sector. International Journal of Business & Management Science, 11(1). https://perfilesycapacidades.javeriana.edu.co/en/publications/impairment-model-applying-montecarlo-simulation-expected-loss-app

Shadabfar, M., & Cheng, L. (2020). Probabilistic approach for optimal portfolio selection using a hybrid Monte Carlo simulation and Markowitz model. Alexandria engineering journal, 59(5), 3381-3393. https://www.sciencedirect.com/science/article/pii/S1110016820302118

Sial, A. H., Rashdi, S. Y. S., & Khan, A. H. (2021). Comparative analysis of data visualization libraries Matplotlib and Seaborn in Python. International Journal of Advanced Trends in Computer Science and Engineering, 10(1), 277-281. https://doi.org/10.30534/ijatcse/2021/391012021

Thakkar, A., & Chaudhari, K. (2021). A comprehensive survey on portfolio optimization, stock price and trend prediction using particle swarm optimization. Archives of Computational Methods in Engineering, 28(4), 2133-2164. https://link.springer.com/article/10.1007/s11831-020-09448-8

Virtanen, P., Gommers, R., Oliphant, T. E., Haberland, M., Reddy, T., Cournapeau, D., & Van Mulbregt, P. (2020). SciPy 1.0: fundamental algorithms for scientific computing in Python. Nature methods, 17(3), 261-272.

Zhang, M., Tang, Y., Liu, L., & Zhou, D. (2022). Optimal investment portfolio strategies for power enterprises under multi-policy scenarios of renewable energy. Renewable and Sustainable Energy Reviews, 154, 111879. https://doi.org/10.1016/j.rser.2021.111879

Zhang, A. (2023). Portfolio Optimization of Stocks-Python-Based Stock Analysis. International Journal of Education and Humanities, 9(2), 32-38. https://doi.org/10.54097/ijeh.v9i2.9584

Zhang, H., Hua, F., Xu, C., Kong, H., Zuo, R., & Guo, J. (2023). Unveiling the potential of sentiment: can large language models predict Chinese stock price movements? arXiv preprint arXiv:2306.14222. https://arxiv.org/abs/2306.14222

ANEXO 1

Código en programación Python

# Import yfinance for downloading financial data like stock prices from Yahoo Finance

# Import pandas for data manipulation and analysis (e.g., working with DataFrames)

# Import numpy for numerical computing, including handling missing values (e.g., np.nan)

# Import matplotlib.pyplot for data visualization (e.g., creating charts and graphs)

import yfinance as yf

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

# List of tickers

tickers = [‘WALMEX.MX’, ‘AMX’, ‘GMEXICOB.MX’, ‘FEMSAUBD.MX’, ‘GFNORTEO.MX’, ‘CEMEXCPO.MX’, ‘AC.MX’, ‘GFINBURO.MX’, ‘GCARSOA1.MX’, ‘BIMBOA.MX’]

# Define the date range

start_date = ‘2014-01-02’

end_date = ‘2024-12-31’

# Download stock data for all tickers

data = yf.download(tickers, start=start_date, end=end_date)

# Extract the ‘Close’ prices for each stock and reset the index

close_prices = data[‘Close’]

# Replace NaN values with 0

close_prices.replace(np.nan, 0, inplace=True)

# Replace zeroes with the last valid data

close_prices.replace(0, np.nan, inplace=True)

close_prices.ffill(inplace=True)

# Function to process portfolio data

def process_portfolio(portfolio_df):

# Replace NaN values with 0

portfolio_df.replace(np.nan, 0, inplace=True)

# Replace zeroes with the last valid data

portfolio_df.replace(0, np.nan, inplace=True)

portfolio_df.ffill(inplace=True)

# Return the processed DataFrame

return portfolio_df

# Apply the function to close_prices if needed

close_prices = process_portfolio(close_prices)

# Print the cleaned Close prices

print(close_prices)

# Save the ‘Close’ prices to a CSV file

file_path = r’C:\stock_prices.csv’

close_prices.to_csv(file_path)

print(f”Stock prices successfully saved in {file_path}!”)

# Optionally, print the first few rows to check

print(close_prices.head())

# Load the close price data back from the CSV file

close_price_df = pd.read_csv(r’C:\stock_prices.csv’)

# Ensure the ‘Date’ column is converted to datetime

close_price_df[‘Date’] = pd.to_datetime(close_price_df[‘Date’])

# Set ‘Date’ as the index of the DataFrame

close_price_df.set_index(‘Date’, inplace=True)

# Define the price_scaling function to make all values start at 1

def price_scaling(df):

“””

Scales stock prices so all start at 1.

“””

return df.div(df.iloc[0], axis=1)

# Define asset allocation function

def asset_allocation(df, weights, initial_investment):

“””

Allocate investment based on closing prices, weights, and initial investment.

“””

portfolio_df = df.copy() # Copy to avoid modifying original DataFrame

scaled_df = price_scaling(df) # Scale prices to start at 1

# Allocate investment across stocks

for i, stock in enumerate(scaled_df.columns): # Include the ‘Date’ column as the index

portfolio_df[stock] = scaled_df[stock] * weights[i] * initial_investment

# Calculate portfolio value

portfolio_df[‘Portfolio Value [$]’] = portfolio_df.sum(axis=1)

# Calculate daily returns as percentage change

portfolio_df[‘Portfolio Daily Return [%]’] = portfolio_df[‘Portfolio Value [$]’].pct_change() * 100

# Replace NaN values with 0

portfolio_df.replace(np.nan, 0, inplace=True)

return portfolio_df

# Number of stocks

n = len(close_price_df.columns) # No need to exclude the ‘Date’ column, as it’s now the index

print(f’Number of stocks under consideration = {n}’)

# Generate random portfolio weights (ensure they sum to 1)

def generate_portfolio_weights(n):

weights = np.random.random(n)

return weights / weights.sum()

# Generate and display portfolio weights

weights = generate_portfolio_weights(n).round(6)

print(f’Portfolio weights = {weights}’)

# Allocate the portfolio

portfolio_df = asset_allocation(close_price_df, weights, 1_000_000)

# Ensure the ‘Date’ column is set as index for plotting

portfolio_df.index = pd.to_datetime(portfolio_df.index) # Ensure index is datetime format

# Save the portfolio DataFrame to a CSV file

portfolio_file_path = r’C:\portfolio_allocation.csv’

portfolio_df.to_csv(portfolio_file_path)

print(f”Portfolio allocation successfully saved in {portfolio_file_path}!”)

# 1. Plot the Portfolio Daily Percentage Return

plt.figure(figsize=(10, 6))

plt.plot(portfolio_df.index, portfolio_df[‘Portfolio Daily Return [%]’], label=’Portfolio Daily Return [%]’, color=’blue’)

plt.title(‘Portfolio Daily Return (%)’)

plt.xlabel(‘Date’)

plt.ylabel(‘Return (%)’)

plt.grid(True)

plt.legend(loc=’upper left’)

plt.xticks(rotation=45)

plt.tight_layout()

# Show the plot for daily returns

plt.show()

# 2. Plot Each Stock Position Over Time (how each individual stock grows over time)

plt.figure(figsize=(10, 6))

# Loop through the stocks and plot each one

for stock in close_price_df.columns:

plt.plot(portfolio_df.index, portfolio_df[stock], label=stock)

plt.title(‘Stock Positions Over Time’)

plt.xlabel(‘Date’)

plt.ylabel(‘Stock Position Value [$]’)

plt.legend(loc=’upper left’)

plt.grid(True)

plt.xticks(rotation=45)

plt.tight_layout()

# Show the plot for each stock position

plt.show()

# 3. Plot the Total Daily Value of the Portfolio (sum of all positions)

plt.figure(figsize=(10, 6))

plt.plot(portfolio_df.index, portfolio_df[‘Portfolio Value [$]’], label=’Total Portfolio Value [$]’, color=’green’)

plt.title(‘Total Portfolio Value Over Time’)

plt.xlabel(‘Date’)

plt.ylabel(‘Portfolio Value [$]’)

plt.grid(True)

plt.legend(loc=’upper left’)

plt.xticks(rotation=45)

plt.tight_layout()

# Show the plot for the total portfolio value

plt.show()

# Define the simulation engine that will calculate the Sharpe ratio

def simulation_engine(weights, initial_investment, close_price_df):

# Ensure the weights match the number of assets

num_assets = close_price_df.shape[1]

if len(weights) != num_assets:

raise ValueError(f”The number of weights ({len(weights)}) does not match the number of assets ({num_assets})”)

# Asset allocation function

portfolio_df = asset_allocation(close_price_df, weights, initial_investment)

# Calculate return on investment (ROI)

return_on_investment = ((portfolio_df[‘Portfolio Value [$]’].iloc[-1] - portfolio_df[‘Portfolio Value [$]’].iloc[0]) /

portfolio_df[‘Portfolio Value [$]’].iloc[0]) * 100

# Portfolio daily returns (drop Date, Portfolio Value [$], Portfolio Daily Return [%] columns)

portfolio_daily_return_df = portfolio_df.drop(columns=[‘Portfolio Value [$]’, ‘Portfolio Daily Return [%]’])

portfolio_daily_return_df = portfolio_daily_return_df.pct_change(1)

# Calculate expected portfolio return (annualized)

expected_portfolio_return = np.sum(weights * portfolio_daily_return_df.mean()) * 252 # Annualized return

# Covariance matrix (annualized)

covariance = portfolio_daily_return_df.cov() * 252 # Annualized covariance matrix

# Expected portfolio volatility (annualized)

expected_volatility = np.sqrt(np.dot(weights, np.dot(covariance, weights))) # Volatility formula

# Risk-free rate

rf = 0.10 # Example risk-free rate (10%)

# Sharpe ratio (assuming annualized return and volatility)

sharpe_ratio = (expected_portfolio_return - rf) / expected_volatility

# Return metrics: expected portfolio return, expected volatility, Sharpe ratio, final value, ROI

return expected_portfolio_return, expected_volatility, sharpe_ratio, portfolio_df[‘Portfolio Value [$]’].iloc[-1], return_on_investment

# Example usage:

initial_investment = 10000000 # Example initial investment

weights = generate_portfolio_weights(n) # Generate random weights for the portfolio

# Run the simulation engine

portfolio_metrics = simulation_engine(weights, initial_investment, close_price_df)

# Print results

# Print the expected annual return of the portfolio, formatted as a percentage with 2 decimal places

print(‘Expected Portfolio Annual Return = {:.2f}%’.format(portfolio_metrics[0] * 100))

# Print the portfolio’s standard deviation (volatility), formatted as a percentage with 2 decimal places

print(‘Portfolio Standard Deviation (Volatility) = {:.2f}%’.format(portfolio_metrics[1] * 100))

# Print the Sharpe Ratio, a measure of risk-adjusted return, formatted with 2 decimal places

print(‘Sharpe Ratio = {:.2f}’.format(portfolio_metrics[2]))

# Print the final value of the portfolio, formatted as a dollar amount with 2 decimal places

print(‘Portfolio Final Value = ${:.2f}’.format(portfolio_metrics[3]))

# Print the return on investment (ROI), formatted as a percentage with 2 decimal places

print(‘Return on Investment = {:.2f}%’.format(portfolio_metrics[4]))

# Create and print a NumPy array of ones with 10 elements (used as a placeholder or weights)

print(np.ones(10))

# Assign equal weights to each asset in the portfolio (10 assets, each with 10% weight)

weights = np.ones(10) * 0.1

# Print the weights array to confirm its values

# Define the initial investment amount for the portfolio (e.g., $10,000,000)

print(weights)

initial_investment = 10000000 # Example initial investment

# Run the simulation engine

portfolio_metrics = simulation_engine(weights, initial_investment, close_price_df)

# Print results

print(‘Expected Portfolio Annual Return = {:.2f}%’.format(portfolio_metrics[0] * 100))

print(‘Portfolio Standard Deviation (Volatility) = {:.2f}%’.format(portfolio_metrics[1] * 100))

print(‘Sharpe Ratio = {:.2f}’.format(portfolio_metrics[2]))

print(‘Portfolio Final Value = ${:.2f}’.format(portfolio_metrics[3]))

print(‘Return on Investment = {:.2f}%’.format(portfolio_metrics[4]))

# Monte Carlo Simulation

sim_runs = 1000

initial_investment = 1_000_000

weights_runs = np.zeros((sim_runs, n))

sharpe_ratio_runs = np.zeros(sim_runs)

expected_portfolio_returns_runs = np.zeros(sim_runs)

volatility_runs = np.zeros(sim_runs)

return_on_investment_runs = np.zeros(sim_runs)

final_value_runs = np.zeros(sim_runs)

for i in range(sim_runs):

# Generate random portfolio weights

weights = generate_portfolio_weights(n)

weights_runs[i, :] = weights

# Run the simulation engine to get portfolio metrics

expected_return, volatility, sharpe_ratio, final_value, roi = simulation_engine(weights, initial_investment, close_price_df)

# Store the results

sharpe_ratio_runs[i] = sharpe_ratio

expected_portfolio_returns_runs[i] = expected_return

volatility_runs[i] = volatility

return_on_investment_runs[i] = roi

final_value_runs[i] = final_value

# Print the results for the current simulation run

print(“Simulation Run = {}”.format(i + 1))

print(“Weights = {}, Final Value = ${:.2f}, Sharpe Ratio = {:.2f}”.format(

weights.round(3), final_value, sharpe_ratio))

print(‘\n’)

# Summary of all simulation runs

print(“Monte Carlo Simulation Complete”)

print(“Average Sharpe Ratio: {:.2f}”.format(np.mean(sharpe_ratio_runs)))

print(“Average Portfolio Return: {:.2f}%”.format(np.mean(expected_portfolio_returns_runs) * 100))

print(“Average Volatility: {:.2f}%”.format(np.mean(volatility_runs) * 100))

print(“Average ROI: {:.2f}%”.format(np.mean(return_on_investment_runs)))

print(“Average Final Value: ${:.2f}”.format(np.mean(final_value_runs)))

# Combine results into a DataFrame

simulation_results = pd.DataFrame({

‘Run’: np.arange(1, sim_runs + 1),

‘Sharpe Ratio’: sharpe_ratio_runs,

‘Expected Return (%)’: expected_portfolio_returns_runs * 100,

‘Volatility (%)’: volatility_runs * 100,

‘ROI (%)’: return_on_investment_runs,

‘Final Value ($)’: final_value_runs

})

# Save to CSV

output_file_path = r’C:\monte_carlo_simulation_results.csv’

simulation_results.to_csv(output_file_path, index=False)

print(f”Monte Carlo simulation results successfully saved in {output_file_path}!”)

# Print the entire `sharpe_ratio_runs` series or DataFrame to show its contents

# Print the minimum value from `sharpe_ratio_runs`, rounded to 4 decimal places

# Print the entire `sharpe_ratio_runs` series or DataFrame again (same as the first print)

# Print the index of the maximum value in `sharpe_ratio_runs`

# This returns the position (index) of the highest Sharpe ratio

# Print the maximum value from `sharpe_ratio_runs`

# This returns the highest Sharpe ratio

# Print the `weights_runs` variable, which likely contains a set of portfolio weights

# Print the row of `weights_runs` corresponding to the maximum Sharpe ratio

# It uses the index of the max Sharpe ratio (from `sharpe_ratio_runs.argmax()`) to select the associated portfolio weights

print(sharpe_ratio_runs)

print(sharpe_ratio_runs.min().round(4))

print(sharpe_ratio_runs)

print(sharpe_ratio_runs.argmax())

print(sharpe_ratio_runs.max())

print(weights_runs)

print(weights_runs[sharpe_ratio_runs.argmax(), :])

# Extract the optimal weights based on the maximum Sharpe ratio

optimal_weights = weights_runs[sharpe_ratio_runs.argmax(), :] # Weights with the best Sharpe ratio

# Run the simulation engine to evaluate the portfolio with the best weights

optimal_portfolio_return, optimal_volatility, optimal_sharpe_ratio, highest_final_value, optimal_return_on_investment = simulation_engine(

optimal_weights, initial_investment, close_price_df

)

# Print the results for the best portfolio

print(‘Optimal Portfolio Metrics Based on {} Monte Carlo Simulation Runs:’.format(sim_runs))

print(‘ - Portfolio Expected Annual Return = {:.02f}%’.format(optimal_portfolio_return * 100))

# Combine volatility, expected returns, and Sharpe ratios into a DataFrame for all 1000 simulations

simulation_metrics_df = pd.DataFrame({

‘Volatility (%)’: volatility_runs * 100, # Convert to percentage

‘Expected Return (%)’: expected_portfolio_returns_runs * 100, # Convert to percentage

‘Sharpe Ratio’: sharpe_ratio_runs

})

# Display all rows (if needed)

pd.set_option(‘display.max_rows’, None) # Adjusts settings to show all rows

print(simulation_metrics_df)

# Save the DataFrame to a CSV file

metrics_file_path = r’C:\simulation_metrics.csv’

simulation_metrics_df.to_csv(metrics_file_path, index=False)

print(f”Simulation metrics successfully saved in {metrics_file_path}!”)

# Import the `matplotlib.pyplot` module, which is commonly used for creating visualizations like plots and charts

import matplotlib.pyplot as plt

# Find the index of the highest Sharpe ratio

best_index = sharpe_ratio_runs.argmax()

# Extract metrics for the best portfolio

best_volatility = volatility_runs[best_index] * 100 # Convert to percentage

best_return = expected_portfolio_returns_runs[best_index] * 100 # Convert to percentage

# Plot volatility vs. return for all simulations

plt.figure(figsize=(10, 6))

plt.scatter(volatility_runs * 100, expected_portfolio_returns_runs * 100,

c=sharpe_ratio_runs, cmap=’viridis’, marker=’o’, edgecolor=’k’, alpha=0.7, label=’Simulations’)

# Highlight the portfolio with the highest Sharpe ratio

plt.scatter(best_volatility, best_return, color=’red’, s=100, label=’Best Portfolio (Max Sharpe Ratio)’)

# Add labels and title

plt.title(‘Efficient Frontier: Portfolio Simulations’, fontsize=16)

plt.xlabel(‘Volatility (%)’, fontsize=12)

plt.ylabel(‘Expected Return (%)’, fontsize=12)

plt.colorbar(label=’Sharpe Ratio’, orientation=’vertical’)

plt.legend(loc=’best’, fontsize=12)

plt.grid(True, linestyle=’--’, alpha=0.7)

# Show the plot

plt.tight_layout()

plt.show()

# Import the `plotly.express` module as `px`, which is used for creating interactive plots and visualizations

# Import the `pandas` library as `pd`, which is a powerful tool for data manipulation and analysis

import plotly.express as px

import pandas as pd

# Create a DataFrame with simulation results

efficient_frontier_df = pd.DataFrame({

‘Volatility (%)’: volatility_runs * 100,

‘Return (%)’: expected_portfolio_returns_runs * 100,

‘Sharpe Ratio’: sharpe_ratio_runs

})

# Find the best portfolio

best_index = sharpe_ratio_runs.argmax()

best_volatility = efficient_frontier_df[‘Volatility (%)’].iloc[best_index]

best_return = efficient_frontier_df[‘Return (%)’].iloc[best_index]

best_sharpe_ratio = efficient_frontier_df[‘Sharpe Ratio’].iloc[best_index]

# Add a column to highlight the best portfolio

efficient_frontier_df[‘Best Portfolio’] = [‘Yes’ if i == best_index else ‘No’ for i in range(len(efficient_frontier_df))]

# Create an interactive scatter plot with Plotly

fig = px.scatter(

efficient_frontier_df,

x=’Volatility (%)’,

y=’Return (%)’,

color=’Sharpe Ratio’,

color_continuous_scale=’viridis’,

hover_data=[‘Sharpe Ratio’, ‘Volatility (%)’, ‘Return (%)’],

title=’Efficient Frontier: Interactive Portfolio Simulations’,

labels={‘Volatility (%)’: ‘Volatility (%)’, ‘Return (%)’: ‘Expected Return (%)’}

)

# Highlight the best portfolio

fig.add_scatter(

x=[best_volatility],

y=[best_return],

mode=’markers’,

marker=dict(size=12, color=’red’, symbol=’circle’),

name=’Best Portfolio’

)

# Update layout for better visualization

fig.update_layout(

coloraxis_colorbar=dict(title=’Sharpe Ratio’),

legend=dict(title=’Legend’),

xaxis=dict(title=’Volatility (%)’),

yaxis=dict(title=’Expected Return (%)’),

template=’plotly_white’

)

# Show the interactive plot

fig.show()

# Import the `plotly.express` module as `px`, which is used for creating interactive plots and visualizations

# Import the `pandas` library as `pd`, which is a powerful tool for data manipulation and analysis

import plotly.express as px

import pandas as pd

# Assuming the following variables are already available:

# - volatility_runs: array of portfolio volatility from the simulations

# - expected_portfolio_returns_runs: array of portfolio returns from the simulations

# - sharpe_ratio_runs: array of Sharpe ratios from the simulations

# Create a DataFrame with simulation results

simulation_df = pd.DataFrame({

‘Simulation Run’: range(1, len(volatility_runs) + 1),

‘Volatility (%)’: volatility_runs * 100, # Convert to percentage

‘Expected Return (%)’: expected_portfolio_returns_runs * 100, # Convert to percentage

‘Sharpe Ratio’: sharpe_ratio_runs

})

# 1. Plot Volatility vs Simulation Run

fig_volatility = px.scatter(

simulation_df,

x=’Simulation Run’,

y=’Volatility (%)’,

title=’Portfolio Volatility vs Simulation Run’,

labels={‘Volatility (%)’: ‘Volatility (%)’, ‘Simulation Run’: ‘Simulation Run’},

template=’plotly_white’

)

fig_volatility.show()

# 2. Plot Return vs Simulation Run

fig_return = px.scatter(

simulation_df,

x=’Simulation Run’,

y=’Expected Return (%)’,

title=’Portfolio Return vs Simulation Run’,

labels={‘Expected Return (%)’: ‘Return (%)’, ‘Simulation Run’: ‘Simulation Run’},

template=’plotly_white’

)

fig_return.show()

# 3. Plot Sharpe Ratio vs Simulation Run

fig_sharpe = px.scatter(

simulation_df,

x=’Simulation Run’,

y=’Sharpe Ratio’,

title=’Portfolio Sharpe Ratio vs Simulation Run’,

labels={‘Sharpe Ratio’: ‘Sharpe Ratio’, ‘Simulation Run’: ‘Simulation Run’},

template=’plotly_white’

)

fig_sharpe.show()

# 4. Perform a sanity check to identify the simulation run with the highest Sharpe ratio

best_sharpe_run_index = sharpe_ratio_runs.argmax() # Index of the run with the highest Sharpe ratio

best_sharpe_value = sharpe_ratio_runs[best_sharpe_run_index]

best_run_number = best_sharpe_run_index + 1 # Adding 1 because the simulation runs are 1-based

# Print the best simulation run

print(f”The optimal simulation run with the highest Sharpe ratio is run #{best_run_number} with a Sharpe ratio of {best_sharpe_value:.4f}”)

print(sharpe_ratio_runs.argmax())

print(sharpe_ratio_runs.max())