Asesores Expertos: Programación en MQL5 para tráders: códigos fuente del libro: Parte 6. - página 3

 
hini #property tester_set "FrameTransfer.set" (extensión de archivo tester set inválida, '*.set' esperado FrameTransfer.mq5)

Debe cambiarse así para que compile correctamente: #property tester_set "\Presets\\FrameTransfer.set"

Incluso `#property tester_set "/Presets/FrameTransfer.set"` fallará.

Tal vez usted podría modificar la descripción en el libro de algoritmos:


Corrección disponible en la build 5506.
 
Alain Verleyen #:
Corrección disponible en la versión 5506.
Gracias.
 
Stanislav Korotky optimización personalizado basado en R2 - RSquared.mqh, en el que se ha corregido el cálculo para el caso de lotes variables.

La calidad de la estimación ha mejorado notablemente: a juzgar por la tabla de resultados de la optimización, se ha obtenido la combinación del factor de recuperación y los parámetros de Sharpe.

Ejemplo de utilización.

Atención. Si se negocian diferentes símbolos, para obtener una estimación adecuada de los volúmenes, se deben convertir de lotes al valor en la moneda de depósito, por ejemplo (una de las variantes simplificadas):

#include <MQL5Book/DealFilter.mqh>
#include <MQL5Book/RSquared.mqh>

template<typename T>
union Type2Bytes
{
   T d;
   uchar bytes[sizeof(T)];
};

double OnTester()
{
   HistorySelect(0, LONG_MAX);
   
   #define   STAT_PROPS 5
   
   const ENUM_DEAL_PROPERTY_DOUBLE props[STAT_PROPS] =
   {
      DEAL_PROFIT, DEAL_SWAP, DEAL_COMMISSION, DEAL_FEE, DEAL_VOLUME
   };
   double expenses[][STAT_PROPS];
   ulong tickets[]; // usado aquí sólo para coincidir con el prototipo 'select', pero útil para depuración
   
   DealFilter filter;
   filter.let(DEAL_TYPE, (1 << DEAL_TYPE_BUY) | (1 << DEAL_TYPE_SELL), IS::OR_BITWISE)
      .let(DEAL_ENTRY, (1 << DEAL_ENTRY_OUT) | (1 << DEAL_ENTRY_INOUT) | (1 << DEAL_ENTRY_OUT_BY), IS::OR_BITWISE)
      .select(props, tickets, expenses);

   const int n = ArraySize(tickets);
   
   double balance[];
   double volumes[]; // tener en cuenta los volúmenes comerciales para utilizar el criterio R2
   
   ArrayResize(balance, n + 1);
   balance[0] = 0;
   ArrayResize(volumes, n + 1);
   volumes[0] = 0;

   MapArray<ulong,double> sym2value; // símbolo hash a valor de 1 lote
   
   for(int i = 0; i < n; ++i)
   {
      const string s = HistoryDealGetString(tickets[i], DEAL_SYMBOL);

      double value = 1;
      Type2Bytes<ulong> sym;
      ArrayInitialize(sym.bytes, 0);
      StringToCharArray(s, sym.bytes);
      int idx = sym2value.find(sym.d);
      if(idx == -1) // aún no hay registro del valor del símbolo por lote
      {
         const double price = SymbolInfoDouble(s, SYMBOL_ASK);
         const double pt = SymbolInfoDouble(s, SYMBOL_POINT);
         double profit = 1;
         ResetLastError();
         if(!OrderCalcProfit(ORDER_TYPE_BUY, s, 1, price, price + pt, profit)) // NB: estimación aproximada, ya que utiliza el tipo de cambio actual de la divisa de la cuenta
         {
            // WARN(StringFormat("Error OrderCalcProfit: %s %d ", s, _LastError));
         }
         value = profit * (price / pt); // Nota: aquí no se aplica el efecto palanca
         idx = sym2value.put(sym.d, value);
      }
      else
      {
         value = sym2value.getValue(idx);
      }
   
      double result = 0;
      for(int j = 0; j < STAT_PROPS - 1; ++j) // bucle a través de todos los accesorios solicitados excepto para el volumen de operaciones
      {
         result += expenses[i][j];
      }
      // utilizar los volúmenes como modelo - más inversiones - más beneficios esperados
      volumes[i + 1] = expenses[i][STAT_PROPS - 1] * value + volumes[i];
      balance[i + 1] = result + balance[i];
   }
   
   const double r2 = RSquaredTest(balance, volumes);
   
   #undef   STAT_PROPS
   
   return r2 * 100;
}

En amarillo está marcado lo que había que añadir en comparación con el cálculo de la negociación de un símbolo (del ejemplo anterior).

 
Stanislav Korotky #:

Corrección de errores MQL5/Include/MQL5Book/TradeUtils.mqh.

Otro bugfix relacionado (en el método NormalizeLot ):

const double newLotsRounded = MathFloor(nlot * (1 + DBL_EPSILON) / stepLot) * stepLot;
Archivos adjuntos:
TradeUtils.mqh  12 kb