English Русский 中文 Español Deutsch 日本語 Português 한국어 Italiano Türkçe
Récits de Robots de Trading : Est-ce moins plus que ca ?

Récits de Robots de Trading : Est-ce moins plus que ca ?

MetaTrader 5Trading | 13 janvier 2022, 14:34
85 0
Roman Zamozhnyy
Roman Zamozhnyy

Avant de pouvoir résoudre un problème, je dois me l’exprimer. Quand je pense avoir trouvé la solution, je dois prouver que j’ai raison.

Je ne connais qu’une seule façon de le prouver; et c’est-à-dire avec mon propre argent.

Jesse Livermore


Prologue

Dans La dernière croisade, nous avons passé en revue une méthode intéressante mais actuellement peu utilisée pour afficher des informations sur le marché - des graphiques de points et de figures. Le script proposé pourrait tracer un graphique. Cependant, il ne suggérait pas l’automatisation du trading. Maintenant, nous pouvons essayer d’automatiser le processus de trading en utilisant le graphique de points et de chiffres pour l’analyse et pour prendre des décisions sur la direction et le volume des échanges.

Je n’écrirai pas ici les principes de base du dessin; il suffit de regarder un graphique type :

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

Je ne soutiendrai pas que les opportunités de trading sont clairement visibles dans ce graphique; Je vous suggère seulement de vérifier deux hypothèses de trading :

Trader avec la tendance principale - acheter dans un marché haussier et vendez dans un marché baissier.

Utiliser des stop loss, définis avant d’entrer sur le marché.

  • acheter au-dessus du niveau de support en utilisant un ordre stop au-dessus du sommet de la colonne X précédente, vendre en dessous de la ligne de résistance en utilisant un ordre stop de vente inférieur au bas de la colonne O précédente; utiliser un arrêt de fin au niveau du pivot;

Laissez vos profits croître.

Concluez des transactions à perte (les bonnes affaires montrent généralement immédiatement les bénéfices).

  • acheter quand il franchit la ligne de résistance, vendre quand il franchit la ligne de support; définissez stop loss au niveau du pivot, définissez l’arrêt de fin sur la ligne de tendance.


Comment choisir le volume

Faites attention aux cotations ci-dessus d’un maître de spéculation boursière: utilisez des ordres stop. Je préfère entrer sur le marché avec un certain volume de sorte que lorsque l’ordre Stop Loss se déclenche, la perte d’équilibre ne soit pas supérieure à un pourcentage du solde que je peux accepter (ce que Ralph Vince appelle le F optimal dans ses Mathématiques de la gestion de l’argent). Le risque de perte par transaction est une variable bien optimisable (opt_f dans le code ci-dessous).

Ainsi, nous avons une fonction qui place un ordre d’achat / vente avec le mécanisme de calcul du volume qui dépend du risque acceptable par transaction :

//+------------------------------------------------------------------+
//| 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;
  };


Quel critère d’optimisation utiliser ?

En fait, il n’y a que deux critères d’optimisation : la minimisation ou le prélèvement à un niveau de rendement donné, ou la maximisation de l’équilibre pour un niveau de prélèvement donné. Je préfère optimiser par le deuxième critère :

//+------------------------------------------------------------------+
//| 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)));
  };

où le risque est le niveau de retrait au-dessus duquel la stratégie est inacceptable pour moi. C’est aussi l’une des variables à optimiser.


Quand ré-optimiser ?

Quelqu’un ré-optimise les stratégies à des intervalles de temps (par exemple, une fois par semaine, un mois), quelqu’un à des intervalles de transaction (après 50 100 transactions), quelqu’un commence une nouvelle optimisation lorsque le marché change. En fait, la nécessité d’une ré-optimisation ne dépend que du critère d’optimisation sélectionné dans le paragraphe précédent. Si le prélèvement tombe en dessous du paramètre de risque maximal autorisé, nous ré-optimisons la stratégie; si tout fonctionne bien, laissez-le fonctionner tel qu’il est. Un prélèvement supérieur à 10 % est inacceptable pour moi. Ainsi, si le système obtient un plus grand retrait pendant le fonctionnement, je le ré-optimise.


Puis-je tout optimiser en même temps ?

Malheureusement, dans le testeur de stratégie, vous ne pouvez pas optimiser les variables externes pour le mode « Tous les symboles sélectionnés dans la surveillance des marchés  ». Par conséquent, choisissons les instruments de marché ainsi que d’autres variables externes optimisable comme suit :

//+------------------------------------------------------------------+
//| 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;
     };
  };

Si nécessaire, vous pouvez ajouter les instruments requis dans la fonction de sélection de symbole et l’énumération (la fonction est appelée dans OnInit()).


Quel robot avons-nous créé ?

Gestionnaire de tics :

//+------------------------------------------------------------------+
//| 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();
        }

     };
  };

Pour la stratégie 1 : « acheter au-dessus du niveau de support en utilisant un ordre stop au-dessus du sommet de la colonne X précédente, vendre en dessous de la ligne de résistance en utilisant un ordre stop de vente inférieur au bas de la colonne O précédente; utiliser un arrêt de fin au niveau du 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();
  };

Pour la stratégie 2 « acheter à la percée de la ligne de résistance, vendre à la percée de la ligne de support ; définir le stop loss au niveau du pivot, définir l’arrêt de fin à la ligne de tendance »:

//+------------------------------------------------------------------+
//| 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();
  };

Cher lecteur, veuillez noter quelques points.

  • Les prix des instruments de marché varient dans une fourchette assez large, allant de cents à des dizaines de milliers (exemple - actions et CFD sur les bourses japonaises). Par conséquent, j’utilise le logarithme de prix pour le graphique en points et en chiffres afin d’éviter de définir des valeurs de un à des dizaines de milliers de pips pour la taille de la boîte.
  • L’indexation du tableau du graphique en points et en figures commence à zéro, de sorte que l’index de la dernière colonne est égal au nombre de colonnes moins une.
  • La valeur de la ligne de support, si elle est utilisée, est supérieure à -10,0, mais inférieure au logarithme du prix. Si aucune ligne de support (ou de résistance) n’est utilisée, sa valeur dans le tableau de graphiques est -10.0. Par conséquent, les conditions de rupture des lignes de support/résistance sont écrites sous la même forme que dans le code de la stratégie 2 ci-dessus.

Voir le code des fonctions auxiliaires dans les pièces jointes ci-dessous. Le code du graphique est trop grand, donc je ne l’écris pas dans l’article; voyez-le avec des commentaires dans les pièces jointes ci-dessous.


Résultats d’EA Trading

J’ai préparé deux ensembles de symboles de marché dans des fichiers symbol_list_1.mhq et symbol_list_2.mhq pour l’optimisation; ils comprennent les paires de devises et les CFD sur actions de l’indice Dow.

Fenêtre d’installation :

Options

Dans le premier cas, la fenêtre d’installation du testeur de stratégie se présente comme suit :

Paramètres d’optimisation

Notez la ligne de démarrage du test. Le robot nécessite au moins quelques colonnes de graphique pour l’analyse et la prise de décision; et lorsque vous définissez une taille de boîte égale à 50 pips ou plus, un historique d’un an n’est souvent pas suffisant, même pour une colonne. Par conséquent, pour les graphiques avec une taille de boîte de 50 pips ou plus, utilisez l’intervalle d’environ trois ans ou plus à partir du début de l’opération du robot, définissez le démarrage de l’opération du robot dans le paramètre Démarrage du test dans la fenêtre de configuration. Dans notre exemple, pour les tests avec la taille de boîte de 100 pips depuis le 01.01.2012, spécifiez l’intervalle depuis le 01.01.2009 dans l’onglet Paramètres; définir l’intervalle depuis le 01.01.2012 dans l’onglet Paramètres.

La fausse valeur du paramètre « Lot minimum de Trade ? » indique que la taille du lot dépend du solde et de la variable « Risque par Trade, % » (dans ce cas 1% par trade, mais il peut également être optimisé). « Max Drawdown, % » est le critère d’optimisation de la fonction OnTester() . Dans cet article, je n’utilise que deux variables pour l’optimisation : Symbole et taille de la boîte en pips.

Période d’optimisation : 2012-2013. L’EA fonctionne mieux sur le graphique EURUSD, car le symbole fournit la meilleure couverture de tics. Le tableau ci-dessous contient un rapport complet pour les tests sur différentes paires de devises avec une taille de boîte 10 basée sur la première stratégie :

Passer Résultat Bénéfice Gain attendu Facteur de profit Facteur de récupération Ratio de Sharpe Personnalisé Capitaux propres DD % Trades selected_symbol boîte
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

Voici un tableau récapitulatif pour divers symboles et valeurs de taille de boîte :

Stratégie Symboles x_size+=1; Trades Capitaux propres DD % Bénéfice Résultat Solde attendu
1 Devises 10 1 659 Septembre, -10 214 2 030 2 030
1 Devises 20 400 5 1 638 2 484 2 484
1 Actions 50 350 60 7 599 7 599 15 199
1 Actions 100 81 2 4 415 4 415 17 659
2 Devises 10 338 20 -4 055 138 138
2 Devises 20 116 8 4 687 3 986 3 986
2 Actions 50 65 6 6 770 9 244 9 244
2 Actions 100 12 1 -332 -332 -5 315

Que voyons-nous ?

Il y a des imbéciles, qui font toujours le mal.

Et il y a les imbéciles de WallStreet qui croient que vous devriez toujours trader.

Il n’y a personne au monde qui a toujours toutes les informations nécessaires pour acheter ou vendre des actions et le faire de manière tout à fait raisonnable.

La conclusion peut vous sembler étrange: votre dépôt est plus susceptible d’être plus élevé avec moins de transactions. S’il y a deux ans, nous avions laissé nos actions EA négocier des actions avec une taille de boîte de 100 et un risque par transaction de 1%, l’EA n’effectuerait que 81 transactions depuis lors (une moyenne de 1,25 transaction par symbole et par an), notre dépôt aurait augmenté de 44%, tandis que le retrait moyen des actions aurait été légèrement supérieur à 2%. En acceptant un éventuel tirage de 10%, nous pourrions risquer 4% par transaction, et notre dépôt aurait augmenté de 177% pendant deux ans, soit 90% par an en dollars américains!


Epilogue

Le prix n’est jamais trop élevé pour commencer à acheter, et n’est jamais trop bas pour commencer à vendre.

Ce n’est pas la pensée qui fait beaucoup d’argent. C’est un siège.

Les stratégies décrites ci-dessus peuvent être modifiées et peuvent afficher un rendement encore plus élevé avec un prélèvement ne dépassant pas 10%. N’essayez pas de trader trop souvent, mieux vaut trouver un broker qui fournit non seulement un « ensemble standard » de symboles de deux douzaines de paires de devises et trois douzaines d’actions, mais au moins trois ou quatre cents symboles (actions, contrats à terme). Plus probablement, les symboles ne seront pas corrélés et votre dépôt sera plus sécurisé. Une remarque de plus - les actions montrent de meilleurs résultats que les paires de devises.


P.S. (une remarque publicitaire)

Mon Chartist »PnF Chartist script est disponible sur le marché. Il dessine des graphiques de points et de figures dans des fichiers texte en utilisant des citations fournies par MT4, MT5 ou Yahoo finance. Utilisez-le pour la recherche visuelle des modèles de prix, car il n’y a pas de meilleur testeur / optimiseur que votre cerveau. Dès que vous trouvez des modèles, utilisez les modèles EA de cet article pour trouver des preuves de vos idées.

Traduit du russe par MetaQuotes Ltd.
Article original : https://www.mql5.com/ru/articles/910

Fichiers joints |
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)
Construire une start-up de technologie sociale, Première partie Envoyez des Tweets sur vos signaux MetaTrader 5 Construire une start-up de technologie sociale, Première partie Envoyez des Tweets sur vos signaux MetaTrader 5
Aujourd’hui, nous allons apprendre à lier un terminal MetaTrader 5 à Twitter afin de pouvoir tweeter les signaux de trading de vos EA. Nous développons un système d’aide à la décision sociale en PHP basé sur un service Web RESTful. Cette idée vient exceptionnellement d’une conception du trading automatique appelée trading assisté par ordinateur. Nous voulons que les capacités cognitives des traders humains filtrent les signaux de trading qui, autrement, seraient automatiquement mis sur le marché par les Experts Advisors.
Indicateur de construction d'un graphique à trois sauts de ligne Indicateur de construction d'un graphique à trois sauts de ligne
Cet article est consacré au tableau des trois sauts de ligne, suggéré par Steve Nison dans son livre « Beyond Candlesticks ». Le plus grand avantage de ce graphique est qu’il permet de filtrer les fluctuations mineures d’un prix par rapport au mouvement précédent. Nous allons discuter du principe de la construction graphique, du code de l’indicateur et de quelques exemples de stratégies de trading basées sur celui-ci.
Comment accéder à la base de données MySQL à partir de MQL5 (MQL4) Comment accéder à la base de données MySQL à partir de MQL5 (MQL4)
L'article décrit le développement d'une interface entre MQL et la base de données MySQL. Il traite des solutions pratiques existantes et offre un moyen plus pratique d'implémenter une bibliothèque pour travailler avec des bases de données. L'article contient une description détaillée des fonctions, la structure de l'interface, des exemples et certaines des fonctionnalités spécifiques de l'utilisation de MySQL. Comme pour les solutions logicielles, les pièces jointes des articles incluent les fichiers de bibliothèques dynamiques, de la documentation et des exemples de scripts pour les langages MQL4 et MQL5.
SQL et MQL5 : Travailler avec la base de données SQLite SQL et MQL5 : Travailler avec la base de données SQLite
Cet article est destiné aux développeurs qui seraient intéressés par l'utilisation de SQL dans leurs projets. Il explique les fonctionnalités et les avantages de SQLite. L'article ne nécessite pas de connaissance particulière des fonctions SQLite, mais une compréhension minimale de SQL serait bénéfique.