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)];
};
doubleOnTester()
{
HistorySelect(0, LONG_MAX);
#define STAT_PROPS 5constENUM_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);
constint n = ArraySize(tickets);
double balance[];
double volumes[]; // tener en cuenta los volúmenes comerciales para utilizar el criterio R2ArrayResize(balance, n + 1);
balance[0] = 0;
ArrayResize(volumes, n + 1);
volumes[0] = 0;
MapArray<ulong,double> sym2value; // símbolo hash a valor de 1 lotefor(int i = 0; i < n; ++i)
{
conststring 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
{
constdouble price = SymbolInfoDouble(s, SYMBOL_ASK);
constdouble 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];
}
constdouble 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).
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 versión 5506.
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):
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).
Corrección de errores MQL5/Include/MQL5Book/TradeUtils.mqh.
Otro bugfix relacionado (en el método NormalizeLot ):