Respuesta

¿Es correcto el guión del Sortino Ratio?

2 respuestas

eastpeace

Cliente, bbp_participante, comunidad, sq-último, 305 respuestas.

Visitar el perfil

hace 4 años #257305

`/*
* Copyright (c) 2017-2018, StrategyQuant - Todos los derechos reservados.
*
* El código en este archivo fue hecho de buena fe de que es correcto y hace lo que debe.
* Si has encontrado un error en este código O tienes una sugerencia de mejora O quieres incluir
* su propio fragmento de código en nuestra biblioteca estándar, póngase en contacto con nosotros:
* https://roadmap.strategyquant.com
*
* Este código sólo puede ser utilizado dentro de los productos StrategyQuant.
* Todo propietario de una licencia válida (gratuita, de prueba o comercial) de cualquier producto StrategyQuant.
* está permitido utilizar, copiar, modificar o hacer trabajos derivados de este código libremente y sin limitaciones,
* para ser utilizado en todos los productos StrategyQuant y compartir sus modificaciones o trabajos derivados
* con la comunidad StrategyQuant.
*
* EL SOFTWARE SE PROPORCIONA "TAL CUAL", SIN GARANTÍA DE NINGÚN TIPO, EXPRESA O IMPLÍCITA,
* INCLUIDAS, ENTRE OTRAS, LAS GARANTÍAS DE COMERCIABILIDAD, IDONEIDAD PARA UN DETERMINADO
* FINALIDAD Y NO INFRACCIÓN. EN NINGÚN CASO LOS AUTORES SERÁN RESPONSABLES DE CUALQUIER RECLAMACIÓN, DAÑOS
* U OTRA RESPONSABILIDAD, YA SEA EN UNA ACCIÓN CONTRACTUAL, EXTRACONTRACTUAL O DE OTRO TIPO, DERIVADA DE,
* DE O EN RELACIÓN CON EL SOFTWARE O EL USO U OTRAS OPERACIONES CON EL SOFTWARE.
*
*/
paquete SQ.Columns.Databanks;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.strategyquant.lib.L;
import com.strategyquant.lib.SQTime;
import com.strategyquant.lib.SQUtils;
import com.strategyquant.lib.SettingsMap;
import com.strategyquant.tradinglib.DatabankColumn;
import com.strategyquant.tradinglib.Directions;
import com.strategyquant.tradinglib.Order;
import com.strategyquant.tradinglib.OrdersList;
importar com.strategyquant.tradinglib.PlTypes;
import com.strategyquant.tradinglib.SQStats;
import com.strategyquant.tradinglib.StatsTypeCombination;
import com.strategyquant.tradinglib.ValueTypes;

import SQ.Functions.StatFunctions;
import it.unimi.dsi.fastutil.doubles.DoubleArrayList;
import it.unimi.dsi.fastutil.ints.Int2DoubleAVLTreeMap;

public class Sortino extends DatabankColumna {
public static final Logger Log = LoggerFactory.getLogger("Sortino");

private final long DURACION_DIA = 24 * 60 * 60 * 1000;

//————————————————————————
//————————————————————————
//————————————————————————

public Sortino() {
super(L.t("Ratio Sortino"), DatabankColumn.Decimal2, ValueTypes.Maximize, 0, -1, 1);

this.setTooltip(L.t("Ratio Sortino (anualizado)"));

// restringir el cálculo de Sortino sólo para el dinero Tipo PL (no vamos a calcular Sortino por separado para % o pips resultados, es igual que para el dinero)
setPLTypeRestrictions(PlTypes.Money);

// restringir el cálculo de Sortino sólo para ambas direcciones, no calcularemos Sharpe para resultados sólo largos o sólo cortos.
setDirectionRestrictions(Directions.Both);
}

//————————————————————————

@Override
public double compute(SQStats stats, StatsTypeCombination combination, OrdersList ordersList, SettingsMap settings, SQStats statsLong, SQStats statsShort) throws Exception {

DoubleArrayList dailyReturnsPct = computeDailyReturn(ordersList);

double retornosMedio = StatFunctions.computeAverage(dailyReturnsPct);

double returnsStddev = computeLowStdev(returnsMean, dailyReturnsPct,0,-1);

double Sortino = Math.sqrt(252) * SQUtils.safeDivide(returnsMean, returnsStddev);

return round2(Sortino);
}

//————————————————————————

private DoubleArrayList computeDailyReturn(OrdersList ordersList) {
if(ordersList.size() == 0) {
devolver null;
}

// tomamos el beneficio anual de 5% como referencia para calcular el Ratio Sortino
doble referencia = 0,05/252;

// calcular la primera y la última fecha
long primeraFecha = Long.MAX_VALUE;
long últimaFecha = -1;

for(int i=0; i<ordersList.size(); i++) {
Pedido o = ordersList.get(i);

if(o.CloseTime < firstDate) {
primeraFecha = o.HoraCierre;
}

if(o.CloseTime > lastDate) {
últimaFecha = o.HoraCierre;
}
}

// arréglalo para que empiece el lunes
primeraFecha = SQTime.correctDayStart(primeraFecha);
int primeraFechaAbajo = SQTime.getDayOfWeek(primeraFecha);

// crear matriz de retornos para cada día que no sea sábado/domingo
DoubleArrayList returns = new DoubleArrayList();
int índice = 1;
long fechaInicio = primeraFecha;
while(true) {
int weekIndex = index+firstDateDow-1;
if(weekIndex > 7) {
int semanas = weekIndex / 7;
weekIndex -= semanas*7;
}
if(weekIndex % 6 != 0 && weekIndex % 7 != 0) {
// saltarse sábados y domingos
returns.add(-benchmark);
}

index++;

startDate += DURACION_DIA;

if(fechainicio > últimafecha) {
romper;
}
}

// ahora vaya a través de los pedidos y añada PctPL para cada pedido
for(int i=0; i<ordersList.size(); i++) {
Pedido o = ordersList.get(i);

int dow = SQTime.getDayOfWeek(o.CloseTime);
if(dow == 6 || dow == 7) {
// saltarse sábados y domingos
continuar;
}

long closeTime = SQTime.correctDayStart(o.CloseTime);

index = (int) ((closeTime - firstDate) / DAY_DURATION);

// deducir fines de semana
if(index > firstDateDow) {
índice -= 2;
}
int semanas = índice / 7;
índice -= semanas*2;

if(index = returns.size()) {
continuar;
}

double currentDayPL = returns.getDouble(index);
returns.set(index, currentDayPL+o.PctPL);
}

devuelva las devoluciones;
}

public static double computeLowStdev(double mean, DoubleArrayList values, int from, int to ) {
if(valores == null || valores.tamaño() == 0) {
Devuelve 0;
}

if(to == -1) {
a = valores.tamaño();
}

doble suma = 0, stdev, pl;
for (int i = desde; i < hasta; i++) {
pl = valores.getDouble(i);
suma += Math.pow((Math.min(pl - media,0)), 2d);
}
stdev = (double) Math.sqrt(suma / ((double) (a - desde)));
retorno (stdev);
}
}

0

tomas262

Administrador, sq-ultimate, 2 respuestas.

Visitar el perfil

hace 4 años #257432

Hola, he comprobado pero esto devuelve 0 para mí. Supongo que hay algún problema con la función computeLowStdev, pero no soy programador Java. Los desarrolladores revisarán el código Sortino por lo que podría ser añadido en las siguientes compilaciones SQ

0

eastpeace

Cliente, bbp_participante, comunidad, sq-último, 305 respuestas.

Visitar el perfil

hace 3 años #258033

 

Tiene resultado. Tal vez usted necesita reiniciar SQ y hacer la prueba de nuevo.

Pero acabo de copiar el ratio de Sharpe y no estoy seguro de si es correcto. Especialmente me siento confundido acerca de las estadísticas de rendimiento diario.

0

Viendo 2 respuestas - de la 1 a la 2 (de un total de 2)