English Русский 中文 Español Deutsch 日本語
Romper o limite do verificador de estratégia em testes de cobertura do EA

Romper o limite do verificador de estratégia em testes de cobertura do EA

MetaTrader 4Testador | 22 fevereiro 2016, 14:02
1 284 0
chayutra sriboonruang
chayutra sriboonruang

Introdução

Uma ideia de teste de cobertura do EA será fornecida neste artigo. Como você sabe, o verificador de estratégia tem seu próprio limite incapacitando a abertura de qualquer ordem para outro símbolo. Cada usuário que gostaria de testar sua própria cobertura dos Expert Advisors precisa testá-la/testá-los ao vivo somente uma vez. Mas isso limita nossas capacidades? Estou certo de que cada cobertura do operador precisa ser testada anteriormente em seu próprio EA em um trading ao vivo. Sendo assim, sugiro a ideia de gerar um verificador de comportamento de estratégia (parecido com o verificador) à todos vocês com esperança de que ele possa nos ajudar a romper o limite do verificador de estratégia MT4 e espero que ele seja útil para posterior utilização.



O conceito do verificador virtual


A ideia de um verificador virtual apareceu na minha cabeça enquanto trabalhava com a função "Arquivos" em mq4. Uma ideia de levar alguns dados importantes de um arquivo para definir um esquema de trading virtual saiu do meu cérebro. "Esta pode ser uma resposta de como testar minha cobertura do EA?" Vamos tentar.

Meu verificador virtual não precisa de nenhum outro programa externo ou software. Tudo pode ser feito por meio de parâmetros mq4. O conceito deste verificador virtual é permitir que as ordens dos parâmetros indicados de abertura ou fechamento da cobertura nos digam para coletar os dados necessários. Tais como preço de abertura, tempo de abertura, preço de fechamento, tempo de fechamento e todos os outros dados importantes. Após os dados necessários estarem ajustados, eles serão usados para comparação com o valor de crédito mais recente de qualquer tipo compatível, como o preço de abertura e última compra, ou preço de abertura e última venda. Tais valores podem nos levar ao método de cálculo do lucro que irá nos guiar para coletar um novo grupo de dados depois que eles encontrarem a condição da cobertura de fechamento.

Estes grupos de dados serão exportados para um arquivo para utilização posterior. Após o teste ser feito e todos os tipos de dados serem coletados para um arquivo(s), seremos capazes de ver "como a cobertura do EA é executada". Ao receber os dados destes arquivos para traçá-los como um indicador da curva de desempenho, acho que podemos terminar o teste virtual da nossa cobertura do EA.

Por este conceito, presumo que podemos obter o resultado do teste que é semelhante ao resultado real do verificador de estratégia. A propósito, esta é apenas uma ideia da criação de um verificador para a cobertura de Expert Advisors. Não vou garantir que ela seja exatamente igual a um verificador real. Mas espero que ela seja uma boa referência para uso futuro.

Vamos começar.



O significado fácil de cobertura de trading

Antes de começar, vamos falar um pouco sobre "COBERTURA".

A maneira fácil de tratar sobre a cobertura é abrindo dois trades opostos de 2 pares de moedas ao mesmo tempo. Isso é para diminuir o risco do trading, se algum subir, outro certamente baixará, mas não há nada para se preocupar, porque temos ordens de compra e venda ao mesmo tempo, então mesmo se perdermos um, nós obtemos um, é por isso que eles chamam de "baixo risco". Existem muitos tipos de estilos de trades opostos no mundo Forex.

  • Para 2 pares de moedas que se movem sempre da mesma forma como o EURUSD e o GBPUSD, a abertura de compra EURUSD e de vendaGBPUSD ao mesmo tempo é uma cobertura.
  • Para 2 pares de moedas que se movem sempre de forma oposta como o EURUSD e o USDCHF, a abertura de compra EURUSD e de vendaUSDCHF ao mesmo tempo, também é uma cobertura.
  • Ou até mesmo abertura de compra e de venda EURUSD ao mesmo tempo também é uma cobertura, mas isto, às vezes, é chamado de "arbitrar".

Na cobertura de trading existem alguns fatos que não se pode duvidar.

  1. A correlação: é a medida estatística da relação entre duas moedas. O coeficiente de correlação varia entre -1 e +1. A correlação de +1 implica que os dois pares de moedas irão se mover no mesmo sentido 100% do tempo. A correlação de -1 implica que os dois pares de moedas irão se mover em posição oposta 100% do tempo. A correlação de zero implica que a relação entre os pares de moedas será completamente aleatória (leia mais aqui).
  2. O tamanho do índice do lote: Para trocar 2 pares de moedas que não se movem da mesma maneira, o índice do lote é absolutamente necessário pois sua própria volatilidade e capacidade de movimento são diferentes, como uma tartaruga e um coelho, se um for a tartaruga, em seguida, o outro será o coelho. O índice do lote pode diminuir o risco afetado por um par de movimento mais poderoso ou um par de coelhos. Colocar o índice do lote mais elevado no par da tartaruga, quando o par do coelho estiver em movimento negativo, garante menos perdas. Depois, você pode ganhar mais da tartaruga positiva, ou em outras palavras, você pode substituir esse lucro negativo da perda do coelho pelo ganho da tartaruga. E assim, a técnica pode garantir que você não perca mais do que abrindo apenas um trade do lado negativo.

A propósito, você já se perguntou como uma cobertura ganha desse estilo de trading. Não se preocupe, sempre haverá uma sobreposição entre 2 pares de moeda, a correlação não é um esquema constante na natureza, frequentemente haverá atraso por um par, um começa a se mover, então o outro seguirá depois, novamente: como o coelho e a tartaruga - um coelho vai descansar e esperar que a tartaruga vença. É por isso que as coberturas ganhar um bom lucro deles. E hoje em dia muitas pessoas usam o estilo de cobertura para fazer dinheiro no Forex, não há nada para se preocupar. Faça uma cobertura, espere e feche quando for exibido um lucro positivo. É isso.



O conceito de cobertura

Antes de começar a codificar o verificador virtual, vamos tentar entender o conceito de cobertura com um experimento. Sem o conceito de cobertura nunca saberemos que tipo de dados devem ser exportados, gravados e calculados. Estes dados podem nos mostrar que tipo de ordem deve ser gerada virtualmente. Neste experimento, irei definir as regras de coberturas como esta.

  • Abra a cobertura diária no início do dia
  • Feche-a quando atingir $100 (assuma o tamanho do loe 1 e 2).
  • Colete os dados de preços de crédito de hora em hora***
  • Limpe-os diariamente quando no começo do novo dia mesmo se eles não atingirem o objetivo.
  • Compre apenas 2 lotes EURJPY e venda 1 lote GBPJPY

De acordo com estas regras as ordens virtuais necessitam diariamente que os preços de abertura (de ambos os pares) sejam utilizados como uma ordem de preço de abertura. Para calcular o lucro intraday, o preço de cada hora, como preço de crédito diário, deve ser registrado como dados para a ordem de preço de fechamento (peça para venda ou compra para comprar) e deve ser registado juntamente com o tempo do crédito (para certificar-se de que o preço do crédito seja o mesmo valor do tempo). E devido ao conceito de abertura da cobertura diária, vou separar todos os dados necessários em 2 tipos de arquivo que estão abertos diariamente e valores de crédito para 2 pares. Ambos os 2 tipos de dados serão exportados como um arquivo de string(s) com nomes diferente, como GBPJPYD1.csv e GBPJPYTick.csv.

E por causa dos dados de crédito, queríamos que o verificador virtual fosse o mais similar possível em relação ao verificador real, estes 2 passos têm de ser processados.

  • Fazendo um script para exportar o preço diário de abertura do GBPJPY para um arquivo
  • Fazendo um script para exportar o preço diário de crédito do GBPJPY para um arquivo

E as 2 etapas também devem ser feitas para o EURJPY.

Mas eu acho que nós podemos combiná-las em um expert advisor, este EA deve exportar os 2 tipos de dados em 2 arquivos separados. Em seguida, após este EA terminar o processo de gravação de dados, um novo EA para gerar o trading virtual irá obter todos os dados do GBPJPY e EURJPY de todos os arquivos exportados para realizar a visualização do teste virtual.



Os 3 passos para romper o limite de teste


Com a ideia acima, cheguei à conclusão de que o nosso sonho de romper esse limite pode ser feito pelas 3 etapas seguintes.

  1. Pegue os dados de preços e coloque-os como saída em alguns arquivos utilizando um EA.
  2. Gere o trading virtual com outro EA separado que também exporte o resultado como um arquivo.
  3. Revise o resultado como um indicador em uma janela separada.

Vamos iniciar a primeira etapa.



Etapa 1: Exporte o preço de dados

Abaixo está o Expert Advisor para exportar o preço diário de abertura do símbolo anexado em um arquivo chamado "GBPJPYD1.csv" para GBPJPY e "EURJPY D1.csv" para EURJPY, nesse meio tempo ele irá exportar o preço do crédito também em um arquivo chamado "symbolT. cSV" (o mesmo que arquivo D1). Por favor, leia os comentários para aprender sobre o funcionamento do EA.

Nota: Todos os arquivos criados por este EA serão exportados para o diretório "MetaTrader 4/verificador/ arquivos".

//+------------------------------------------------------------------+
//|                                                    symbol-D1.mq4 |
//|                                                    A Sexy Trader |
//|                                  http://pipsmaker.wordpress.com/ |
//+------------------------------------------------------------------+
#property copyright "A Sexy Trader"
#property link      "http://pipsmaker.wordpress.com/"
#include <stdlib.mqh>
 
extern string StartDate = "2007.03.17"   //set the starting date to get the same time data
             ,StopDate  = "2007.06.28";  //set the testing time limit to protect the over 
                                         //data recording process
 
extern bool For_OP_SELL = true;/*This is to guide for the right type of data to be collected
                                 ->if For_OP_SELL = true 
                                   the daily Open will be collected as an order open price
                                 ->if For_OP_SELL = false , means for OP_BUY,
                                   the daily Open+SPREAD will be collected instate.
                               */
                               
string name,tname;
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
 
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//-------------------------------------------------------------------+
//| Some Essential Parameters In This EA                             |
//-------------------------------------------------------------------+
   int day                   // a variable to mark that today Open has been collected 
      ,ho                    // handle of the file recording the Open price 
      ,ht                    // handle of the file recording the tick price
      ,x=1                   /* the order of D1 file increasing every time D1 data is 
                             equal to 4086 characters and generate the new recording file*/
      ,xt=1                  // same as x but for tick data
      ,bartime               // a variable to mark that current bar's Open has been collected 
      ; 
   double ot                 // latest Open Time
         ,op                 // latest Open price
         ,lt                 // latest tick time
         ,ltk                // latest tick price
         ;
   string OStr               // the string to collect the daily open
         ,TStr               // the string to collect the tick value
         ;
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {   
    
    /*---------------------Only collect the data in the specific time period.----------------------*/  
    if(TimeToStr(TimeCurrent(),TIME_DATE)>=StartDate && TimeToStr(TimeCurrent(),TIME_DATE)<=StopDate)  
    {
       name=Symbol()+x+"D1.csv";       // setup the name of daily open price file
       tname=Symbol()+xt+"T.csv"       // the name of tick price file
            ;
//----       
      if(day!=TimeDay(Time[0]))        // the new day has come
       {
         ot=Time[0];                   // get the new bar time
         if(For_OP_SELL)op=Open[0];    // get the new order open price for SELL Symbol 
                                                 
         else           op=Open[0]+MarketInfo(Symbol(),MODE_SPREAD)*Point;
                                       // else if collecting for the BUY Symbol
         
 
         OStr=OStr+TimeToStr(Time[0],TIME_DATE)+",";//collect the new time data separate each data with ","
         OStr=OStr+DoubleToStr(op,Digits)+",";      //now the new open price
       
       //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~now it's time to export as a file 
       
       ho=FileOpen(name ,FILE_CSV|FILE_WRITE);  // open a file to record the daily open
       if(ho>0)                                 // if the file Symbol()+x+"D1.csv" exist
       {
        FileWrite(ho,OStr);                     // write the collected data
        FileClose(ho);                          // close the file every time your file process done
        if(StringLen(OStr)==4086){x++;OStr="";} /* if the data contains 4086 characters set new x to*/
       }                                        /*   create the new file and prepare the new string for 
                                                   the new file 
                                                */            
        
       Print(TimeToStr(Time[0],TIME_DATE));     // print the collected day time 
       
       int thex=FileOpen(Symbol()+"x.csv",FILE_CSV|FILE_WRITE);
                                                // create a file to record "how many x?" for D1 file for further usage
       if(thex>0)                               // if the file exist
       {
        string xs=DoubleToStr(x,0);             // transform x into string 
        FileWrite(thex,xs);                     // write the x value
        FileClose(thex);                        // close file (every time you finish)
       } 
        
        
        day=TimeDay(Time[0]);                   // now mark today as collected 
       }
 
//--------------------------------FOR TICK VALUE
       /*Because of the decision of collecting the tick data hourly*/
       if(bartime!=Time[0])                     // the new hourly bar has come
                                                // and to make it more flexible when you decided 
                                                      // to collect data in another time frame
       {
         lt=TimeCurrent();                      // get the tick time 
         
         if(!For_OP_SELL) ltk=Bid;              // the tick price for sell order 
         else             ltk=Ask;              // in case for buy order
         
         TStr=TStr+TimeToStr(lt,TIME_DATE|TIME_MINUTES)+",";
                                                // insert the data into the collected string 
         TStr=TStr+DoubleToStr(ltk,Digits)+","; //
         
       //~~~~~~~~                               // now export the data 
       ht=FileOpen(tname,FILE_CSV|FILE_WRITE);  // open a file to record the tick value
       if(ht>0)                                 // if the file Symbol+xt+"T.csv" exist
       {
        FileWrite(ht,TStr);                     // write the collected tick with time 
        FileClose(ht);                          // finish.
        if(StringLen(TStr)==4080){xt++;TStr="";}// prepare for new file if this file reached 4080 character
       }
       
       int thext=FileOpen(Symbol()+"xt.csv",FILE_CSV|FILE_WRITE);
                                                // record the xt value .. same as D1 file 
                                                
       if(thext>0)                              // if the file exist
       {
        string xts=DoubleToStr(xt,0);           // transform into string 
        FileWrite(thext,xts);                   // write xt
        FileClose(thext);                       // done
       } 
     bartime=Time[0];                           // mark as current hourly bar Open price has been collected
     }  
   }    
   else if(TimeToStr(TimeCurrent(),TIME_DATE)>StopDate)  // if out of specified period  
   Print("Done.");                                       // let us know it all done.
//----
   return(0);
  }
//+------------------------------------------------------------------+

Etapa 2: Gere o trading virtual

Esta etapa é a mais excitante. A etapa de fazer com que a cobertura do EA seja testável pelo verificador de estratégia. Veja o script abaixo para saber com o que isto se parece. E não se esqueça de ler os comentários para entender como isto funciona. E, assim como no primeiro EA, o arquivo resultante será exportado para o diretório "MetaTrader 4/verificador/arquivos".

//|                                                 VirtualHedge.mq4 |
//|                                                    A Sexy Trader |
//|                                  http://pipsmaker.wordpress.com/ |
//+------------------------------------------------------------------+
#property copyright "A Sexy Trader"
#property link      "http://pipsmaker.wordpress.com/"
#include <stdlib.mqh>
 
extern string  StartDate         = "2007.03.17";    // specify the testing period the same as collected data
extern string  StopDate          = "2007.06.27";
extern string  BaseSymbol        = "GBPJPY";        // the base symbol          
extern string  HedgeSymbol       = "EURJPY";        // the hedge symbol
 
extern int     Base_OP           = OP_SELL;         // by the rules always sell GBPJPY
extern int     Hedge_OP          = OP_BUY;          // and always buy EURJPY
 
extern double  BaseLotSize       = 1.0;             // take the lot size of 1 for GBPJPY
extern double  HedgeLotSize      = 2.0;             // and take 2 lots for EURJPY
 
extern double  ExpectProfit$     = 100;             // always close when reach $100
 
extern bool    PrintDetails      = true;            // print the order opening and closing detail ?
 
int BSP                                      // the spread of GBPJPY 
   ,HSP                                      // the spread of EURJPY
   ,BOP=-1                                   // OrderType of GBPJPY
   ,HOP=-1                                   // OrderType of EURJPY
   ,day=0                                    // for marking that today hedge was executed
   ,hr                                       // handle of the file for exporting the hedge result
   ,p=1
   ,BC                                       // the base-symbol's contract size
   ,HC                                       // the hedge-symbol's contract size
   ,floating=0                               // for marking as there are some orders currently floating
   ,Pointer=0                                // the Pointer of each string data
   ,AL                                       // Account Leverage
   ,on                                       // order number
   ;
double BOpen                                 // open price of base symbol
      ,HOpen                                 // open price of hedge symbol
      ,BLots                                 // base symbol lotsize
      ,HLots                                 // base symbol lotsize
      ,lastTick                              // to mark the last tick for calculating the current profit
      ,BPF                                   // base symbol order profit
      ,HPF                                   // hedge symbol order profit
      ,TPF                                   // the total profit
      ,CurBalance                            // the array to collect the hedge results
      ,CurB=0                                // the current balance
      ,BTick                                 // Base tick
      ,HTick                                 // Hedge tick
      ,BD1Time                               // Base daily open time 
      ,HD1Time                               // Hedge daily open time 
      ,BTTime                                // Base tick time 
      ,HTTime                                // Hedge tick time 
;
 
string CurTrade                              // a string to show the current performance as a comment 
      ,BORD                                  // a string to specify the type of arrows and text of base symbol
      ,HORD                                  // same thing but for hedge symbol                   
      ,hobstr                                // the whole string of the base symbol open price data
      ,bstr                                  // the string of all daily data of base Symbol 
      ,hstr                                  // the string of all daily data of hedge Symbol
      ,btstr                                 // the string of tick data of base Symbol
      ,htstr                                 // the string of tick data of hedge Symbol
      ,pstr                                  // the string for exporting result data
      ;                   
 
color SELLCL=DeepSkyBlue                     // the color of arrows to mark that sell order was executed
     ,BUYCL=HotPink                          // the color of arrows to mark that buy order was executed
     ,BCL                                    // the color of base symbol, varies by the Base_OP parameter
     ,HCL                                    // the color of hedge symbol, varies by the Hedge_OP parameter
     ;
     
bool closed=true                             // for marking as all trades were closed
     ,trimb=true                             // get rid of taken data of base Symbol or not?
     ,trimh=true                             // get rid of taken data of hedge Symbol or not?
     ,trimbd1=true                           // get rid of taken daily data of base Symbol or not?
     ,trimhd1=true                           // get rid of taken daily data of hedge Symbol or not?
     ;     
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
//----
   CurBalance=AccountBalance();                      //mark the initial deposit
   CurB=AccountBalance();                            //mark the current balance
   pstr=pstr+DoubleToStr(CurBalance,2)+",";          //collect the performance string
   
   AL=AccountLeverage();                             //get the Account Leverage
   
   BSP=MarketInfo(BaseSymbol  ,MODE_SPREAD);         //get the spread
   HSP=MarketInfo(HedgeSymbol ,MODE_SPREAD);
   
   BC =MarketInfo(BaseSymbol  ,MODE_LOTSIZE);        //get the contract size for calculating profit
   HC =MarketInfo(HedgeSymbol ,MODE_LOTSIZE);
   
   BOP=Base_OP;                                      //get the OrderType 
   HOP=Hedge_OP;
   
   BLots=BaseLotSize;                                //get the lot size
   HLots=HedgeLotSize;
   
   string RName=BaseSymbol+"_"+HedgeSymbol+"_result"+p+".csv";    
                                                     //name the performance file
                                                     //this file is needed to copy to 
                                                     /* Program files/MetaTrader 4 /Experts/files */
   
   hr =FileOpen(RName ,FILE_CSV|FILE_WRITE);         //open the file to export the initial deposit
 
   if(hr>0)                                          //if the file exist
   {
    FileWrite(hr,pstr);                              //export the initial deposit
    FileClose(hr);                                   //close file
   }
   
   if(Base_OP==OP_SELL){BCL=SELLCL;BORD="sell";}     //specify the parameter leading to create 
   else                {BCL=BUYCL; BORD="buy";}      // the trading arrow and text
   if(Hedge_OP==OP_BUY){HCL=BUYCL; HORD="buy";}
   else                {HCL=SELLCL;HORD="sell";}
   
   getdata(BaseSymbol);                              //get all data of BaseSymbol
   getdata(HedgeSymbol);                             //all data of HedgeSymbol
                                                     //the function located at the bottom 
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
string RName=BaseSymbol+"_"+HedgeSymbol+"_result"+p+".csv"; //name the performance file
 
//--------------------------Only perform the show of specified period--------------------------// 
if(TimeToStr(TimeCurrent(),TIME_DATE)>=StartDate && TimeToStr(TimeCurrent(),TIME_DATE)<=StopDate)
                                                                               //mark as no any order now
{
 if(day!=TimeDay(Time[0]))                                  //the new day has come
 {
  
  {
   if(BOpen!=0 && HOpen!=0)                                 //check if yesterday hedge still floating
   {
 
    if(Base_OP==OP_BUY)                                     //the base-symbol's current profit
     {
      BPF=((BTick-BOpen)*BLots*BC)/BOpen;                   
     }
    else
    {
     BPF=((BOpen-BTick)*BLots*BC)/BOpen;
    }
    
    if(Hedge_OP==OP_BUY)                                    //the hedge-symbol's current profit
    {  
     HPF=((HTick-HOpen)*HLots*HC)/HOpen;
    }
    else
    {
     HPF=((HOpen-HTick)*HLots*HC)/HOpen;
    }
    
    TPF=BPF+HPF;                                            //the total current profit
    
    CurB+=TPF;
    
    CurBalance=CurB;                                        //get the latest AccountBalance
    
    pstr=pstr+DoubleToStr(CurBalance,2)+",";                //insert into the performance string
    
    floating=0;                                             //mark as no any order now
 
    BOpen=0;                                                // block the profit calculation process
    HOpen=0;
    
    if(BOpen==0 && HOpen==0)                                //make sure there is no any order now
    {
     closed=true;                                           //mark all orders were closed
     
     CreateObject("R : "+on,OBJ_TEXT,Time[0],Close[0],0,0,DarkViolet,"","Cleared With Profit Of : "+DoubleToStr(TPF,2));
                                                            //create the cleared all orders text
     
     if(PrintDetails)Print("Cleared Hedge With Profit : "+DoubleToStr(TPF,2));
                                                            //print latest action if PrintDetails allowed
                                                            
      hr =FileOpen(RName ,FILE_CSV|FILE_WRITE);             //open the result file to prepare for file writing
      if(hr>0)
      { 
       FileWrite(hr,pstr);                                  //export the data
       FileClose(hr);
      }
      if(StringLen(pstr)>4086){p++;pstr="";}                //set the new file name if pstr is larger than 4086 characters
    
                                                            
                                                            
      int thep=FileOpen("p.csv",FILE_CSV|FILE_WRITE);       //this file is needed to copy to 
                                                            /* Program files/MetaTrader 4 /Experts/files */  
                                                            //too
                                                            
                                                            // record the p value as a file 
                                                
       if(thep>0)                                           // if the file exist
       {
        string ps=DoubleToStr(p,0);                         // transform into string 
        FileWrite(thep,ps);                                 // write p
        FileClose(thep);                                    // done
       } 
    
    }  
   }   
   
   if(floating==0)                                          //now all yesterday hedge were cleared 
   {
    trimb=true; trimh=true;                                 //allow getting tick data for today to work
       
            
    //----------GETTING TODAY ORDER OPEN PRICE AND TIME----------//  
         if(trimbd1)                                              //getting the daily base price allowed
         {
             Pointer=StringFind(bstr,",",0);                      //find the nearest "," from the beginning of string
             BD1Time=StrToTime(StringSubstr(bstr,0,Pointer));     //get the time value located before the "," syntax
             bstr=StringSubstr(bstr,Pointer+1,0);                 //trim off the taken data
             
             Pointer=StringFind(bstr,",",0);                      //find the nearest "," from the trimmed data string
             BOpen=StrToDouble(StringSubstr(bstr,0,Pointer));     //get the PRICE value located before the "," syntax
             bstr=StringSubstr(bstr,Pointer+1,0);                 //trim off the taken data again to prepare for next time 
         }
         if(trimhd1)                                              //getting the daily hedge price allowed
         {
             Pointer=StringFind(hstr,",",0);                      //all processes are the same as bstr above
             HD1Time=StrToTime(StringSubstr(hstr,0,Pointer));     //...
             hstr=StringSubstr(hstr,Pointer+1,0);                 //...   
             
             Pointer=StringFind(hstr,",",0);                      //...
             HOpen=StrToDouble(StringSubstr(hstr,0,Pointer));     //...
             hstr=StringSubstr(hstr,Pointer+1,0);                 //...
         }
    //--------GETTING TODAY ORDER OPEN PRICE AND TIME ENDED--------//  
 
       
       if(BOpen!=0 && HOpen!=0 && CurBalance>(BLots+HLots)*BC/AL)     
               //make sure the data taken is not zero and margin balance still available    
       {
       floating=1;            //mark as hedge sent
       
       closed=false;          //mark as all orders opened
       
       on++;                  //new hedge orders have opened 
        
        if(PrintDetails)      //if PrintDetails allowed
        {
         Print(on+" Opened : "+BaseSymbol+" "+DoubleToStr(BLots,2)+" lots @ "+DoubleToStr(BOpen,Digits)+".");
         Print(on+" Opened : "+HedgeSymbol+" "+DoubleToStr(HLots,2)+" lots @ "+DoubleToStr(HOpen,Digits)+".");
        }
       }
       else                                                 //in case can not send hedge
       {
        Comment("Can Not Open The Trade : No Margin Available");
       }                                                    //let us know 
       
       
       if(closed==false)                                    //hedge sent
       {
                                                            //create the buy and sell arrow and text
                                                            //this function is located at the bottom of the EA
       CreateObject("B : "+on,OBJ_ARROW,Time[0],Open[0]-20*Point,0,0,BCL,BORD,"");
 
       CreateObject("H : "+on,OBJ_ARROW,Time[0],Open[0]+30*Point,0,0,HCL,HORD,"");
       }
   }   
  } 
  
  day=TimeDay(Time[0]);                                     //mark as proceeded
 }  
 
//-------------------------For Each Tick----------------------------// 
 
if(lastTick!=Hour())                 //the new hour has come
{                                                    
  
   if(trimb && StringFind(btstr,",",0)>0)                         //getting base tick allowed
   {
             Pointer=StringFind(btstr,",",0);                     //same process as getting daily data above
             BTTime=StrToTime(StringSubstr(btstr,0,Pointer));
             btstr=StringSubstr(btstr,Pointer+1,0);
             
             Pointer=StringFind(btstr,",",0);
             BTick=StrToDouble(StringSubstr(btstr,0,Pointer));
             btstr=StringSubstr(btstr,Pointer+1,0);  
   }
   if(trimh && StringFind(htstr,",",0)>0)                         //if getting hedge tick allowed
   {    
             Pointer=StringFind(htstr,",",0);
             HTTime=StrToTime(StringSubstr(htstr,0,Pointer));
             htstr=StringSubstr(htstr,Pointer+1,0);
             
             Pointer=StringFind(htstr,",",0);
             HTick=StrToDouble(StringSubstr(htstr,0,Pointer));
             htstr=StringSubstr(htstr,Pointer+1,0);  
   }
  
  
  
  if(TimeDay(BD1Time)==TimeDay(BTTime) && TimeDay(HD1Time)==TimeDay(HTTime))
                                                            //only if the tick is form the same day
  {    
   trimbd1=true; trimhd1=true;                              //allow to get the next day value
   
   if(TimeHour(BTTime)==TimeHour(HTTime))                   //and same time hour
   {                                             
     
     trimb=true; trimh=true;                                //allow to get the next tick value
 
     if(BOpen!=0 && HOpen!=0)                               //if the calculation process allowed
     {
      
      if(Base_OP==OP_BUY)
       {
        BPF=((BTick-BOpen)*BLots*BC)/BOpen;                 //the base-symbol's current profit
       }
      else
      {
       BPF=((BOpen-BTick)*BLots*BC)/BOpen;
      }
    
      if(Hedge_OP==OP_BUY)
      {  
       HPF=((HTick-HOpen)*HLots*HC)/HOpen;                  //the hedge-symbol's current profit
      }
      else
      {
       HPF=((HOpen-HTick)*HLots*HC)/HOpen;
      }
     
      TPF=BPF+HPF;                                          //the total current profit
      
      CurTrade=DoubleToStr(TPF,2);                          //show the current profit
     
      if(TPF > ExpectProfit$)                               //when they need to close  
      {                                                 
       
       BOpen=0;                                             //set the new value of order open price 
       HOpen=0;                                             //and block the profit calculation process
      
       CurTrade="No Any Hedge Order Now.";                  //Hedge was closed 
       
       
       floating=0;                                          //mark as hedge was closed
       CurB+=TPF;
       
       CurBalance=CurB;                                     //get the last balance equity
       
       pstr=pstr+DoubleToStr(CurBalance,2)+",";             //insert into performance string
       
       CreateObject("R : "+on,OBJ_TEXT,Time[0],Close[0],0,0,YellowGreen,"",
                                 "Close With Profit Of : "+DoubleToStr(TPF,2));
                                                            //create the closed text
                                                            
       if(PrintDetails)                                     //Print the last Close detail
       {                                                    
         Print(on+" Closed "+BaseSymbol+" @ "+DoubleToStr(BTick,Digits));
         Print(on+" Closed "+HedgeSymbol+" @ "+DoubleToStr(HTick,Digits));
         Print(on+" Closed Hedge With Profit : "+DoubleToStr(TPF,2));  
       }                                                   
       hr =FileOpen(RName ,FILE_CSV|FILE_WRITE);    //open it again to prepair for file writing
       
       if(hr>0)
       { 
        FileWrite(hr,pstr);                         //export the data
        FileClose(hr);
       }
      
      if(StringLen(pstr)>4086){p++;pstr="";}        //set the new file name if pstr is larger than 4086 characters
       
      
       thep=FileOpen("p.csv",FILE_CSV|FILE_WRITE);
                                                    // record the p value again
                                                
       if(thep>0)                                   // if the file exist
       {
        ps=DoubleToStr(p,0);                        // transform into string 
        FileWrite(thep,ps);                         // write p
        FileClose(thep);                            // done
       } 
      
      }
     }
     
   }
   else                                             //in case the data values are not from the same tick time  
   {
     if(BTTime>HTTime){trimb=false;}                //freeze the offside data to can not be trim off
     
     else             {trimh=false;}
   }
  }
  else                                              //in case tick data is offside from today
  {
     if(BTTime>BD1Time){trimb=false;}               //freeze the offside data to can not be trim off
     else
     if(BTTime<BD1Time){trimbd1=false;}
      
     if(HTTime>HD1Time){trimh=false;}
     else 
     if(HTTime<HD1Time){trimhd1=false;}
  } 
}
 
 
 
lastTick=Hour();                                     //mark as latest tick proceeded
}   
   
   
   Comment("\nBOpen : "+DoubleToStr(BOpen,Digits)    //show the current situation
          ,"\nHOpen : "+DoubleToStr(HOpen,Digits) 
          ,"\nBOT : "+TimeToStr(BD1Time,TIME_DATE)
          ,"\nHOT : "+TimeToStr(HD1Time,TIME_DATE)
          ,"\nBTick : "+DoubleToStr(BTick,Digits)
          ,"\nHTick : "+DoubleToStr(HTick,Digits)
          ,"\nBTT : "+TimeToStr(BTTime,TIME_DATE|TIME_MINUTES)
          ,"\nHTT : "+TimeToStr(HTTime,TIME_DATE|TIME_MINUTES)
          ,"\nfloating : "+floating
          ,"\nclosed : "+closed
          ,"\ntrimb : "+trimb
          ,"\ntrimh : "+trimh
          ,"\n"
          ,"\nCurOrderNo. : "+on
          ,"\nCurProfit : "+CurTrade
          ,"\nCurBalance : "+DoubleToStr(CurBalance,2)
          );
//----
   return(0);                                               //ALL DONE.
  }
//+------------------------------------------------------------------+
//| A Function To Make This Virtual Tester Looks Like The Real One   |
//+------------------------------------------------------------------+
void CreateObject(string name,int type, int time1, double price1, int time2, 
                             double price2, color cl,string ordtype,string txt)
{
    
    if(type==OBJ_TREND)
    {
    ObjectCreate(name,type,0,time1,price1,time2,price2);
    ObjectSet(name,OBJPROP_COLOR,HotPink);
    }
    
    if(type==OBJ_ARROW)
    {
    ObjectCreate(name,type,0,time1,price1);
    ObjectSet(name,OBJPROP_COLOR,cl);
     if(ordtype=="sell")ObjectSet(name,OBJPROP_ARROWCODE,221);
     else              ObjectSet(name,OBJPROP_ARROWCODE,222);
    }
 
    if(type==OBJ_TEXT)
    {
     ObjectCreate(name,type,0,time1,price1);
     ObjectSetText(name,txt,8,"Comic Sans MS",cl);
    }
}
//+------------------------------------------------------------------+
//| GETTING ALL DATA FROM FILES FUNCTION                             |
//+------------------------------------------------------------------+
void getdata(string sym)
{
Comment("Collecting Data.","\n\nPlease Wait........");  //let us know that getting data still in process
      
      int x =FileOpen(sym+"x.csv",FILE_CSV|FILE_READ)   //get how many files of D1 and tick
         ,xt=FileOpen(sym+"xt.csv",FILE_CSV|FILE_READ)
         ,pter=0,s=0,v=0
         ,lastME=0,t=0
         ;
      double ME,U;
      string str,str2;
      int xa=StrToInteger(FileReadString(x))
         ,xta=StrToInteger(FileReadString(xt))
         ,xtc=1
         ;
      FileClose(x);
      FileClose(xt);   
   
      if(xta>xa)xtc=xta;                                     //make it run only in one for loop
      else      xtc=xa;
      
      pter=0;s=0;
      for(int i=1;i<=xtc;i++)                                //the loop to get all string data
      {
       string name=sym+i+"T.csv"                             //set the data file name
             ,d1  =sym+i+"D1.csv"
             ;
       int h=FileOpen(name,FILE_CSV|FILE_READ)               //open all files to read
          ,d=FileOpen(d1  ,FILE_CSV|FILE_READ);
       
       //------------------------------------------------------------
       string source=FileReadString(h);                      //read the tick string
       FileClose(h);
       
        if(sym==BaseSymbol)                                  //if get the data of base symbol 
        {
         btstr=btstr+source;
        }
        else                                                 //if hedge symbol 
        {
         htstr=htstr+source;
        }
 
       //------------------------------------------------------------
       if(d>0)                                               //read the daily data 
       {
         string d1s  =FileReadString(d);FileClose(d);
         
         if(sym==BaseSymbol)                                 //if get base daily data
         {
          bstr=bstr+d1s;
         }
         else                                                //if get hedge data
         {
          hstr=hstr+d1s;
         }
       }
      }
}
//------------------------------------ALL DONE---------------------------------------------//



Etapa 3: Revisão do resultado

Após as ordens virtuais serem executadas e os resultados de cobertura forem registrados, podemos pegar estes dados para demonstrar nosso conceito de cobertura. Para fazer isso, decidi exportar todos os dados gravados como um indicador para traçar a curva de desempenho em uma janela separada como em muitos indicadores como CCI, RSI ou ATR e etc. E todos os arquivos a partir do segundo EA devem ser copiados para o diretório " MetaTrader 4/experts/arquivos".

Para finalizar esta curva, o indicador abaixo é necessário.

//+------------------------------------------------------------------+
//|                                                  performance.mq4 |
//|                                                    A Sexy Trader |
//|                                         http://pipsmaker.wordpress.com/ |
//+------------------------------------------------------------------+
#property copyright "A Sexy Trader"
#property link      "http://pipsmaker.wordpress.com/"
 
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Goldenrod
//---- input parameters
extern string    BaseSymbol="GBPJPY";
extern string    HedgeSymbol="EURJPY";
//---- buffers
double ExtMapBuffer1[]                 //this is the indicator buffer
      ,curve[8888888]                  //this array is for collecting the result from the performance file
      ;
 
int handle;                            //maybe no need to explain anymore
string data;
int len=0
   ,i=0
   ,j=0
   ,p
   ,pv
   ,pter=0
   ;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtMapBuffer1);
   
   IndicatorShortName(BaseSymbol+"~"+HedgeSymbol+" ");
//----
   
   p =FileOpen("p.csv",FILE_CSV|FILE_READ);                       //get how many result files were exported
   pv=StrToInteger(FileReadString(p));
   FileClose(p);
   
   for(int i=1;i<=pv;i++)                                         //the loop to get all exported result as a string
   {
      string name = BaseSymbol+"_"+HedgeSymbol+"_result"+p+".csv";//get the name of the performance file
      handle=FileOpen(name,FILE_CSV|FILE_READ);                   //search for the file to open to read
      if(handle>0)                                                //if the file is exist
      {   
          data=data+FileReadString(handle);                       //get the whole data
          FileClose(handle);                                      //close it
      }
   
   }
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars=IndicatorCounted(),i=0,s=-1;
   
//----
   len=StringLen(data);                              //get the lenght of the data string
  
   pter=0;                                           //set the pointer which use for searching the ","
                                                     /*please be informed that the file csv was collected 
                                                     the result as a string like this 
                                                     1000.54,1100.54,1200.54,1300.54,1400.54
                                                     but the fact is we want only the real data is like this
                                                     1000.54
                                                     1100.54
                                                     1200.54
                                                     1300.54
                                                     1400.54
                                                     so the "," is the key to get the data as above
                                                     and it can be done by finding out the data befor ","
                                                     and get rid off it from the whole data 
                                                     to shift the next data into the front
                                                     and insert each taken off data into the curve array 
                                                     */
   
   for(i=len;i>=0;i--)                               /*the loop to define how many room this array should build
   {                                                   to contain the performance data
                                                     */
    if(StringFind(data,",",0)>0)                     //if there is a nearest "," from the front
    {
     s++;                                            //indicate the room number  
     pter=StringFind(data,",",0);                    //get the point where the first "," exist
     curve[s]=StrToDouble(StringSubstr(data,0,pter));//insert the first data of the whole string
     data=StringSubstr(data,pter+1,0);               //cut the inserted data off
    }                           
    else          break;                             //no data to count anymore , break the loop
 
   ArrayResize(curve,s+1);                           //resize the curve array for furthur usage
//----
   for(i=0,j=s;i<=s;i++,j--)                         //the plotting process bigin
   {
    if(curve[j]>0)ExtMapBuffer1[i]=curve[j];         //plot the performance curve
   }
//----                                               //all the things done.
 
   return(0);
  }
//+------------------------------------------------------------------+



Como usá-los

Antes de baixar uma cópia do meu código, vamos detalhar brevemente "como usá-los?" como um mini manual do usuário.

Para fazer com que a nossa expectativa realmente se torne realidade, existem 5 etapas simples que não podem ser ignoradas. Elas são:

  1. No verificador (não há necessidade de fazer o modo visual), selecione o símbolo D1.mq4 no menu "Expert Advisor:", e no "símbolo:" selecione o primeiro símbolo de cobertura de seu par de cobertura favorito, ajuste período de tempo e horário e o valor "For_OP_SELL" para verdadeiro se este símbolo for para ordem de venda ou definido para falso se este símbolo for para ordem de compra, selecione o período de horário no menu "Período:', clique em "Iniciar" para executar o processo de gravação.
  2. Para o segundo símbolo de cobertura, faça a mesma coisa que na etapa 1 mas *** NÃO ESQUEÇA DE ALTARAR O PARÂMETRO "For_OP_SELL" *** para ajustá-lo no tipo de ordem deste símbolo.
  3. Selecione o VirtualHedge.mq4, defina todas as variáveis, e selecione o símbolo de teste (qualquer símbolo que você desejar). Mas isto precisa do modo visual para ver o desempenho da cobertura.
  4. Copie todos os arquivos relacionados de exibição do desempenho de cobertura do diretório "arquivos de programa/metatrader 4/verificador/arquivos" para o diretório "arquivos de programas/metatrader 4/experts/arquivos" . (talvez incluindo GBPJPY_EURJPY_result1.csv e p.csv, se houver mais de um arquivo de resultado, você precisa copiar todos eles.)
  5. Anexe o performance.mq4 em qualquer gráfico ativo atual para ver o desempenho real de cobertura.

E esta é a curva de performance das minhas regras experimentais.

Oops! Isso é feio. Mas eu acho que o seu será melhor.



Conclusão

Fico feliz que estamos indo para o novo mundo de testar a cobertura do EA. O limite do verificador não é mais problema da cobertura. Mas, a propósito, o conceito de cobertura neste artigo é apenas um exemplo gerado para apenas encurtar o processo de tempo de teste. Para fazer o testador virtual trabalhar com a sua estratégia de cobertura, você precisa listar seus dados importantes, tais como: abertura e fechamento de cada dia, alta, baixa e quaisquer outros tipos. E se você realizar trade com a correlação, todos os valores de correlação de cada tempo específico também devem ser exportados. Por esta lista você vai saber quais dados devem ser gravados, os dados que devem ser calculados e quais dados devem ser enviados como resultado. E para reduzir o tempo de processamento de dados, eu recomendo que você separa o seu período de testes em pedaços pequenos - é melhor do que processar tudo de uma só vez. Por exemplo, se você quiser testar o EA por 1 ano e separá-lo em 4 partes de 3 meses cada, seria melhor. Espero que a sua curva de desempenho se pareça com uma mulher sexy de vermelho e que este artigo o ajude com as coberturas, ou ao menos uma parte delas, ou pelo menos inspire-o a criar um resultado de cobertura maravilhoso. Finalmente, espero que você goste.

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/1493

Arquivos anexados |
performance.mq4 (5.71 KB)
symbol-D1.mq4 (8.23 KB)
VirtualHedge.mq4 (24.81 KB)
Modelo Universal do Expert Advisor Modelo Universal do Expert Advisor
Este artigo ajudará iniciantes em trading a criar Expert Advisors ajustáveis.
Matemática na negociação: Como estimar resultados de trading Matemática na negociação: Como estimar resultados de trading
Nós todos sabemos que "Nenhum lucro obtido no passado garantirá algum sucesso no futuro". No entanto, ser capaz de estimar sistemas de negociação, ainda é muito atual. Este artigo trata sobre alguns métodos simples e convenientes que ajudarão a estimar resultados de trade.
Linguagem MQL4 para Iniciantes. Indicadores técnicos e funções integradas Linguagem MQL4 para Iniciantes. Indicadores técnicos e funções integradas
Este é o terceiro artigo da série "Linguagem MQL4 para Iniciantes". Agora, vamos aprender a utilizar funções integradas e funções para trabalhar com indicadores técnicos. Estes últimas serão essenciais para o desenvolvimento futuro de seus próprios Advisors e indicadores. Além disso, veremos em um exemplo simples, como rastrear sinais de trading para entrar no mercado, assim, você entenderá como usar indicadores corretamente. E no final do artigo você aprenderá algo novo e interessante sobre a própria linguagem.
Como cortar um Código de EA para uma vida mais fácil e menos erros Como cortar um Código de EA para uma vida mais fácil e menos erros
Um conceito simples descrito no artigo permite que as pessoas que desenvolvem sistemas de trading automatizados em MQL4 simplifiquem os sistemas de trading existentes, bem como reduzir o tempo necessário para o desenvolvimento de novos sistemas devido a códigos mais curtos.