Resposta

O script do Sortino Ratio está correto?

2 respostas

Eastpeace

Cliente, bbp_participant, community, sq-ultimate, 305 respostas.

Perfil da visita

4 anos atrás #257305

`/*
* Copyright (c) 2017-2018, StrategyQuant - Todos os direitos reservados.
*
* O código contido neste arquivo foi criado de boa-fé, com a certeza de que está correto e faz o que deveria.
* Se você encontrou um bug neste código OU tem uma sugestão de melhoria OU deseja incluir
* seu próprio trecho de código em nossa biblioteca padrão, entre em contato conosco pelo e-mail:
* https://roadmap.strategyquant.com
*
* Esse código pode ser usado somente em produtos StrategyQuant.
* Todo proprietário de uma licença válida (gratuita, de teste ou comercial) de qualquer produto StrategyQuant
* tem permissão para usar, copiar, modificar ou fazer trabalhos derivados desse código livremente, sem limitações,
* para ser usado em todos os produtos StrategyQuant e compartilhar suas modificações ou trabalhos derivados
* com a comunidade StrategyQuant.
*
* O SOFTWARE É FORNECIDO "NO ESTADO EM QUE SE ENCONTRA", SEM GARANTIA DE QUALQUER TIPO, EXPRESSA OU IMPLÍCITA,
* INCLUINDO, MAS NÃO SE LIMITANDO ÀS GARANTIAS DE COMERCIALIZAÇÃO, ADEQUAÇÃO A UM DETERMINADO
* FINALIDADE E NÃO VIOLAÇÃO. EM NENHUMA HIPÓTESE OS AUTORES SERÃO RESPONSÁVEIS POR QUALQUER REIVINDICAÇÃO, DANO
* OU OUTRA RESPONSABILIDADE, SEJA EM UMA AÇÃO DE CONTRATO, ATO ILÍCITO OU DE OUTRA FORMA, DECORRENTE DE,
* FORA OU EM CONEXÃO COM O SOFTWARE OU COM O USO OU OUTRAS NEGOCIAÇÕES COM O SOFTWARE.
*
*/
pacote SQ.Columns.Databanks;

importar org.slf4j.Logger;
importar 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;
import com.strategyquant.tradinglib.PlTypes;
import com.strategyquant.tradinglib.SQStats;
import com.strategyquant.tradinglib.StatsTypeCombination;
import com.strategyquant.tradinglib.ValueTypes;

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

public class Sortino extends DatabankColumn {
logger final estático público Logger = LoggerFactory.getLogger("Sortino");

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

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

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

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

// restringir o cálculo do Sortino apenas para o PL Type em dinheiro (não calcularemos Sortino separado para resultados % ou pips, é o mesmo que para dinheiro)
setPLTypeRestrictions(PlTypes.Money);

// restringir o cálculo do Sortino apenas para ambas as direções, não calcularemos o Sharpe para resultados apenas longos ou curtos
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 returnsMean = 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) {
Se (ordersList.size() == 0) {
retornar nulo;
}

// tomamos o lucro anual de 5% como referência para calcular o Sortino Ratio
benchmark duplo = 0,05/252;

// calcular a primeira e a última data
long firstDate = Long.MAX_VALUE;
long lastDate = -1;

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

se (o.CloseTime < firstDate) {
firstDate = o.CloseTime;
}

se (o.CloseTime > lastDate) {
lastDate = o.CloseTime;
}
}

// corrigi-lo para que comece na segunda-feira
firstDate = SQTime.correctDayStart(firstDate);
int firstDateDow = SQTime.getDayOfWeek(firstDate);

// criar uma matriz de retornos para cada dia que não seja sábado/domingo
DoubleArrayList returns = new DoubleArrayList();
índice int = 1;
long startDate = firstDate;
while(true) {
int weekIndex = index+firstDateDow-1;
if(weekIndex > 7) {
int weeks = weekIndex / 7;
weekIndex -= weeks*7;
}
if(weekIndex % 6 != 0 && weekIndex % 7 != 0) {
// pular sábados e domingos
returns.add(-benchmark);
}

índice++;

startDate += DAY_DURATION;

se (startDate > lastDate) {
pausa;
}
}

// Agora, examine os pedidos e adicione PctPL para cada pedido
for(int i=0; i<ordersList.size(); i++) {
Ordem o = ordersList.get(i);

int dow = SQTime.getDayOfWeek(o.CloseTime);
se(dow == 6 || dow == 7) {
// pular sábados e domingos
continuar;
}

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

índice = (int) ((closeTime - firstDate) / DAY_DURATION);

// deduzir finais de semana
se (índice > firstDateDow) {
índice -= 2;
}
int semanas = índice / 7;
índice -= semanas*2;

se(índice = returns.size()) {
continuar;
}

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

retornos;
}

public static double computeLowStdev(double mean, DoubleArrayList values, int from, int to ) {
Se (valores == nulo || valores.tamanho() == 0) {
retornar 0;
}

se(to == -1) {
to = values.size();
}

double sum = 0, stdev, pl;
for (int i = from; i < to; i++) {
pl = values.getDouble(i);
sum += Math.pow((Math.min(pl - mean,0)), 2d);
}
stdev = (double) Math.sqrt(sum / ((double) (to - from)));
retorno (stdev);
}
}

0

tomas262

Administrador, sq-ultimate, 2 respostas.

Perfil da visita

4 anos atrás #257432

Olá, eu verifiquei, mas o resultado é 0 para mim. Acho que há algo errado com a função computeLowStdev, mas não sou programador de Java. Os desenvolvedores revisarão o código do Sortino para que ele possa ser adicionado às próximas compilações do SQ

0

Eastpeace

Cliente, bbp_participant, community, sq-ultimate, 305 respostas.

Perfil da visita

3 anos atrás #258033

 

Ele tem resultado. Talvez você precise reiniciar o SQ e fazer um novo teste.

Mas acabei de copiar o índice de Sharpe e não tenho certeza se está correto. Além disso, estou confuso com as estatísticas de retorno diário.

0

Visualizando 2 respostas - 1 até 2 (de um total de 2)