Librerías: SingleTesterCache

 

SingleTesterCache:

Datos de una sola pasada del probador.

SingleTesterCache

Author: fxsaber

 

Todas las estadísticas que están en el Informe de Ejecución Única están disponibles. Anteriormente, mucho de esto era imposible de obtener incluso si usted tiene la fuente del Asesor Experto.

  double            ghpr;                    // transacción media geométrica 
  double            ghprpercent;             // transacción media geométrica en porcentaje 
  double            ahpr;                    // media aritmética de la transacción 
  double            ahprpercent;             // media aritmética de las transacciones en porcentaje 
  double            zscore;                  // prueba en serie 
  double            zscorepercent;           // prueba en serie en porcentaje 
  double            lrcorr;                  // coeficiente de correlación de regresión lineal 
  double            lrstderror;              // error estándar de la desviación del equilibrio de la regresión lineal 
  double            corr_prf_mfe;            // correlación entre mfe y beneficio 
  double            corr_prf_mae;            // correlación entre mae y beneficio 
  double            corr_mfe_mae;            // correlación entre mae y mfe 
  double            mfe_a;                   // correlación entre mfe y beneficio, coeficiente de la recta de regresión lineal 
  double            mfe_b;                   // correlación entre mfe y beneficio, coeficiente de la recta de regresión lineal 
  double            mae_a;                   // correlación entre mae y beneficio, coeficiente de la recta de regresión lineal 
  double            mae_b;                   // correlación entre mae y beneficio, coeficiente de la recta de regresión lineal 
  UINT              in_per_hours[24];        // distribución de las entradas por horas 
  UINT              in_per_week_days[7];     // distribución de las entradas por día de la semana 
  UINT              in_per_months[12];       // distribución de las entradas por mes 
  double            out_per_hours[24][2];    // distribución de las entradas por horas 
  double            out_per_week_days[7][2]; // distribución de las entradas por día de la semana 
  double            out_per_months[12][2];   // distribución de las entradas por mes 
  INT64             holding_time_min;        // tiempo mínimo de mantenimiento de la posición 
  INT64             holding_time_max;        // tiempo máximo de mantenimiento de la posición 
  INT64             holding_time_avr;        // tiempo medio de mantenimiento de la posición
 

La versión actual del formato tst no dispone de los siguientes datos

  • Tiempo en milisegundos.
  • PositionID.
  • MagicNumber.
Esto impone limitaciones en los escenarios de uso.
 

Reproducción de varios errores. Ejecutar el Asesor Experto en el Probador en una cuenta de cobertura.

#include <MT4Orders.mqh> // https://www.mql5.com/es/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
    }
}


Obtenemos lo siguiente

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


A continuación, leemos el archivo tst correspondiente con el script.

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

void OnStart()
{  
  uchar Bytes2[];
  
  if (MTTESTER::GetLastTstCache(Bytes2) != -1) // Si fuera posible leer el último registro de caché de una sola ejecución
  {
    const SINGLETESTERCACHE SingleTesterCache(Bytes2); // Condúcelo al objeto apropiado.

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


Nos mostrará los datos de las posiciones

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


Si comparamos todo lo expuesto en este post, se formulan los siguientes bugs.

  • Id's nulos en lugar de los id's correctos.
  • Comisiones y swap no se tienen en cuenta a la hora de calcular el beneficio.
  • La retirada de operaciones se incluye por error en el número de posiciones cerradas.
 

En lugar de set-files ahora uso tst-files. Puedes cambiar entre ellos muy rápidamente, teniendo no sólo parámetros de entrada, sino también backtests completos.

Es una pena que sea imposible combinar diferentes TSs en una cartera debido a la falta de datos de milisegundos en tst.


Espero que los desarrolladores empiecen a utilizar al máximo los campos existentes.

INT64             TradeDeal::time_create;             // hora de creación del registro

INT64             TradeOrder::time_setup;             // hora de recepción del pedido del cliente al sistema
INT64             TradeOrder::time_done;              // momento de la anulación del pedido

escribiendo el valor del tiempo en milisegundos en lugar de segundos.


En general, en la práctica para demostrar toda la frescura de usar tst no dan defectos muy pequeños de tst. Debería corregirse.

 
A menudo es necesario examinar con más detalle el gráfico de equilibrio de una sola pasada.
// Gráfico interactivo de balance de una sola pasada.

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

#include <..\Files\Graph.mqh> // https://www.mql5.com/es/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) // Si fuera posible leer el último registro de caché de una sola ejecución
  {
    const SINGLETESTERCACHE SingleTesterCache(Bytes2); // Condúcelo al objeto correspondiente.
    
    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);      
  }
}


Si sustituimos

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

es un gráfico de equidad.

 

El volumen de operaciones/órdenes se escribe incorrectamente en tst. Siempre se calcula como si SYMBOL_TRADE_CONTRACT_SIZE = 100 000.

Si se establece un valor diferente, no tiene ningún efecto sobre el valor del volumen en tst.

 
fxsaber:

en la práctica para demostrar toda la frescura del uso de tst en la práctica no se da en absoluto por pequeñas deficiencias de tst. Debería corregirse.

Elprimer trago.

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

No sé cómo ocurre en los blogs, ¿se señala de alguna manera la aparición de un nuevo comentario (si no es una respuesta)? ¿O es mejor publicar en uno de los hilos del foro donde los nuevos comentarios son visibles?

¿Por qué no lo publican en la KB? Sería más cómodo.

Entonces, ¿dónde publicar para obtener una respuesta rápida?