Stanislav Korotky ottimizzazione personalizzato basato su R2 - RSquared.mqh, in cui il calcolo per il caso di lotti variabili è stato corretto.
La qualità della stima è stata notevolmente migliorata: a giudicare dalla tabella dei risultati dell'ottimizzazione, è stata ottenuta la combinazione del fattore di recupero e dei parametri di Sharpe.
Esempio di utilizzo.
Attenzione! Se vengono negoziati simboli diversi, per ottenere una stima adeguata dei volumi, è necessario convertirli da lotti al valore nella valuta di deposito, ad esempio (una delle varianti semplificate):
#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[]; // usato qui solo per corrispondere al prototipo 'select', ma utile per il debug
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[]; // prendere in considerazione i volumi di scambio per l'utilizzo del criterio R2ArrayResize(balance, n + 1);
balance[0] = 0;
ArrayResize(volumes, n + 1);
volumes[0] = 0;
MapArray<ulong,double> sym2value; // simbolo hash al valore di 1 lottofor(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) // non è ancora stato registrato il valore del simbolo per lotto
{
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: stima approssimativa, perché utilizza il tasso di cambio corrente per la valuta del conto.
{
// WARN(StringFormat("Errore OrderCalcProfit: %s %d ", s, _LastError));
}
value = profit * (price / pt); // NB: la leva non viene applicata in questo caso
idx = sym2value.put(sym.d, value);
}
else
{
value = sym2value.getValue(idx);
}
double result = 0;
for(int j = 0; j < STAT_PROPS - 1; ++j) // esegue il ciclo di tutti gli oggetti richiesti, eccetto il volume dell'accordo
{
result += expenses[i][j];
}
// utilizzare i volumi come modello - più investimenti - più rendimenti attesi
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;
}
In giallo è indicato ciò che deve essere aggiunto rispetto al calcolo della negoziazione di un simbolo (dall'esempio precedente).
Deve essere modificato in questo modo perché la compilazione vada a buon fine: #property tester_set "\\Presets\FrameTransfer.set"
Anche `#property tester_set "/Presets/FrameTransfer.set"` fallirà.
Forse si potrebbe modificare la descrizione nel libro degli algoritmi:
La correzione è disponibile nella build 5506.
La qualità della stima è stata notevolmente migliorata: a giudicare dalla tabella dei risultati dell'ottimizzazione, è stata ottenuta la combinazione del fattore di recupero e dei parametri di Sharpe.
Esempio di utilizzo.
Attenzione! Se vengono negoziati simboli diversi, per ottenere una stima adeguata dei volumi, è necessario convertirli da lotti al valore nella valuta di deposito, ad esempio (una delle varianti semplificate):
In giallo è indicato ciò che deve essere aggiunto rispetto al calcolo della negoziazione di un simbolo (dall'esempio precedente).
Correzione del bug MQL5/Include/MQL5Book/TradeUtils.mqh.
Un'altra correzione correlata (nel metodo NormalizeLot ):