Librerie: SingoloTesterCache

 

SingoloTesterCache:

Dati del tester a passaggio singolo.

SingoloTesterCache

Author: fxsaber

 

Sono disponibili tutte le statistiche presenti nel Rapporto di esecuzione singola. In precedenza, molte di queste statistiche erano impossibili da ottenere anche se si disponeva della fonte dell'Expert Advisor.

  double            ghpr;                    // media geometrica della transazione 
  double            ghprpercent;             // media geometrica delle transazioni in percentuale 
  double            ahpr;                    // media aritmetica della transazione 
  double            ahprpercent;             // media aritmetica delle transazioni in percentuale 
  double            zscore;                  // test in serie 
  double            zscorepercent;           // test seriale in percentuale 
  double            lrcorr;                  // coefficiente di correlazione della regressione lineare 
  double            lrstderror;              // errore standard della deviazione dell'equilibrio dalla regressione lineare 
  double            corr_prf_mfe;            // correlazione tra mfe e profitto 
  double            corr_prf_mae;            // correlazione tra mae e profitto 
  double            corr_mfe_mae;            // correlazione tra mae e mfe 
  double            mfe_a;                   // correlazione tra mfe e profitto, coefficiente della retta di regressione lineare 
  double            mfe_b;                   // correlazione tra mfe e profitto, coefficiente della retta di regressione lineare 
  double            mae_a;                   // correlazione tra mae e profitto, coefficiente della retta di regressione lineare 
  double            mae_b;                   // correlazione tra mae e profitto, coefficiente della retta di regressione lineare 
  UINT              in_per_hours[24];        // distribuzione degli input per ore 
  UINT              in_per_week_days[7];     // distribuzione degli ingressi per giorno della settimana 
  UINT              in_per_months[12];       // distribuzione degli input per mese 
  double            out_per_hours[24][2];    // distribuzione degli input per ore 
  double            out_per_week_days[7][2]; // distribuzione degli ingressi per giorno della settimana 
  double            out_per_months[12][2];   // distribuzione degli input per mese 
  INT64             holding_time_min;        // tempo minimo di mantenimento della posizione 
  INT64             holding_time_max;        // tempo massimo di mantenimento della posizione 
  INT64             holding_time_avr;        // tempo medio di mantenimento della posizione
 

La versione attuale del formato tst non contiene i seguenti dati

  • Tempo in millisecondi.
  • PositionID.
  • Numero magico.
Ciò impone limitazioni negli scenari di utilizzo.
 

Riproduzione di diversi bug. Eseguire l'Expert Advisor nel Tester su un conto di copertura.

#include <MT4Orders.mqh> // https://www.mql5.com/it/code/16006

#define  Ask SymbolInfoDouble(_Symbol, SYMBOL_ASK)

#define  PAUSE 100000

void OnTick()
{
  static bool FirstRun = true;
  
  if (FirstRun)
  {
    OrderSend(_Symbol, OP_BUY, 1, Ask, 0, 0, 0);
    Sleep(PAUSE);
    
    OrderSend(_Symbol, OP_BUY, 2, Ask, 0, 0, 0);
    Sleep(PAUSE);

    if (OrderSelect(0, SELECT_BY_POS))
      OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0);
    Sleep(PAUSE * 2);
    
    if (OrderSelect(0, SELECT_BY_POS))
      OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 0);
    Sleep(PAUSE * 2);

    TesterWithdrawal(100);    
    
    FirstRun = false;
  }
}

void OnDeinit( const int )
{
  const int Total = OrdersHistoryTotal();
  
  for (int i = 0; i < Total; i++)
    if (OrderSelect(i, SELECT_BY_POS, MODE_HISTORY))
    {
      OrderPrint();
      
      Print(OrderTicketID()); // MT5-PositionID
    }
}


Otteniamo questo

2020.01.08 23:59:58   #1 2020.01.01 00:00:00 balance 0.00 0.00000 0.00000 0.00000 2020.01.01 00:00:00 0.00000 0.00 0.00 100000.00 0
2020.01.08 23:59:58   0
2020.01.08 23:59:58   #4 2020.01.02 06:00:00 buy 1.00 EURUSD 1.12137 0.00000 0.00000 2020.01.02 06:03:20 1.12132 -3.56 0.00 -4.46 0
2020.01.08 23:59:58   2
2020.01.08 23:59:58   #5 2020.01.02 06:01:40 buy 2.00 EURUSD 1.12137 0.00000 0.00000 2020.01.02 06:06:40 1.12129 -7.14 0.00 -14.27 0
2020.01.08 23:59:58   3
2020.01.08 23:59:58   #6 2020.01.02 06:10:00 balance 0.00 0.00000 0.00000 0.00000 2020.01.02 06:10:00 0.00000 0.00 0.00 -100.00 withdrawal 0
2020.01.08 23:59:58   0


Successivamente, leggiamo il file tst corrispondente con lo script.

#include <fxsaber\SingleTesterCache\SingleTesterCache.mqh> // https://www.mql5.com/it/code/27611
#include <fxsaber\MultiTester\MTTester.mqh> // https://www.mql5.com/it/code/26132

void OnStart()
{  
  uchar Bytes2[];
  
  if (MTTESTER::GetLastTstCache(Bytes2) != -1) // Se fosse possibile leggere l'ultimo record della cache di una singola esecuzione
  {
    const SINGLETESTERCACHE SingleTesterCache(Bytes2); // Inserirlo nell'oggetto appropriato.

    for (int i = 0; i < ArraySize(SingleTesterCache.Positions); i++)
      Print(SingleTesterCache.Positions[i].ToString());
  }
}


Verranno visualizzati i dati sulle posizioni

id = 0
mfe = 0.0
mae = -8.029999999999999
profit = -4.46
lifetime = 00:03:20

id = 0
mfe = 0.0
mae = -21.4
profit = -14.27
lifetime = 00:05:00

id = 0
mfe = 0.0
mae = 0.0
profit = 0.0
lifetime = 00:00:00


Se confrontiamo tutto quanto riportato in questo post, vengono formulati i seguenti bug.

  • Id nulli al posto di quelli corretti.
  • Le commissioni e gli swap non vengono presi in considerazione nel calcolo del profitto.
  • Il ritiro dalla negoziazione viene erroneamente incluso nel numero di posizioni di trading chiuse.
 

Al posto dei set-file ora uso i tst-file. È possibile passare da un file all'altro molto rapidamente, avendo a disposizione non solo i parametri di input, ma anche i backtest completi.

È un peccato che sia impossibile combinare diversi TS in un portafoglio a causa della mancanza di dati al millisecondo in tst.


Spero che gli sviluppatori inizino a utilizzare al meglio i campi esistenti.

INT64             TradeDeal::time_create;             // ora di creazione del record

INT64             TradeOrder::time_setup;             // ora di ricezione dell'ordine dal cliente al sistema
INT64             TradeOrder::time_done;              // momento della cancellazione dell'ordine

scrivendo il valore del tempo in millisecondi invece che in secondi.


In generale, nella pratica per dimostrare tutte le comodità dell'uso di tst non si danno difetti molto piccoli di tst. Dovrebbe essere corretto.

 
Spesso è necessario esaminare il grafico del bilancio a passaggio singolo in modo più dettagliato.
// Grafico interattivo del bilancio a passaggio singolo.

#include <fxsaber\SingleTesterCache\SingleTesterCache.mqh> // https://www.mql5.com/it/code/27611
#include <fxsaber\MultiTester\MTTester.mqh> // https://www.mql5.com/it/code/26132

#include <..\Files\Graph.mqh> // https://www.mql5.com/it/code/18801

#import "shell32.dll"
  int ShellExecuteW( int, string, string, string, string, int );
#import

#define  BASEPATH (::TerminalInfoString(TERMINAL_DATA_PATH) + "\\MQL5\\Files\\")

bool CreateBalanceData( const SINGLETESTERCACHE &SingleTesterCache, const string FileName = "exdat.txt" )
{
  const int handle = FileOpen(FileName, FILE_WRITE | FILE_TXT | FILE_ANSI);
  const bool Res = (handle != INVALID_HANDLE);

  if (Res)
  {
    FileWriteString(handle, "var dat1=[\n");
    
    for (uint i = 0; i < SingleTesterCache.Header.equities_total; i++)
      FileWriteString(handle, "[" + (string)((long)SingleTesterCache.TradeState[i].time * 1000) + "," + ::DoubleToString(SingleTesterCache.TradeState[i].balance, 2) + "],\n");

    FileWriteString(handle, "];\n");
    FileWriteString(handle, "var T1=dat1[0][0];\n");
    FileWriteString(handle, "var T2=dat1[dat1.length-1][0];\n");
    FileWriteString(handle, "var nTrades=dat1.length;\n");
    FileWriteString(handle, "var Balance=" + ::DoubleToString(SingleTesterCache.TradeState[SingleTesterCache.Header.equities_total - 1].balance, 2) + ";\n");
    FileWriteString(handle, "var Currency=\"" + (SingleTesterCache.Header.trade_pips ? "Pips" : SingleTesterCache.Header.trade_currency[]) + "\";\n");

    FileClose(handle);
  }

  return(Res);
}

void OnStart()
{  
  uchar Bytes2[];
  
  if (MTTESTER::GetLastTstCache(Bytes2) != -1) // Se fosse possibile leggere l'ultimo record della cache di una singola esecuzione
  {
    const SINGLETESTERCACHE SingleTesterCache(Bytes2); // Inserirlo nell'oggetto corrispondente.
    
    const string FileName = "Report.htm";
    uchar Array[];    
    
    if ((StringToCharArray(StrMQH, Array) > 0) && FileSave(FileName, Array) && CreateBalanceData(SingleTesterCache))
      ShellExecuteW(0, "Open", BASEPATH + FileName, NULL, NULL, 3);      
  }
}


Se sostituiamo

TradeState[i].balance -> TradeState[i].equity

è un grafico azionario.

 

Il volume degli scambi/ordini è scritto in modo errato in tst. Viene sempre calcolato come se SYMBOL_TRADE_CONTRACT_SIZE = 100 000.

Se viene impostato un valore diverso, non ha alcun effetto sul valore del volume in tst.

 
fxsaber:

in pratica, per dimostrare che l'utilità dell'uso di tst nella pratica non è affatto data da piccole carenze di tst. Dovrebbe essere corretto.

Laprima rondine.

TesterPortfolio - портфель ТС
TesterPortfolio - портфель ТС
  • www.mql5.com
Возьмем третий пункт. Допустим, взяли несколько приглянувшихся советников из Маркета. Настроили их для каждого символа. TesterPortfolio запустит все варианты одновременно, показав общую торговую статистику (просадка эквити на реальных тиках и т.д.). Чаще всего использую для оценки диверсификации различных настроек своих ТС. Использование. На...
 
TesterPortfolio - портфель ТС
TesterPortfolio - портфель ТС
  • 2020.01.16
  • www.mql5.com
В приложении советник/робот, который объединяет несколько независимых одиночных проходов MT5-Тестера в один. Сценарии использования. Чужой советник с закрытым исходным кодом не запускается в MT5-Визуализаторе. TesterPortfolio сможет немного помочь. Сбор статистики прямо во время торговли советников с закрытым исходным кодом. Например...
 
 

Non so come avvenga nei blog, la comparsa di un nuovo commento (se non è una risposta) viene segnalata in qualche modo? O è meglio postare in una delle discussioni del forum dove i nuovi commenti sono visibili?

Perché non l'hanno pubblicato nella KB? Sarebbe più comodo.

Quindi dove postare per avere una risposta immediata?