Répondre

Le script du ratio de Sortino est-il correct ?

2 réponses

paix à l'est

Client, bbp_participant, community, sq-ultimate, 305 réponses.

Visiter le profil

Il y a 4 ans #257305

`/*
* Copyright (c) 2017-2018, StrategyQuant - Tous droits réservés.
*
* Le code contenu dans ce fichier a été élaboré en toute bonne foi, en pensant qu'il est correct et qu'il fait ce qu'il doit faire.
* Si vous avez trouvé un bogue dans ce code OU si vous avez une suggestion d'amélioration OU si vous voulez inclure
* votre propre extrait de code dans notre bibliothèque standard, veuillez nous contacter à l'adresse suivante :
* https://roadmap.strategyquant.com
*
* Ce code ne peut être utilisé que pour les produits StrategyQuant.
* Tout propriétaire d'une licence valide (gratuite, d'essai ou commerciale) de n'importe quel produit StrategyQuant.
* Il est permis d'utiliser, de copier, de modifier ou de faire un travail dérivé de ce code sans aucune limitation,
* à utiliser dans tous les produits de StrategyQuant et à partager ses modifications ou travaux dérivés
* avec la communauté StrategyQuant.
*
* LE LOGICIEL EST FOURNI "EN L'ÉTAT", SANS GARANTIE D'AUCUNE SORTE, EXPRESSE OU IMPLICITE,
* Y COMPRIS, MAIS SANS S'Y LIMITER, LES GARANTIES DE QUALITÉ MARCHANDE, D'ADÉQUATION À UN USAGE PARTICULIER, D'EFFICACITÉ ET D'EFFICIENCE.
* LES AUTEURS NE SONT EN AUCUN CAS RESPONSABLES D'UNE QUELCONQUE RÉCLAMATION, D'UN QUELCONQUE DOMMAGE OU D'UN QUELCONQUE PRÉJUDICE. EN AUCUN CAS LES AUTEURS NE POURRONT ETRE TENUS RESPONSABLES DE TOUTE RECLAMATION, DE TOUT DOMMAGE
* OU TOUTE AUTRE RESPONSABILITÉ, QUE CE SOIT DANS LE CADRE D'UNE ACTION CONTRACTUELLE, DÉLICTUELLE OU AUTRE, DÉCOULANT DE,
* DE OU EN RELATION AVEC LE LOGICIEL OU L'UTILISATION OU D'AUTRES TRANSACTIONS DANS LE LOGICIEL.
*
*/
package 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 ;
import 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 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("Ratio de Sortino (annualisé)")) ;

// restreindre le calcul de Sortino uniquement pour le type d'argent PL (nous ne calculerons pas de Sortino séparé pour les résultats % ou pips, c'est la même chose que pour l'argent).
setPLTypeRestrictions(PlTypes.Money) ;

// restreindre le calcul de Sortino uniquement pour les deux directions, nous ne calculerons pas Sharpe pour les résultats Long uniquement ou Short uniquement.
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) {
if(ordersList.size() == 0) {
retourner null ;
}

// nous prenons le bénéfice annuel de 5% comme référence pour le calcul du ratio de Sortino
double benchmark = 0,05/252 ;

// calculer la première et la dernière date
long firstDate = Long.MAX_VALUE ;
long lastDate = -1 ;

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

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

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

// le fixer de manière à ce qu'il commence le lundi
firstDate = SQTime.correctDayStart(firstDate) ;
int firstDateDow = SQTime.getDayOfWeek(firstDate) ;

// créer un tableau de rendements pour chaque jour qui n'est pas un samedi/dimanche
DoubleArrayList returns = new DoubleArrayList() ;
int index = 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) {
// sauter les samedis et dimanches
returns.add(-benchmark) ;
}

index++ ;

startDate += DAY_DURATION ;

if(startDate > lastDate) {
pause ;
}
}

// passer maintenant en revue les commandes et ajouter le PctPL pour chacune d'entre elles
for(int i=0 ; i<ordersList.size() ; i++) {
Ordre o = ordersList.get(i) ;

int dow = SQTime.getDayOfWeek(o.CloseTime) ;
if(dow == 6 || dow == 7) {
// sauter les samedis et dimanches
continuer ;
}

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

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

// déduire les week-ends
if(index > firstDateDow) {
indice -= 2 ;
}
int weeks = index / 7 ;
index -= semaines*2 ;

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

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

les retours ;
}

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

if(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))) ;
retour (stdev) ;
}
}

0

tomas262

Administrateur, sq-ultimate, 2 réponses.

Visiter le profil

Il y a 4 ans #257432

Bonjour, j'ai vérifié mais le résultat est 0 pour moi. Je suppose qu'il y a un problème avec la fonction computeLowStdev mais je ne suis pas un codeur Java. Les développeurs vont revoir le code Sortino afin qu'il puisse être ajouté dans les prochaines versions de SQ.

0

paix à l'est

Client, bbp_participant, community, sq-ultimate, 305 réponses.

Visiter le profil

il y a 3 ans #258033

 

Il y a un résultat. Il est peut-être nécessaire de redémarrer le SQ et de refaire le test.

Mais je viens de copier le ratio de Sharpe et je ne suis pas sûr qu'il soit correct. En particulier, je ne comprends pas bien les statistiques de rendement journalier.

0

Affichage de 2 réponses de 1 à 2 (sur un total de 2)