Risposta

Il Sortino Ratio è un copione corretto?

2 risposte

eastpeace

Cliente, bbp_partecipante, comunità, sq-ultimate, 305 risposte.

Visita il profilo

4 anni fa #257305

`/*
* Copyright (c) 2017-2018, StrategyQuant - Tutti i diritti riservati.
*
* Il codice contenuto in questo file è stato realizzato in buona fede, in modo che sia corretto e faccia ciò che dovrebbe.
* Se avete trovato un bug in questo codice O avete un suggerimento per un miglioramento O volete includere
* il vostro frammento di codice nella nostra libreria standard, contattateci all'indirizzo:
* https://roadmap.strategyquant.com
*
* Questo codice può essere utilizzato solo per i prodotti StrategyQuant.
* Ogni proprietario di una licenza valida (gratuita, di prova o commerciale) di qualsiasi prodotto StrategyQuant
* è consentito usare, copiare, modificare o fare lavori derivati da questo codice senza limitazioni,
* da utilizzare in tutti i prodotti StrategyQuant e condividerne le modifiche o i lavori derivati
* con la comunità StrategyQuant.
*
* IL SOFTWARE VIENE FORNITO "COSÌ COM'È", SENZA ALCUN TIPO DI GARANZIA, ESPLICITA O IMPLICITA,
* COMPRESE, MA NON SOLO, LE GARANZIE DI COMMERCIABILITÀ, DI IDONEITÀ PER UN PARTICOLARE
* SCOPO E NON VIOLAZIONE. IN NESSUN CASO GLI AUTORI POTRANNO ESSERE RITENUTI RESPONSABILI PER QUALSIASI RECLAMO, DANNO
* O ALTRA RESPONSABILITÀ, SIA IN UN'AZIONE CONTRATTUALE, CHE IN UN ILLECITO O ALTRO, DERIVANTE DA,
* DA O IN RELAZIONE AL SOFTWARE O ALL'USO O AD ALTRI RAPPORTI CON IL SOFTWARE.
*
*/
pacchetto SQ.Columns.Databanks;

importare org.slf4j.Logger;
importare org.slf4j.LoggerFactory;

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

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

public class Sortino extends DatabankColumn {
public static final Logger Log = 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 (annualizzato)");

// limitiamo il calcolo di Sortino solo per il tipo di PL denaro (non calcoleremo Sortino separati per i risultati % o pip, è lo stesso che per il denaro)
setPLTypeRestrictions(PlTypes.Money);

// limitiamo il calcolo di Sortino solo per entrambe le direzioni, non calcoleremo Sharpe per risultati solo Long o solo Short
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);

restituire round2(Sortino);
}

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

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

// prendiamo il profitto annuo di 5% come benchmark per il calcolo del Sortino Ratio
doppio benchmark = 0,05/252;

// calcolare la prima e l'ultima data
long firstDate = Long.MAX_VALUE;
long lastDate = -1;

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

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

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

// sistemare il tutto in modo che inizi lunedì
firstDate = SQTime.correctDayStart(firstDate);
int firstDateDow = SQTime.getDayOfWeek(firstDate);

// creare un array di rendimenti per ogni giorno che non è sabato/domenica
DoubleArrayList returns = new DoubleArrayList();
int index = 1;
long startDate = firstDate;
while(true) {
int weekIndex = index+firstDateDow-1;
if(weekIndex > 7) {
int settimane = weekIndex / 7;
weekIndex -= settimane*7;
}
if(weekIndex % 6 != 0 && weekIndex % 7 != 0) {
// saltare il sabato e la domenica
returns.add(-benchmark);
}

indice++;

startDate += DAY_DURATION;

se(data di inizio > data di fine) {
pausa;
}
}

// ora scorrere gli ordini e aggiungere PctPL per ogni ordine
for(int i=0; i<ordersList.size(); i++) {
Ordine o = ordersList.get(i);

int dow = SQTime.getDayOfWeek(o.CloseTime);
if(dow == 6 || dow == 7) {
// saltare il sabato e la domenica
continuare;
}

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

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

// dedurre i fine settimana
se(indice > firstDateDow) {
indice -= 2;
}
int settimane = indice / 7;
indice -= settimane*2;

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

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

ritorno;
}

public static double computeLowStdev(double mean, DoubleArrayList values, int from, int to ) {
if(values == null || values.size() == 0) {
restituire 0;
}

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

double sum = 0, stdev, pl;
per (int i = da; i < a; i++) {
pl = values.getDouble(i);
somma += Math.pow((Math.min(pl - media,0)), 2d);
}
stdev = (double) Math.sqrt(sum / ((double) (to - from)));
ritorno (stdev);
}
}

0

tomas262

Amministratore, sq-ultimate, 2 risposte.

Visita il profilo

4 anni fa #257432

Salve, ho controllato ma il risultato è 0 per me. Credo che ci sia qualcosa di sbagliato nella funzione computeLowStdev, ma non sono un codificatore Java. Gli sviluppatori rivedranno il codice di Sortino in modo che possa essere aggiunto alle successive versioni di SQ.

0

eastpeace

Cliente, bbp_partecipante, comunità, sq-ultimate, 305 risposte.

Visita il profilo

3 anni fa #258033

 

Il risultato è stato ottenuto. Forse è necessario riavviare SQ e ripetere il test.

Ma ho appena copiato lo Sharpe ratio e non sono sicuro che sia corretto. In particolare mi sento confuso sulle statistiche del rendimento giornaliero.

0

Stai visualizzando 2 risposte - da 1 al 2 (di 2 totali)