2 votos

¿Cómo calcular el ratio Sortino de una cartera ponderada con Python?

En este ejemplo de trabajo soy capaz de calcular un ratio de Sharpe (con rf=0) a partir de una cartera ponderada de 3 valores, pero ¿cómo puedo modificar el código de abajo para que calcule un ratio de Sortino?

import numpy as np
from pandas_datareader import data

tickers = ['AAPL', 'MSFT', '^GSPC']
start_date = '2010-01-01'
end_date = '2016-12-31'

weights = [1/3, 1/3, 1/3]

# Fetch data
df = data.DataReader(tickers, 'yahoo', start_date, end_date)['Close']

# Calculate historical returns
returns = df.pct_change(1).dropna()

# Weighted mean returns
exp_rets = returns.mean()
mean = sum(exp_rets * weights)

# Standard deviation
var = np.dot(np.dot(weights, returns.cov()), weights)

# Sharp ratio
sr = mean / np.sqrt(var)

print(sr)
0.054270779230564975

4voto

xrost Puntos 129

Ratio Sortino en Python:

Haciendo mi propia investigación, encontré un documento que describe la fórmula del ratio de Sortino que sigue la misma configuración que la de este enlace descrito en un comentario anterior. En el caso de la brevedad, la fórmula del ratio de Sortino puede especificarse como:

$$ S = \frac{R - T}{TDD} $$

donde $R$ es el rendimiento del periodo medio y $T$ es la rentabilidad objetivo (también denominada rentabilidad media aceptable, MAR). Además,

$$ TDD = \sqrt{\frac{1}{N}\sum_{i=1}^N \min\left(0, X_i - T\right)^2} $$

denota la desviación a la baja objetivo, con $X_i$ siendo el $i$ de la rentabilidad. Utilizando la fórmula anterior podemos calcular el ratio de Sortino en Python. Sin tener en cuenta la primera parte de su código anterior ( definir los pesos, obtener los datos de las existencias, etc. ), podemos calcular el ratio de Sortino utilizando la siguiente función:

def SortinoRatio(df, T):
    """Calculates the Sortino ratio from univariate excess returns.

    Args:
        df ([float]): The dataframe or pandas series of univariate excess returns.
        T ([integer]): The targeted return. 
    """

    #downside deviation:

    temp = np.minimum(0, df - T)**2
    temp_expectation = np.mean(temp)
    downside_dev = np.sqrt(temp_expectation)

    #Sortino ratio:

    sortino_ratio = np.mean(df - T) / downside_dev

    return(sortino_ratio)

Ahora puede construir la rentabilidad de la cartera, definir su objetivo de rentabilidad especificado $T$ y los introducimos en la función:

#portfolio returns:
port_ret = returns.dot(weights)

#-------------------output:-----------------------
print(np.round(SortinoRatio(port_ret, T = 0),4))
0.0782

El resultado es un ratio Sortino de 0,0782.

Verificación:

Una buena forma de validar la función anterior, es encontrar una función ya implementada de una fuente "respetable" . Aquí, el PerformanceAnalytics paquete de R contiene una función que calcula el ratio de Sortino. Utilizando esta función en las 10 primeras filas de su marco de datos ( llamado ret ) obtenemos lo siguiente:

#R code:
ret <- matrix( 
c(0.001729,  0.000323,  0.003116,
-0.015906, -0.006137,  0.000546,
-0.001849, -0.010400,  0.004001,
 0.006648,  0.006897,  0.002882,
-0.008821, -0.012720,  0.001747,
-0.011375, -0.006607, -0.009381,
 0.014106,  0.009312,  0.008326,
-0.005792,  0.020099,  0.002426,
-0.016712, -0.003230, -0.010823,
0.044238, 0.007777, 0.012500), nrow = 10, ncol = 3, byrow = TRUE)

weights <- c(1/3, 1/3, 1/3)

portret <- as.xts(ret %*% weights, order.by = as.Date(1:10))

#-------------------output:-----------------------
round(SortinoRatio(portret, MAR = 0), 4)
                           [,1]
> Sortino Ratio (MAR = 0%) 0.1664

Aquí, la función en Python da el mismo resultado (hay una ligera diferencia para los decimales más altos):

return_test = returns.head(10)@weights

#-------------------output:-----------------------
print(np.round(SortinoRatio(return_test, T = 0),4))
0.1664

Hay una ligera desviación entre los dos resultados para más decimales ( >5 ), lo que podría atribuirse a los diferentes valores de precisión utilizados entre las lenguas. No obstante, espero que esto le ayude en su aplicación .

2 votos

Aprecio mucho tu explicación y el ejemplo de código, ¡gracias!

0 votos

Supongo que el rendimiento objetivo es 0 por defecto

1 votos

Elegí $T = 0$ en el ejemplo anterior para imitar el ratio de Sortino que intentaste especificar ayer, en tu pregunta ahora borrada. Es un parámetro definido por el usuario, y lo más fácil para mí, fue ponerlo igual a 0 :-)

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X