English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Contos de Robôs de Negociação: É Mais ou Menos?

Contos de Robôs de Negociação: É Mais ou Menos?

MetaTrader 5Negociação | 14 julho 2014, 09:33
1 462 0
Roman Zamozhnyy
Roman Zamozhnyy

Antes que eu possa resolver um problema, devo provar que estou certo quando acho que encontrei a solução.

Conheço apenas uma maneira de provar isso, com o meu próprio dinheiro.

Jesse Livermore


Prólogo

Em A Última Cruzada analisamos bastante um método que ainda não é amplamente utilizado na atualidade e interessante para a exibição das informações de mercado - gráficos de ponto e figura. O script oferecido podia traçar um gráfico. No entanto não foi sugerido uma negociação automatizada. Agora podemos tentar automatizar o processo de negociação usando o gráfico ponto e figura para análise e tomada de decisão sobre a direção e o volume de negócios.

Não vou escrever aqui os princípios básicos do desenho; basta olhar para um gráfico típico:

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

Eu não vou argumentar que as oportunidades de negociação estão claramente visíveis nesta tabela; Eu apenas sugiro que você verifique duas hipóteses na negociação:

Negociação com tendência primária — comprar no mercado touro e vender no urso.

Usar stop losses, definidos antes de entrar no mercado.

  • comprar acima do nível de suporte usando uma stop order (ordem pendente) acima do alto da coluna "X" anterior, vender abaixo da linha de resistência usando uma ordem sell stop abaixo coluna da "O" anterior; usar um trailing stop no nível do pivô;

Deixe os seus lucros crescerem.

Fechar operações com prejuízo (geralmente boas entradas mostram imediatamente o lucro).

  • entrar com posição comprada quando a linha resistência é quebrada, entrar com posição vendida quando a linha suporte é quebrada; definir stop loss no nível pivô, definir trailing stop na linha de tendência.


Como Escolher o Volume

Preste atenção nas citações de um mestre da especulação em ações: usar stop orders (ordens pendentes). Eu prefiro entrar no mercado com um certo volume de modo que as ordens desencadeadas pelo Stop Loss não sejam um percentual maior do que eu possa aceitar (o que Ralph Vince chama ideal F em seu A Matemática da Gestão do Dinheiro). O risco de perda por operação é uma variável bem otimizável (opt_f no código abaixo).

Assim, temos uma função que coloca uma ordem de compra/venda com o mecanismo de cálculo do volume dependendo do risco aceitável por transação:

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


Usar Qual Critério de Otimização?

Na verdade existem apenas dois critérios de otimização: minimização ou rebaixamento em determinado nível de retorno, ou então, maximização do balanço para um certo nível de rebaixamento. Eu prefiro otimizar pelo segundo critério:

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

Onde o risco acima do nível de rebaixamento na estratégia é inaceitável para mim. Esta também é uma das variáveis a ser otimizada.


Quando Reotimizar?

Alguns reotimizam estratégias em intervalos de tempo (por exemplo, uma vez por semana, um mês), em intervalos de operações (após 50, 100 operações) ou quando o mercado muda. Na verdade a necessidade de reotimização depende apenas do critério de otimização selecionado no parágrafo anterior. Se o rebaixamento fica abaixo do parâmetro de risco máximo permitido, nós reotimizamos a estratégia; se tudo funciona ok, deixamos trabalhar como está. Rebaixamento superior a 10% é inaceitável para mim. Assim se o sistema tem um rebaixamento maior durante a operação eu reotimizo.


Posso Otimizar Tudo de Uma Vez?

Infelizmente no testador estratégia você não pode otimizar variáveis externas para o modo "Todos os ativos selecionados na Observação de Mercado". Então vamos escolher os instrumentos (ativos) do mercado juntamente com outras variáveis externas otimizáveis da seguinte forma:

//+------------------------------------------------------------------+
//| 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 necessário, você pode adicionar os instrumentos (ativos) na função para selecionar o símbolo e a enumeração (a função é chamada em OnInit()).


Qual Robô Nós Criamos?

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

     };
  };

Para Estratégia 1: "comprar acima do nível de suporte usando uma stop order (ordem pendente) acima do alto da coluna "X" anterior, vender abaixo da linha de resistência usando uma ordem sell stop abaixo coluna da "O" anterior; usar um trailing stop no nível do pivô;":

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

Para Estratégia 2: "entrar com posição comprada quando a linha resistência é quebrada, entrar com posição vendida quando a linha suporte é quebrada; definir stop loss no nível pivô, definir trailing stop na linha de tendência.":

//+------------------------------------------------------------------+
//| 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 leitor, por favor observe algumas coisas:

  • Os preços dos ativos do mercado variam num alcance muito grande, a partir de centavos para dezenas de milhares (exemplo - ações e CFDs na Bolsa de Valores Japonesa). Portanto eu uso o algoritmo de preço para o gráfico ponto e figura para evitar definir valores de um a dezenas de milhares de pips para o tamanho da caixa.
  • A indexação do array do gráfico ponto e figura começa do zero, de modo que o índice da última coluna seja igual ao número de colunas menos um.
  • O valor da linha suporte, se for utilizado, é maior do que -10, mas menor do que o algoritmo de preço. Se nenhuma linha suporte (ou resistência) é usada, seu valor no array do gráfico é -10. Portanto as condições para rompimento das linhas suporte/resistência são escritas da mesma forma como no código de Estratégia 2 acima.

Veja o código das funções auxiliares nos anexos abaixo. O código do gráfico é muito grande, então eu não o escrevi no artigo, ver com comentários nos anexos abaixo.


Resultados da Negociação do EA

Eu preparei dois conjuntos de ativos do mercado nos arquivos symbol_list_1.mhq e symbol_list_2.mhq para otimização; eles incluem pares de moedas e CFDs de ações do índice Dow.

Janela de Configuração:

Opções de teste

No primeiro caso, a janela de configuração do testador estratégia é a seguinte:

Parâmetros de Otimização

Observe a Linha Inicial do Teste. O robô requer pelo menos algumas colunas do gráfico para análise e tomada de decisão; e quando você define o tamanho da caixa igual a 50 pips ou mais, o histórico de um ano muitas vezes não é o suficiente até mesmo para uma coluna. Portanto para gráficos com tamanho da caixa de 50 pips ou mais, usar o intervalo de cerca de três anos ou mais a partir do início operacional do robô, definir o início da operação do robô no parâmetro "Testing Start" na janela de configuração. No nosso exemplo, para testar com uma tamanho da caixa de 100 pips desde 01.01.2012, especificar intervalo de 01.01.2009 na aba Configuração do Testador de Estratégia e definir o intervalo de 01.01.2012 na aba Parâmetros de Entrada.

O valor falso do parâmetro "Trade minimum lot?" indica que o tamanho do lote depende do balanço e da variável "Risk per Trade, %" (neste caso 1% por negociação, mas também pode ser otimizado). "Max Drawdown, %" é o critério de otimização na função OnTester(). Neste artigo, vou usar apenas duas variáveis para otimização: "Symbol" e "Box size in pips".

Período de otimização: 2012-2013. O EA trabalha melhor no gráfico EURUSD, já que o símbolo proporciona uma melhor cobertura de tick. A tabela abaixo contém um relatório completo para o teste com vários pares de moedas com caixa de tamanho base 10 (b_10) na primeira estratégia.

Passe Resultado Lucro Resultado Esperado Fator de Lucro Fator de Recuperação Índice Sharpe Personalizado Patrimônio DD % Negociações Símbolo Caixa
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

Aqui está uma tabela de resumo para vários símbolos e valores de tamanho de caixa:

Estratégia Símbolos Tamanho da Caixa Negociações Patrimônio DD % Lucro Resultado Balanço Esperado
1 Moedas 10 1 659 Setembro -10 214 2 030 2 030
1 Moedas 20 400 5 1 638 2 484 2 484
1 Ações 50 350 60 7 599 7 599 15 199
1 Ações 100 81 2 4 415 4 415 17 659
2 Moedas 10 338 20 -4 055 138 138
2 Moedas 20 116 8 4 687 3 986 3 986
2 Ações 50 65 6 6 770 9 244 9 244
2 Ações 100 12 1 -332 -332 -5 315

O que vemos?

Existem tolos que sempre estão fazendo errado.

E existem tolos de Wall Street acreditando que você deve sempre negociar.

Não há ninguém no mundo tendo sempre todas as informações necessárias para comprar ou vender ações de maneira completamente coerente.

A conclusão pode parecer estranho para você: o seu depósito é provavelmente muito maior com menos negociações. Se há dois anos nós deixássemos nosso EA negociando ações com o tamanho da caixa igual a 100 e o risco por negociação igual a 1%, o EA faria apenas 81 operações (com média de 1,25 operações por símbolo a cada ano), o nosso depósito teria crescido 44 % e a média do rebaixamento patrimônio líquido teria sido um pouco acima de 2%. Aceitando possível rebaixamento de 10%, poderíamos arriscar 4% por operação, e nosso depósito teria crescido 177% em dois anos, ou seja, 90% ao ano em dólares norte-americanos! dólares!


Epílogo

O preço nunca é alto demais para começar a comprar e nunca é muito baixo para começar a vender.

Não é pensando que se faz o dinheiro grande, é sentado.

As estratégias acima descritas podem ser modificadas e podem mostrar um rendimento ainda maior com o rebaixamento não superior a 10%. Não tente negociar muitas vezes, é melhor encontrar uma corretora que não proporciona apenas um "conjunto padrão" de duas dezenas de pares de moedas e três dezenas de ações, mas pelo menos três ou quatro centenas de símbolos (ações, futuros). É mais provável que os símbolos não serão correlacionados e seu depósito estará mais seguro. Uma observação a mais - ações apresentam melhores resultados do que os pares de moedas.


P.S. (um comentário de publicidade)

Meu script PnF Chartist está disponível no Mercado. Ele desenha gráficos de ponto e figura em arquivos de texto usando cotações fornecidas pelo terminal MT4, MT5 ou Yahoo finanças. Use-o para a busca visual dos padrões de preços, uma vez que não existe melhor testador/otimizador do que seu cérebro. Assim que você encontrar padrões, usar os modelos de EA deste artigo para provar de suas idéias.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/910

Arquivos anexados |
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)
Criando Filtros Digitais Sem Atraso Criando Filtros Digitais Sem Atraso
O artigo descreve uma das abordagens para a determinação de um sinal útil (tendência) num fluxo de dados. Pequenos testes de filtragem (suavização) aplicados às cotações do mercado demonstram o potencial para a criação de filtros digitais sem atrasos (indicadores) que não são redesenhados nas últimas barras.
SQL e MQL5: Trabalhando com Banco de Dados SQLite SQL e MQL5: Trabalhando com Banco de Dados SQLite
Este artigo é destinado aos desenvolvedores interessados ​​em usar SQL em seus projetos. Ele explica as funcionalidades e vantagens do SQLite. O artigo não exige conhecimentos especiais de funções SQLite, mas é interessante um conhecimento mínimo de SQL.
Provedores de Sinal Johnpaul77: "Nossa estratégia continua a ser rentável por mais de três anos. Então, por que devemos mudar isso?" Provedores de Sinal Johnpaul77: "Nossa estratégia continua a ser rentável por mais de três anos. Então, por que devemos mudar isso?"
Vamos revelar um pequeno segredo: Os visitantes do site MQL5.com passam a maior parte do seu tempo na página do sinal Johnpaul77. Ele é líder em nosso ranking de sinais, com cerca de 900 assinantes e com fundos de contas reais no valor total de $5.7 milhões. Entrevistamos o provedor deste sinal. Acontece que há quatro deles! Como são distribuídos os deveres entre os membros da equipe? Quais são as ferramentas técnicas que eles usam? Por que eles se auto-denominam de John Paul? E, finalmente, como que simples jogadores da Indonésia se tornaram os principais provedores de sinais no MQL5.com? Descubra tudo neste artigo.
Contratos futuros contínuos em MetaTrader 5 Contratos futuros contínuos em MetaTrader 5
O curto período dos contratos futuros complica sua análise técnica, é tecnicamente difícil de analisar este tipo de ativo. Por exemplo, o número de barras no gráfico diário do contrato futuro do índice de Ações Ucraniana UX-9.13 é maior do que 100, portanto o trader cria longos contratos futuros sintéticos. Este artigo explica como emendar contratos futuros com datas diferentes no terminal MetaTrader 5.