Pymorningstar: Automatización de la API Morningstar Excel Add-in con Python

Pablo Vilas Naval
Octubre 2022

Introducción

Este notebook explica el paquete pymorningstar que puedes encontrar en mi perfil de GitHub. También puedes instalar este módulo mediante el comando pip install pymorningstar. Este módulo contiene la clase ExcelMorning que permite automatizar la descarga de información desde la API Morningstar Direct Excel Add-In. Puedes descargar la API de Morningstar para Excel desde este enlace.

Morningstar Direct Excel Add-In es un complemento/API para Excel que permite acceder desde Excel a las bases de datos que posee Morningstar (es necesario poseer una licencia con las claves de acceso). Esta API es adecuada para obtener datos concretos, es decir, información en serie temporal para un único individuo (small data). Sin embargo, cuando el objetivo es obtener información de varias series temporales (big data) la API presenta ciertas limitaciones las cuales he corregido mediante la creación del paquete pymorningstar.

Motivación

En el ámbito académico es necesario disponer de una gran cantidad de información para poder realizar una investigación de calidad. Sin embargo, la API Excel que ofrece Morningstar no permite descargar los datos en formato tabular.

Esta carencia suele ser suplida mediante “becarios” que dedican su tiempo a obtener y ordenar manualmente la información que facilita Morningstar para posteriormente poder realizar análisis cuantitativos. Pymorningstar evita el despilfarro de tiempo y talento al suplir las carencias de la API de Morningstar mediante el uso de Python. Además, este paquete reduce a la mínima expresión los posibles errores en el proceso de descarga y tabulación de la información. Esto no hubiera sido posible sin el paquete xlwings, desde aquí, quiero dejar por escrito mi más sincero agradecimiento a los contribuidores de esta biblioteca.

Uso de pymorningstar

Este paquete contiene la clase ExcelMorning, cuyos dos principales métodos son self.get_holding() y self.get_attributes() y sus dos principales atributos son self.hold_info y self.attr_info. Podemos descargar esta API desde PyPi (pip install pymorningstar). Este paquete tiene varias dependencias; para que funcione correctamente es necesario tener instaladas estas bibliotecas: xlwings, pandas, pyautogui, opencv-python y Pillow. En las siguientes líneas de código instalo el paquete e inicializo la clase ExcelMorning.

Importante: Antes de inicializar la clase es importante abrir el Excel para iniciar sesión en la API Excel de Morningstar (introducir nuestras claves de acceso).

In [1]:
# ! pip install pymorningstar

from pymorningstar.excel import ExcelMorning

morning = ExcelMorning()

Composición de fondos: get_holdings

La API-Excel de Morningstar instala la fórmula Excel MSHOLDING (más información sobre esta fórmula aquí). Esta fórmula te devuelve la composición de un fondo de inversión con las claves primarias de individuo (activos financieros) en las filas y las claves primarias de tiempo en columnas. Este formato de datos no es el apropiado, la clave primaria de tiempo tiene que estar en una sola columna. Además, es necesario añadir una nueva clave primaria que identifique el fondo de inversión para el que solicitamos la información (rara será la vez que nos interese un único fondo/individuo). En definitiva, las claves primarias (columnas) deben ser: fondo_id, activo_id, time_id.

Adicionalmente, hay que tener en cuenta que Morningstar tiene un límite diario de descargas (registros/celdas). En la fórmula Excel (MSHOLDING) cuanto mayor sea el horizonte temporal solicitado más fácil será gastar este límite. El activo financiero que estaba en fondo de inversión en febrero de 2010, ya no está en marzo de 2011 ni en junio de 2012 ni en septiembre de 2013… pero el formato matriz hace que sea necesario consumir un registro. Es decir, la formula nos devolverá la información solicitada en 2010 pero celdas con registros nulos para 2011, 2012… Cuanto mayor sea el horizonte temporal solicitado en la fórmula más información nula recibiremos y antes gastaremos el límite de descargas.

La fórmula que cree (get_holdings) tiene el parámetro months_frac que permite paliar parcialmente esta problemática dividiendo el horizonte temporal en subperiodos. Es decir, fraccionar la consulta en periodos de n meses para obtener matrices más pequeñas con menos registros nulos (por defecto months_frac=12).


En la siguiente pieza de código obtengo para el fondo de inversión “FSUSA06ITC” el valor de mercado de las inversiones que tenía en cartera para el periodo dic-2016 hasta dic-2021. En este vídeo, escucharlo con sonido y en máxima definición, podemos ver parte de lo que hace la función get_holdings() (fijarse en las variaciones que va experimentando la fórmula Excel). En el video el nombre de la compañía y CUSIP están ocultos para evitar cualquier problema legal.

In [2]:
from datetime import datetime
df = morning.get_holding('FSUSA06ITC', datetime(2016,12,31), datetime(2021,12,31),'CUSIP',data_type='MV',
                         frequency='M', show_country=True, show_currency=True, wait_time=0)
df
Out[2]:
Name CUSIP Detail Holding Type Country Currency MV
SerieCode Date
FSUSA06ITC 2016-12-31 BorgWarner Inc 099724106 EQUITY USA USD 2484720.0
2016-12-31 KKR & Co LP 48248M102 EQUITY USA USD 2605527.0
2016-12-31 Oracle Corp 68389X105 EQUITY USA USD 2272395.0
2016-12-31 CVS Health Corp 126650100 EQUITY USA USD 749645.0
2016-12-31 Barrick Gold Corp 067901108 EQUITY CAN USD 1791070.0
... ... ... ... ... ... ...
2021-12-31 Progressive Corp 743315103 EQUITY USA USD 969529.0
2021-12-31 Northern Institutional Treasury Premier 665279873 MUTUAL FUND - MONEY MARKET USA USD 873529.0
2021-12-31 ViacomCBS Inc Class B 92556H206 EQUITY USA USD 868037.0
2021-12-31 Madison Square Garden Sports Corp Class A 55825T103 EQUITY USA USD 835641.0
2021-12-31 Cash NaN CASH USA NaN 67867.0

650 rows × 6 columns

In [3]:
morning.hold_info
Out[3]:
StarDate EndDate IndexLen ColLen NaN Size Time Formula
SerieCode StarDown EndDown
FSUSA06ITC 2016-12-01 2017-11-30 2016-12-31 2021-12-31 37 8 29 296 2022-09-21 13:19:53.435515 '=MSHOLDING("FSUSA06ITC","CUSIP","01/12/2016",...
2017-12-01 2018-11-30 2016-12-31 2021-12-31 37 8 24 296 2022-09-21 13:19:59.300824 '=MSHOLDING("FSUSA06ITC","CUSIP","01/12/2017",...
2018-12-01 2019-11-30 2016-12-31 2021-12-31 35 8 17 280 2022-09-21 13:20:04.911698 '=MSHOLDING("FSUSA06ITC","CUSIP","01/12/2018",...
2019-12-01 2020-11-30 2016-12-31 2021-12-31 37 8 24 296 2022-09-21 13:20:10.542846 '=MSHOLDING("FSUSA06ITC","CUSIP","01/12/2019",...
2020-12-01 2021-11-30 2016-12-31 2021-12-31 37 8 30 296 2022-09-21 13:20:16.116616 '=MSHOLDING("FSUSA06ITC","CUSIP","01/12/2020",...
2021-12-01 2021-12-31 2016-12-31 2021-12-31 31 5 1 155 2022-09-21 13:20:21.656461 '=MSHOLDING("FSUSA06ITC","CUSIP","01/12/2021",...

Como se observa la función morning.get_holding() devuelve un DataFrame con los datos preparados y tabulados en el formato correcto. Por otro lado, el atributo self.hold_info, mientras la clase permanezca viva, nos irá almacenando metadatos de cada una de las fórmulas/peticiones que hemos realizado a Morningstar mediante el uso de su fórmula MSHOLDING. Como puedes observar este DataFrame es muy útil para detectar errores.

Series temporales: get_attributes

La API-Excel de Morningstar instala la fórmula Excel MSTS (más información sobre esta fórmula aquí). Esta fórmula te devuelve una serie temporal (o varias series temporales) para un activo financiero (una acción, un bono, un fondo de inversión). Por suerte, no somos económetras apasionados de las series temporales y de modelos ARIMA, ARMAX, VAR… por lo que rara vez estaremos interesados en una única serie temporal. Es decir, esta función lo que nos va a devolver es para un activo y fecha dado (activo_id + fecha_id) varios atributos/características.

Al usar esta fórmula aconsejo no mezclar atributos que tengan frecuencia diferente, o que por su naturaleza no sea aconsejable tenerlos en una misma tabla. Por ejemplo, el precio o rentabilidad de una acción normalmente es facilitado en frecuencia diaria, sin embargo, el rating ESG de dicha acción tendrá una frecuencia mensual o anual (será el mismo durante todo un mes o todo un año). Normalmente, también aconsejo introducir como primera variable la rentabilidad (o alguna variable de importancia similar). Si la primera serie temporal que queremos descargar no tiene información, la columna fecha no será generada y por lo tanto los datos que obtengamos no servirán

In [4]:
variables =['Gross Return', 'Morningstar Sustainability Rating™', 'Portfolio Corporate Sustainability Score', 
                  'Portfolio Environmental Risk Score', 'Portfolio Social Risk Score',]
df = morning.get_attributes('FSUSA06ITC', variables, (2019,1,1), (2019,3,31), 'M', 'C')
df
Out[4]:
Date Gross Return Morningstar Sustainability Rating™ Portfolio Corporate Sustainability Score Portfolio Environmental Risk Score Portfolio Social Risk Score
serie_code
FSUSA06ITC 2019-01-31 11.35094 Low NaN NaN NaN
FSUSA06ITC 2019-02-28 2.01001 Low NaN NaN NaN
FSUSA06ITC 2019-03-31 0.14193 Low 42.49 50.59 49.45
In [5]:
morning.attr_info
Out[5]:
Index Len Col Len NaN Size Time Formula
serie_code
FSUSA06ITC 3 5 6 15 2022-09-21 13:20:29.036047 '=MSTS("FSUSA06ITC","Gross Return,"&"Morningst...

La función get_attributes() nos permite obtener para un activo financiero dado las series temporales que nos interesen. El atributo self.attr_info de la clase ExcelMorning nos permite acceder a los metadatos de cada una de las fórmulas/peticiones que hemos realizado a Morningstar mediante el uso de su fórmula MSTS.

Otras funciones

wait_processing(): Esta función detiene la ejecución del código mientras Excel está haciendo la conexión con el servidor de Morningstar (ejecutando la fórmula que hemos introducido).

initialize_morning(): Esta función nos permite abrir un nuevo Excel sin necesidad de reiniciar la clase; sin necesidad de perder los metadatos almacenados en self.hold_info y self.attr_info.

is_limit(): Cuando hemos superado el límite de descargas Morningstar nos lanza un mensaje como este:
Está función detecta la aparición de este cuadro de diálogo (o alguno con una similitud superior al 85%) y detiene la ejecución del código. Concretamente, lanza una función input(). Llegados a este punto podemos interrumpir la ejecución del código o pulsar enter para que el código se siga ejecutando. Si queremos que el código se siga ejecutando es importante que nuestra sesión con Morningstar-Excel no haya caducado.

Conclusiones

Este paquete permite agilizar la extracción de información de la API Morningstar Excel Add-in ahorrando una gran cantidad de tiempo para los usuarios de este producto.

Si te ha gustado este contenido, puedes acompañarme en LinkedIn y GitHub
o explorar más recursos en mi página web.