English Русский 中文 Español Deutsch 日本語 Português 한국어 Français Türkçe
Racconti di robot di trading: Meno è veramente di più?

Racconti di robot di trading: Meno è veramente di più?

MetaTrader 5Trading | 12 gennaio 2022, 11:17
158 0
Roman Zamozhnyy
Roman Zamozhnyy

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:

Opzioni di test

Nel primo caso, la finestra di configurazione nel tester di strategia ha il seguente aspetto:

Parametri di ottimizzazione

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

File allegati |
licence.txt (1.05 KB)
strategy_one.mq5 (37.87 KB)
strategy_two.mq5 (37.39 KB)
symbol_list_1.mqh (2.43 KB)
symbol_list_2.mqh (2.17 KB)
Costruire una startup di tecnologia sociale, parte I: Twitta i tuoi segnali MetaTrader 5 Costruire una startup di tecnologia sociale, parte I: Twitta i tuoi segnali MetaTrader 5
Oggi impareremo come collegare un terminale MetaTrader 5 con Twitter in modo da poter twittare i segnali di trading dei tuoi EA. Stiamo sviluppando un Social Decision Support System in PHP basato su un servizio web RESTful. Questa idea nasce da una particolare concezione del trading automatico chiamato trading assistito da un computer. Vogliamo che le capacità cognitive dei trader umani filtrino quei segnali di trading che altrimenti verrebbero automaticamente immessi sul mercato dagli Expert Advisor.
Indicatore per la costruzione di un grafico Three Line Break Indicatore per la costruzione di un grafico Three Line Break
Questo articolo è dedicato al grafico Three Line Break, suggerito da Steve Nison nel suo libro "Beyond Candlesticks". Il più grande vantaggio di questo grafico è che consente di filtrare le fluttuazioni minori di un prezzo rispetto al movimento precedente. Discuteremo il principio della costruzione del grafico, il codice dell'indicatore e alcuni esempi di strategie di trading basate su di esso.
Come accedere al database MySQL da MQL5 (MQL4) Come accedere al database MySQL da MQL5 (MQL4)
L'articolo descrive lo sviluppo di un'interfaccia tra MQL e il database MySQL. Espone le soluzioni pratiche esistenti e offre un modo più conveniente per implementare una libreria da utilizzare per lavorare con i database. L'articolo contiene una descrizione dettagliata delle funzioni, della struttura dell'interfaccia, degli esempi e di alcune caratteristiche specifiche per lavorare con MySQL. Per quanto riguarda le soluzioni software, gli allegati agli articoli includono i file delle librerie dinamiche, la documentazione ed esempi di script per i linguaggi MQL4 e MQL5.
SQL e MQL5: Lavorare con il database SQLite SQL e MQL5: Lavorare con il database SQLite
Questo articolo è destinato agli sviluppatori interessati a utilizzare SQL nei loro progetti. Spiega le funzionalità e i vantaggi di SQLite. L'articolo non richiede una conoscenza speciale delle funzioni SQLite, ma sarebbe utile una minima conoscenza di SQL.