
Racconti di robot di trading: Meno è veramente di più?
Prima di poter risolvere un problema devo sapere come enunciarlo a me stesso. Quando penso di aver trovato la soluzione devo dimostrare che ho ragione.
Conosco solo un modo per dimostrarlo; e cioè, con i miei soldi.
Jesse Livermore
Prologo
L'ultima crociata abbiamo esaminato un metodo piuttosto interessante ma attualmente non ampiamente utilizzato per la visualizzazione di informazioni di mercato - grafici a punti e cifre. Lo script offerto potrebbe tracciare un grafico. Tuttavia non ha suggerito l'automazione del trading. Ora possiamo provare ad automatizzare il processo di trading utilizzando il grafico a punti e cifre per l'analisi e per prendere decisioni sulla direzione e sul volume degli scambi.
Non scriverò qui i principi di base del disegno; ti basterà guardare un grafico tipico:
Copyright (c) 2012-2014 Roman Rich Euro vs US Dollar, Box-20, Reverse-3 1.4588 | \.....\.................................................................... | 1.4588 1.4521 | X\....X\................................................................... | 1.4521 1.4454 | XO\.\.XO\.................................................................. | 1.4454 1.4388 | XOX\X\XO.\................................................................. | 1.4388 1.4322 | XOXOXOXO..\................................................................ | 1.4322 1.4256 | XOXOXOXO...\....\.......................................................... | 1.4256 1.4191 | XOXO/OXO....\...X\......................................................... | 1.4191 1.4125 | XOX/.O/O.....\..XO\........................................................ | 1.4125 1.4060 | XO/../.O......\.XO.\....................................................... | 1.4060 1.3996 | ./.....O.......\XO..\...................................................... | 1.3996 1.3932 | .......OX.......XO...\....................................................X | 1.3932 1.3868 | .......OXO..X.X.XOX...\.................................................X.X | 1.3868 1.3804 | .......OXO..XOXOXOXOX..\..............................................X.XOX | 1.3804 1.3740 | .......OXO..XOXOXOXOXO..\.................................\...........XOXOX | 1.3740 1.3677 | .......OXOX.XO.O.OXOXO...\................................X\..........XOXOX | 1.3677 1.3614 | .......OXOXOX....O.OXO....\...............................XO\.........XOXOX | 1.3614 1.3552 | .......O.OXOX...../OXO.....\..............................XO.\........XOXOX | 1.3552 1.3490 | .........OXOX..../.O.OX.....\.............................XO..\.......XOXO. | 1.3490 1.3428 | .........OXOX.../....OXO.....\X.\.........................XO...\\...X.XOX.. | 1.3428 1.3366 | .........O.OX../.....OXO......XOX\........................XO....X\..XOXOX.. | 1.3366 1.3305 | ...........OX./......OXO....X.XOXO\.....................X.XO....XO\.XOXO... | 1.3305 1.3243 | ...........OX/.......O.O....XOXOXOX\....................XOXO....XO.\XOX.../ | 1.3243 1.3183 | ...........O/..........OX...XOXOXOXO\...................XOXOX.X.XOX.XOX../. | 1.3183 1.3122 | .........../...........OXO..XOXOXOXO.\..........X...X.X.XOXOXOXOXOXOXO../.. | 1.3122 1.3062 | .......................OXOX.XOXO.OXO..\.........XOX.XOXOXOXOXOXOXOXOX../... | 1.3062 1.3002 | .......................O.OXOXO...O/O...\........XOXOXOXOXO.OXO.OXOXO../.... | 1.3002 1.2942 | .........................OXOX..../.O....\.......XOXOXOXOX..OX..OXOX../..... | 1.2942 1.2882 | .........................O.OX.../..O.....\......XOXO.OXO...OX..OXOX./...... | 1.2882 1.2823 | ...........................OX../...OX.....\.....XO...OX.../OX..O/OX/....... | 1.2823 1.2764 | ...........................OX./....OXO.....\....X....OX../.O.../.O/........ | 1.2764 1.2706 | ...........................OX/.....OXO..X...\...X....O../......../......... | 1.2706 1.2647 | ...........................O/......O.OX.XOX..\..X....../................... | 1.2647 1.2589 | .........................../.........OXOXOXO..\.X...../.................... | 1.2589 1.2531 | .....................................OXOXOXO...\X..../..................... | 1.2531 1.2474 | .....................................OXO.OXO....X.../...................... | 1.2474 1.2417 | .....................................OX..O.O..X.X../....................... | 1.2417 1.2359 | .....................................OX....OX.XOX./........................ | 1.2359 1.2303 | .....................................O.....OXOXOX/......................... | 1.2303 1.2246 | ...........................................OXOXO/.......................... | 1.2246 1.2190 | ...........................................OXO./........................... | 1.2190 1.2134 | ...........................................OX.............................. | 1.2134 1.2078 | ...........................................O............................... | 1.2078 1.2023 | ........................................................................... | 1.2023 222222222222222222222222222222222222222222222222222222222222222222222222222 000000000000000000000000000000000000000000000000000000000000000000000000000 111111111111111111111111111111111111111111111111111111111111111111111111111 111111111111111111111111112222222222222222222222222222222333333333333333344 ........................................................................... 000000000001111111111111110000000000000000000000011111111000000000000011100 788888899990000001111112221122233445566666677888900001222123444567778901213 ........................................................................... 200011211220111220011231220101212121201112222001100010001002123110112020231 658801925683489071404504193396436668111288937260415979579417630739120547713 000100001012111111110111111100112010210001111101101101011111111101011101110 910501876933613095500253237788652909250001557626626824655375907538165785367 ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: 550433251023230204310404232105354323532031240033315125241340044324523153453 000000000000000000000000000000000000000000000000000000000000000000000000000
Non sosterrò che le opportunità di trading sono chiaramente visibili in questo grafico; Ti suggerisco solo di controllare due ipotesi di trading:
Fai trading con la tendenza principale: acquista in un mercato rialzista e vendi in uno ribassista.
Usa gli stop loss che avrai definito prima di entrare nel mercato.
- acquistare al di sopra del livello di supporto utilizzando un ordine di stop al di sopra del massimo della colonna X precedente, vendi al di sotto della linea di resistenza utilizzando un ordine di stop di vendita al di sotto del minimo della colonna O precedente; utilizza un trailing stop a livello del pivot;
Lascia che i tuoi profitti crescano.
Chiudi le offerte in perdita (le offerte buone di solito generano immediatamente profitto).
- compra quando sfonda la linea di resistenza, vendi quando sfonda la linea di supporto; imposta lo stop loss a livello di pivot, imposta il trailing stop sulla linea di tendenza.
Come scegliere il volume
Presta attenzione alle quotazioni del maestro della speculazione azionaria sopra descritte : usa gli ordini stop. Preferisco entrare nel mercato con un certo volume in modo che quando scatta l'ordine Stop Loss, la perdita di saldo non sia più della percentuale del saldo che posso accettare (ciò che Ralph Vince chiama F ottimale nel suo The Mathematics of Money Management). Il rischio di perdita per deal è una variabile ottimizzabile (opt_f nel codice sottostante).
Pertanto, abbiamo una funzione che inserisce un ordine di acquisto / vendita con il meccanismo di calcolo del volume che dipende dal rischio accettabile per operazione:
//+------------------------------------------------------------------+ //| The function places an order with a precalculated volume | //+------------------------------------------------------------------+ void PlaceOrder() { //--- Variables for calculating the lot uint digits_2_lot=(uint)SymbolInfoInteger(symbol,SYMBOL_DIGITS); double trade_risk=AccountInfoDouble(ACCOUNT_EQUITY)*opt_f; double one_tick_loss_min_lot=SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_LOSS)*SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP); //--- Fill out the main fields of the request trade_request.magic=magic; trade_request.symbol=symbol; trade_request.action=TRADE_ACTION_PENDING; trade_request.tp=NULL; trade_request.comment=NULL; trade_request.type_filling=NULL; trade_request.stoplimit=NULL; trade_request.type_time=NULL; trade_request.expiration=NULL; if(is_const_lot==true) { order_vol=SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN); } else { order_vol=trade_risk/(MathAbs(trade_request.price-trade_request.sl)*MathPow(10,digits_2_lot)*one_tick_loss_min_lot)*SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP); order_vol=MathMax(order_vol,SymbolInfoDouble(symbol,SYMBOL_VOLUME_MIN)); if(SymbolInfoDouble(symbol,SYMBOL_VOLUME_LIMIT)!=0) order_vol=MathMin(order_vol,SymbolInfoDouble(symbol,SYMBOL_VOLUME_LIMIT)); order_vol=NormalizeDouble(order_vol,(int)MathAbs(MathLog10(SymbolInfoDouble(symbol,SYMBOL_VOLUME_STEP)))); } //--- Place an order while(order_vol>0) { trade_request.volume=MathMin(order_vol,SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX)); if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order); order_vol=order_vol-SymbolInfoDouble(symbol,SYMBOL_VOLUME_MAX); }; ticket=trade_result.order; };
Quale criterio di ottimizzazione utilizzare?
In realtà ci sono solo due criteri di ottimizzazione: minimizzazione o drawdown ad un dato livello di rendimento, o massimizzazione del bilanciamento per un dato livello di drawdown. Preferisco ottimizzare con il secondo criterio:
//+------------------------------------------------------------------+ //| Result of strategy run in the testing mode | //+------------------------------------------------------------------+ double OnTester() { if(TesterStatistics(STAT_EQUITY_DDREL_PERCENT)>(risk*100)) return(0); else return(NormalizeDouble(TesterStatistics(STAT_PROFIT),(uint)SymbolInfoInteger(symbol,SYMBOL_DIGITS))); };
nel quale il rischio è il livello di prelievo al di sopra del quale la strategia diventa per me inaccettabile. Questa è anche una delle variabili da ottimizzare.
Quando ri-ottimizzare?
Qualcuno riottimizza le strategie a intervalli di tempo (ad esempio, una volta alla settimana, un mese), qualcuno a intervalli di affari (dopo 50, 100 offerte), qualcuno inizia una nuova ottimizzazione quando il mercato cambia. Infatti, la necessità di ri-ottimizzazione dipende solo dal criterio di ottimizzazione selezionato nel paragrafo precedente. Se il drawdown scende al di sotto del parametro di rischio massimo consentito, riottimizziamo la strategia; se tutto funziona bene, lasciala così com'è. Drawdown superiore al 10% è per me inaccettabile. Pertanto, se il sistema ottiene un maggiore drawdown durante il funzionamento, riottimizzo il suo.
Posso ottimizzare tutto in una volta?
Sfortunatamente, nel tester di strategia non è possibile ottimizzare le variabili esterne per la modalità "Tutti i simboli selezionati nel Market Watch". Scegliamo quindi gli strumenti di mercato insieme ad altre variabili esterna ottimizzabili come segue:
//+------------------------------------------------------------------+ //| Enumeration of symbols | //+------------------------------------------------------------------+ enum SYMBOLS { AA=1, AIG, AXP, BA, C, CAT, DD, DIS, GE, HD, HON, HPQ, IBM, IP, INTC, JNJ, JPM, KO, MCD, MMM, MO, MRK, MSFT, PFE, PG, QQQ, T, SPY, UTX, VZ, WMT, XOM }; //+------------------------------------------------------------------+ //| Symbol selection function | //+------------------------------------------------------------------+ void SelectSymbol() { switch(selected_symbol) { case 1: symbol="#AA"; break; case 2: symbol="#AIG"; break; case 3: symbol="#AXP"; break; case 4: symbol="#BA"; break; case 5: symbol="#C"; break; case 6: symbol="#CAT"; break; case 7: symbol="#DD"; break; case 8: symbol="#DIS"; break; case 9: symbol="#GE"; break; case 10: symbol="#HD"; break; case 11: symbol="#HON"; break; case 12: symbol="#HPQ"; break; case 13: symbol="#IBM"; break; case 14: symbol="#IP"; break; case 15: symbol="#INTC"; break; case 16: symbol="#JNJ"; break; case 17: symbol="#JPM"; break; case 18: symbol="#KO"; break; case 19: symbol="#MCD"; break; case 20: symbol="#MMM"; break; case 21: symbol="#MO"; break; case 22: symbol="#MRK"; break; case 23: symbol="#MSFT"; break; case 24: symbol="#PFE"; break; case 25: symbol="#PG"; break; case 26: symbol="#QQQ"; break; case 27: symbol="#T"; break; case 28: symbol="#SPY"; break; case 29: symbol="#UTX"; break; case 30: symbol="#VZ"; break; case 31: symbol="#WMT"; break; case 32: symbol="#XOM"; break; default: symbol="#SPY"; break; }; };
Se necessario, è possibile aggiungere gli strumenti necessari nella funzione di selezione dei simboli e nell'enumerazione (la funzione viene chiamata in OnInit()).
Quale robot abbiamo creato?
OnTick handler.
//+------------------------------------------------------------------+ //| A typical ticks handler OnTick() | //| Draw the chart only based on complete bars but first | //| check if it is a new bar. | //| If the bar is new and there is a position, check | //| whether we need to move the stop loss, | //| if the bar is new and no position, check | //| if we have conditions for opening a deal. | //+------------------------------------------------------------------+ void OnTick() { //--- If the bar is new if(IsNewBar()==true) { RecalcIndicators(); //--- Tester/optimizer mode? if((MQLInfoInteger(MQL_TESTER)==true) || (MQLInfoInteger(MQL_OPTIMIZATION)==true)) { //--- Is it the testing period? if(cur_bar_time_dig[0]>begin_of_test) { //--- If there is an open position on the symbol if(PositionSelect(symbol)==true) //--- check if we need to move SL; if need, move it TrailCondition(); //--- If there are no positions else //--- check if we need to open a position; if we need, open it TradeCondition(); } } else { //--- if there is an oprn position on the symbol if(PositionSelect(symbol)==true) //--- check if we need to move SL; if need, move it TrailCondition(); //--- If there are no positions else //--- check if we need to open a position; if we need, open it TradeCondition(); } }; };
Per la strategia 1: "acquista al di sopra del livello di supporto utilizzando un ordine di stop al di sopra del massimo della precedente colonna X, vendi al di sotto della linea di resistenza utilizzando un ordine di stop di vendita al di sotto del minimo della colonna O precedente; utilizza un trailing stop a livello del pivot|":
//+------------------------------------------------------------------+ //| Function checks trade conditions for opening a deal | //+------------------------------------------------------------------+ void TradeCondition() { if(order_col_number!=column_count) //--- Are there any orders on the symbol? { if(OrdersTotal()>0) { //--- Delete them! for(int loc_count_1=0;loc_count_1<OrdersTotal();loc_count_1++) { ticket=OrderGetTicket(loc_count_1); if(!OrderSelect(ticket)) Print("Failed to select order #",ticket); if(OrderGetString(ORDER_SYMBOL)==symbol) { trade_request.order=ticket; trade_request.action=TRADE_ACTION_REMOVE; if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order); }; }; order_col_number=column_count; return; } else { order_col_number=column_count; return; } } else if((MathPow(10,pnf[column_count-1].resist_price)<SymbolInfoDouble(symbol,SYMBOL_ASK)) && (pnf[column_count-1].column_type=='X') && (pnf[column_count-1].max_column_price<=pnf[column_count-3].max_column_price)) { //--- Conditions for BUY met; let's see if there are any pending Buy orders for the symbol with the price we need? trade_request.price=NormalizeDouble(MathPow(10,pnf[column_count-3].max_column_price+double_box),digit_2_orders); trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-3].max_column_price-(reverse-1)*double_box),digit_2_orders); trade_request.type=ORDER_TYPE_BUY_STOP; if(OrderSelect(ticket)==false) //--- No pending orders - place an order { PlaceOrder(); order_col_number=column_count; } else //--- If there is a pending order { //--- what is the type and price of the pending order? if((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP) || ((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP) && (OrderGetDouble(ORDER_PRICE_OPEN)!=trade_request.price))) { //--- The wrong type or the price differs - close the order trade_request.order=ticket; trade_request.action=TRADE_ACTION_REMOVE; if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order); //--- open with the desired price PlaceOrder(); order_col_number=column_count; }; }; return; } else if((MathPow(10,pnf[column_count-1].resist_price)>SymbolInfoDouble(symbol,SYMBOL_ASK)) && (pnf[column_count-1].column_type=='O') && (pnf[column_count-1].min_column_price>=pnf[column_count-3].min_column_price)) { //--- Conditions for SELL met; let's see if there are any pending Sell orders for the symbol with the price we need? trade_request.price=NormalizeDouble(MathPow(10,pnf[column_count-3].min_column_price-double_box),digit_2_orders); trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-3].min_column_price+(reverse-1)*double_box),digit_2_orders); trade_request.type=ORDER_TYPE_SELL_STOP; if(OrderSelect(ticket)==false) //--- No pending orders, place an order { PlaceOrder(); order_col_number=column_count; } else //--- or there is a pending order { //--- what is the type and price of the pending order? if((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP) || ((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP) && (OrderGetDouble(ORDER_PRICE_OPEN)!=trade_request.price))) { //--- The wrong type or the price differs - close the order trade_request.order=ticket; trade_request.action=TRADE_ACTION_REMOVE; if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order); //--- and open with the desired price PlaceOrder(); order_col_number=column_count; }; }; return; } else return; }; //+------------------------------------------------------------------+ //| The function checks conditions for moving Stop Loss | //+------------------------------------------------------------------+ void TrailCondition() { if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-1].max_column_price-reverse*double_box),digit_2_orders); else trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-1].min_column_price+reverse*double_box),digit_2_orders); if(PositionGetDouble(POSITION_SL)!=trade_request.sl) PlaceTrailOrder(); };
Per la Strategia 2 "acquista alla svolta della linea di resistenza, vendi alla svolta della linea di supporto; imposta lo stop loss a livello di pivot, imposta il trailing stop sulla linea di tendenza":
//+------------------------------------------------------------------+ //| The function checks trade conditions for opening a deal | //+------------------------------------------------------------------+ void TradeCondition() { if(order_col_number!=column_count) //--- Are there any orders for the symbol? { if(OrdersTotal()>0) { //--- Delete them! for(int loc_count_1=0;loc_count_1<OrdersTotal();loc_count_1++) { ticket=OrderGetTicket(loc_count_1); if(!OrderSelect(ticket)) Print("Failed to select order #",ticket); if(OrderGetString(ORDER_SYMBOL)==symbol) { trade_request.order=ticket; trade_request.action=TRADE_ACTION_REMOVE; if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order); }; }; order_col_number=column_count; return; } else { order_col_number=column_count; return; } } else if(MathPow(10,pnf[column_count-1].resist_price)>SymbolInfoDouble(symbol,SYMBOL_ASK)) { //--- Conditions for BUY met; let's see if there are any pending Buy orders for the symbol with the price we need? trade_request.price=NormalizeDouble(MathPow(10,pnf[column_count-1].resist_price),digit_2_orders); trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-1].resist_price-(reverse-1)*double_box),digit_2_orders); trade_request.type=ORDER_TYPE_BUY_STOP; if(OrderSelect(ticket)==false) //--- No pending orders - place an order { PlaceOrder(); order_col_number=column_count; } else //--- or there is a pending order { //--- what is the type and price of the pending order? if((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP) || ((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP) && (OrderGetDouble(ORDER_PRICE_OPEN)!=trade_request.price))) { //--- The wrong type or the price differs - close the order trade_request.order=ticket; trade_request.action=TRADE_ACTION_REMOVE; if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order); //--- open with the desired price PlaceOrder(); order_col_number=column_count; }; }; return; } else if(MathPow(10,pnf[column_count-1].resist_price)<SymbolInfoDouble(symbol,SYMBOL_ASK)) { //--- Conditions for SELL met; let's see if there are any pending Sell orders for the symbol with the price we need? trade_request.price=NormalizeDouble(MathPow(10,pnf[column_count-1].supp_price),digit_2_orders); trade_request.sl=NormalizeDouble(MathPow(10,pnf[column_count-1].supp_price+(reverse-1)*double_box),digit_2_orders); trade_request.type=ORDER_TYPE_SELL_STOP; if(OrderSelect(ticket)==false) //--- No pending orders - place an order { PlaceOrder(); order_col_number=column_count; } else //--- If there is a pending order { //--- what is the type and price of the pending order? if((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_BUY_STOP) || ((OrderGetInteger(ORDER_TYPE)==ORDER_TYPE_SELL_STOP) && (OrderGetDouble(ORDER_PRICE_OPEN)!=trade_request.price))) { //--- The wrong type or the price differs - close the order trade_request.order=ticket; trade_request.action=TRADE_ACTION_REMOVE; if(!OrderSend(trade_request,trade_result)) Print("Failed to send order #",trade_request.order); //--- open with the desired price PlaceOrder(); order_col_number=column_count; }; }; return; } else return; }; //+------------------------------------------------------------------+ //| The function checks conditions for moving Stop Loss | //+------------------------------------------------------------------+ void TrailCondition() { if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY) trade_request.sl=NormalizeDouble(MathMax(SymbolInfoDouble(symbol,SYMBOL_ASK),MathPow(10,pnf[column_count-1].max_column_price-reverse*double_box)),digit_2_orders); else trade_request.sl=NormalizeDouble(MathMin(SymbolInfoDouble(symbol,SYMBOL_BID),MathPow(10,pnf[column_count-1].min_column_price+reverse*double_box)),digit_2_orders); if(PositionGetDouble(POSITION_SL)!=trade_request.sl) PlaceTrailOrder(); };
Caro lettore, per favore nota alcune cose.
- I prezzi degli strumenti di mercato variano ampiamente, da centesimi a decine di migliaia (esempio - azioni e CFD sulle borse giapponesi). Pertanto, uso il logaritmo dei prezzi per il grafico di punti e figure per evitare di impostare valori da uno a decine di migliaia di pip per le dimensioni del box.
- L'indicizzazione della matrice del grafico a punti e figure inizia da zero, quindi l'indice dell'ultima colonna è uguale al numero di colonne meno una.
- Il valore della linea di supporto, se utilizzato, è maggiore di -10,0, ma inferiore al logaritmo del prezzo. Se non viene utilizzata alcuna linea di supporto (o resistenza), il suo valore nella matrice del grafico è -10,0. Pertanto, le condizioni per sfondare le linee di supporto/ resistenza sono scritte nella stessa forma del codice della Strategia 2 di cui sopra.
Guarda il codice delle funzioni ausiliarie negli allegati seguenti. Il codice del grafico è troppo grande, quindi non lo scrivo nell'articolo; dagli un’occhiata con i commenti negli allegati qui sotto.
Risultati di EA Trading
Ho preparato due serie di simboli di mercato nei file symbol_list_1.mhq e symbol_list_2.mhq per effettuarne l'ottimizzazione; includono coppie di valute e CFD azionari dell'indice Dow.
Finestra di configurazione:
Nel primo caso, la finestra di configurazione nel tester di strategia ha il seguente aspetto:
Prendere nota della riga Iniziale del test. Il robot richiede almeno alcune colonne del grafico per l'analisi e il processo decisionale; e quando si imposta la dimensione del box pari a 50 pip o più, una cronologia di un anno spesso non è sufficiente nemmeno per una colonna. Pertanto, per i grafici con dimensioni del box pari o superiori a 50 pip, utilizza l'intervallo di circa tre anni o più dall'inizio del funzionamento del robot, e imposta l'inizio dell'operazione del robot nel parametro Testing Start nella finestra di configurazione. Nel nostro esempio, per il test con dimensione del box di 100 pip dal 01.01.2012 specifica l'intervallo dal 01.01.2009 nella scheda Impostazioni; imposta l'intervallo dal 01.01.2012 nella scheda Parametri.
Il falso valore del parametro "Trade minimum lot?" indica che la dimensione del lotto dipende dal saldo e dalla variabile "Rischio per Trade, %" (in questo caso 1% per trade, ma può anche essere ottimizzata). "Max Drawdown, %" è il criterio di ottimizzazione nella funzione OnTester(). In questo articolo uso solo due variabili per l'ottimizzazione: Simbolo e dimensione del box in pip.
Periodo di ottimizzazione: 2012-2013. L'EA funziona meglio sul grafico EURUSD, poiché il simbolo fornisce la migliore copertura tick. La tabella seguente contiene un rapporto completo dei test su varie coppie di valute con dimensione del box di 10, basato sulla prima strategia:
pass | Risultato | Profitto | Profitto previsto | Fattore di profitto | Fattore di recupero | Indice di Sharpe | Personalizza | Patrimonio netto DD % | Trade | selected_symbol | box |
---|---|---|---|---|---|---|---|---|---|---|---|
0,00 | 0,00 | -1 002,12 | -18,91 | 0,54 | -0,79 | -0,24 | 0,00 | 12,67 | 53,00 | AUDCAD | 10,00 |
1,00 | 886,56 | 886,56 | 14,53 | 1,40 | 1,52 | 0,13 | 886,56 | 5,76 | 61,00 | AUDCHF | 10,00 |
2,00 | 0,00 | -1 451,63 | -10,60 | 0,77 | -0,70 | -0,09 | 0,00 | 19,92 | 137,00 | AUDJPY | 10,00 |
3,00 | -647,66 | -647,66 | -17,50 | 0,57 | -0,68 | -0,24 | -647,66 | 9,46 | 37,00 | AUDNZD | 10,00 |
4,00 | -269,22 | -269,22 | -3,17 | 0,92 | -0,26 | -0,03 | -269,22 | 9,78 | 85,00 | AUDUSD | 10,00 |
5,00 | 0,00 | -811,44 | -13,52 | 0,72 | -0,64 | -0,14 | 0,00 | 12,20 | 60,00 | CADCHF | 10,00 |
6,00 | 0,00 | 1 686,34 | 16,53 | 1,36 | 1,17 | 0,12 | 0,00 | 11,78 | 102,00 | CHFJPY | 10,00 |
7,00 | 356,68 | 356,68 | 5,66 | 1,13 | 0,40 | 0,06 | 356,68 | 8,04 | 63,00 | EURAUD | 10,00 |
8,00 | 0,00 | -1 437,91 | -25,68 | 0,53 | -0,92 | -0,25 | 0,00 | 15,47 | 56,00 | EURCAD | 10,00 |
9,00 | 0,00 | -886,66 | -46,67 | 0,34 | -0,74 | -0,46 | 0,00 | 11,56 | 19,00 | EURCHF | 10,00 |
10,00 | 0,00 | -789,59 | -21,93 | 0,54 | -0,75 | -0,26 | 0,00 | 10,34 | 36,00 | EURGBP | 10,00 |
11,00 | 0,00 | 3 074,86 | 28,47 | 1,62 | 1,72 | 0,20 | 0,00 | 12,67 | 108,00 | EURJPY | 10,00 |
12,00 | 0,00 | -1 621,85 | -19,78 | 0,55 | -0,97 | -0,25 | 0,00 | 16,75 | 82,00 | EURNZD | 10,00 |
13,00 | 152,73 | 152,73 | 2,88 | 1,07 | 0,21 | 0,03 | 152,73 | 6,90 | 53,00 | EURUSD | 10,00 |
14,00 | 0,00 | -1 058,85 | -14,50 | 0,65 | -0,66 | -0,16 | 0,00 | 15,87 | 73,00 | GBPAUD | 10,00 |
15,00 | 0,00 | -1 343,47 | -25,35 | 0,43 | -0,64 | -0,34 | 0,00 | 20,90 | 53,00 | GBPCAD | 10,00 |
16,00 | 0,00 | -2 607,22 | -44,19 | 0,27 | -0,95 | -0,59 | 0,00 | 27,15 | 59,00 | GBPCHF | 10,00 |
17,00 | 0,00 | 1 160,54 | 11,72 | 1,27 | 0,81 | 0,10 | 0,00 | 12,30 | 99,00 | GBPJPY | 10,00 |
18,00 | 0,00 | -1 249,91 | -14,70 | 0,69 | -0,85 | -0,15 | 0,00 | 14,41 | 85,00 | GBPNZD | 10,00 |
19,00 | 208,94 | 208,94 | 5,36 | 1,12 | 0,25 | 0,05 | 208,94 | 7,81 | 39,00 | GBPUSD | 10,00 |
20,00 | 0,00 | -2 137,68 | -21,17 | 0,53 | -0,79 | -0,24 | 0,00 | 25,62 | 101,00 | NZDUSD | 10,00 |
21,00 | 0,00 | -1 766,80 | -38,41 | 0,30 | -0,97 | -0,53 | 0,00 | 18,10 | 46,00 | USDCAD | 10,00 |
22,00 | -824,69 | -824,69 | -11,95 | 0,73 | -0,90 | -0,13 | -824,69 | 9,11 | 69,00 | USDCHF | 10,00 |
23,00 | 2 166,53 | 2 166,53 | 26,10 | 1,58 | 2,40 | 0,18 | 2 166,53 | 7,13 | 83,00 | USDJPY | 10,00 |
2 029,87 | -10 213,52 | 13,40 | 1 659,00 |
Ecco una tabella riassuntiva dei vari simboli e valori delle dimensioni del box:
Strategia | Simboli | dimensioni del box | Trade | Patrimonio netto DD % | Profitto | Risultato | Saldo previsto |
---|---|---|---|---|---|---|---|
1 | Valute | 10 | 1 659 | Settembre, | -10 214 | 2 030 | 2 030 |
1 | Valute | 20 | 400 | 5 | 1 638 | 2 484 | 2 484 |
1 | Azioni | 50 | 350 | 60 | 7 599 | 7 599 | 15 199 |
1 | Azioni | 100 | 81 | 2 | 4 415 | 4 415 | 17 659 |
2 | Valute | 10 | 338 | 20 | -4 055 | 138 | 138 |
2 | Valute | 20 | 116 | 8 | 4 687 | 3 986 | 3 986 |
2 | Azioni | 50 | 65 | 6 | 6 770 | 9 244 | 9 244 |
2 | Azioni | 100 | 12 | 1 | -332 | -332 | -5 315 |
Cosa vediamo?
Ci sono sciocchi, che sbagliano sempre.
E ci sono gli sciocchi di Wall Street che credono che si dovrebbe sempre fare trading.
Nessuno ha sempre tutte le informazioni necessarie per acquistare o vendere azioni e farlo in modo ragionevole.
La conclusione può sembrarti strana: è più probabile che il tuo deposito sia più alto con meno operazioni. Se due anni fa avessimo lasciato che il nostro EA negoziasse azioni con una dimensione del box di 100 e il rischio per operazione dell'1%, l'EA avrebbe fatto solo 81 operazioni fino adesso (una media di 1,25 operazioni per simbolo all'anno) il nostro deposito sarebbe cresciuto del 44%, mentre il drawdown azionario medio sarebbe stato leggermente superiore al 2%. Accettando un eventuale drawdon del 10%, potremmo rischiare il 4% per affare, e il nostro deposito sarebbe cresciuto del 177% per due anni, cioè del 90% annuo in dollari USA!
Epilogo
Il prezzo non è mai troppo alto per iniziare a comprare, e non è mai troppo basso per iniziare a vendere.
Non è pensando che si fanno tanti soldi. È aspettando.
Le strategie sopra descritte possono essere modificate e possono dare un rendimento ancora maggiore con il drawdown non superiore al 10%. Non cercare di fare trading troppo spesso, meglio trovare un broker che fornisca non solo un "set standard" di simboli di due dozzine di coppie di valute e tre dozzine di azioni, ma almeno tre o quattrocento simboli (azioni, futures). Probabilmente i simboli non saranno correlati e il tuo deposito sarà più sicuro. Un'altra osservazione: le azioni mostrano risultati migliori rispetto alle coppie di valute.
P.S. (un'osservazione pubblicitaria)
Il mio PnF Chartist script è disponibile sul Market. Disegna grafici a punti e figure in file di testo utilizzando citazioni fornite da MT4, MT5 o Yahoo finance. Usalo per la ricerca visiva dei modelli di prezzo, dal momento che non esiste un tester / ottimizzatore migliore del tuo cervello. Non appena trovi i modelli, usa i modelli EA di questo articolo per testare le tue idee.
Tradotto dal russo da MetaQuotes Ltd.
Articolo originale: https://www.mql5.com/ru/articles/910





- App di trading gratuite
- Oltre 8.000 segnali per il copy trading
- Notizie economiche per esplorare i mercati finanziari
Accetti la politica del sito e le condizioni d’uso