Durchbrechen des Strategietester Limits beim Testen eines Hedge EA

chayutra sriboonruang | 24 Februar, 2016

Einführung

In diesem Artikel wird ein Vorschlag zum Testen eines Hedge EA im Strategietester gemacht. Wie Sie wissen, hat der Strategietester seine eigenen Grenzen, durch die er nicht in der Lage ist eine Order für ein anderes Symbol zu öffnen. Jeder Benutzer, der seinen/ihren eigenen Hedge Expert Advisor testen möchte, kann ihn/sie nur live testen. Aber, schränkt das unsere Möglichkeiten ein? Ich bin sicher, dass jeder Hedge-Trader seinen eigenen EA testen muss, bevor er live mit ihm handelt. Also, ich gebe die Idee zum Erzeugen eines virtuellen Strategie-Testverhaltens ()Tester-artig) an euch alle weiter mit der Hoffnung, dass sie uns hilft die Grenzen des MZ4 Strategietesters zu durchbrechen, und ich hoffe, dass sie nützlich in der weiteren Verwendung sein wird.



Das Konzept des Virtuellen Tester


Die Idee eines virtuellen Testers tauchte in meinem Kopf auf, während ich mit der "Files" Funktion in mq4 arbeitete. Der Gedanke einige wichtige Daten aus einer Datei zu entnehmen um ein virtuelles Handelssystem einzurichten, reifte in meinem Verstand. "Kann dies die Antwort zum Testen meines Hedge EA sein?" Probieren wir es aus.

Mein virtueller Tester benötigt kein anderes externes Programm oder Software. Es kann alles mittels der mq4 Parameter umgesetzt werden. Das Konzept dieses virtuellen Testers ist es, uns durch die angegebenen Parameter von öffnenden oder schließenden Hedge Ordern die zu erfassenden benötigten Daten erzählen zu lassen. Daten wie der Eröffnungskurs, Zeitpunkt der Öffnung, Schlusskurs, Zeitpunkt des Schließens und alle anderen wichtigen Daten. Nach dem die benötigten Daten eingerichtet sind, werden sie für den Vergleich mit dem letzten Tick-Wert jedes kompatiblen Typs verwendet, solche wie Eröffnungskurs und letzter Bid, oder Eröffnungskurs und letzter Ask. Solche Werte können uns zu der Profit-Berechnungsmethode leiten, die uns zum Sammeln einer neuen Gruppe Daten führen wird, nachdem diese die Hedge Schließ-Bedingung erfüllen

Diese Gruppen von Daten werden in eine Datei exportiert, für die weitere Verwendung. Nachdem der Test abgeschlossen ist und alle Datentypen in einer Datei(en) gesammelt, sind wir in der Lage "zu sehen, wie der Hedge EA ausgeführt wird". Mit dem Abrufen der Daten aus diesen Dateien, um sie als Indikator der Performance-Kurve zu zeichnen, denke ich, wir können das virtuelle Testen unseres Hedge EA abschließen.

Durch dieses Konzept gehe ich davon aus, dass wir ein Testergebnis erhalten, das dem Ergebnis des echten Strategietesters ähnlich ist. Allerdings, dies ist nur eine Idee zum Erstellen eines Testers für Hedge Expert Advisors. Ich werde nicht garantieren, dass er genau das gleiche sein wird wie ein echter Tester. Aber ich hoffe, dass eine gute Referenz für die künftige Nutzung sein wird.Fangen wir an.



Die einfache Bedeutung von Hedge Trading

Bevor wir anfangen, sprechen wir über "HEDGE".

Der einfache Weg, etwas über Hedging (Absicherung) zu sagen wäre, dass zwei gegenläufige Trades zur gleichen Zeit geöffnet werden. Die passiert um das Handelsrisiko zu senken, wenn einer steigt, wird einer sicher fallen. Aber es gibt nichts zu befürchten, denn wenn wir Buy und Sell Ordern zur gleichen Zeit haben, dann selbst wenn wir eine verlieren, ist eine rentabel, deshalb wird es "Low Risk" genannt. Es gibt viele Arten von gegenläufigen Trading-Stilen in der Forex-Welt.

Im Hedge-Trading gibt es einige Fakten, die nicht angezweifelt werden können.

  1. Die Korrelation : Sie ist das statistische Maß der Beziehung zwischen zwei Währungen. Der Korrelation Koeffizient liegt zwischen -1 und +1. Eine Korrelation von +1 bedeutet, dass sich die beiden Währungspaare in 100% der Zeit in die gleiche Richtung bewegen. Eine Korrelation von -1 bedeutet, dass die zwei Währungspaare sich in 100% der Zeit in entgegengesetzte Richtungen bewegen. Eine Korrelation von Null bedeutet, dass die Beziehung zwischen den Währungspaaren komplett zufällig ist (lesen Sie hier mehr).
  2. Das Lot-Größen-Verhältnis: Um 2 Währungspaare zu handeln, die sich weder auf die gleiche Weise, noch auf die entgegengesetzte Weise bewegen, ist das Lot-Verhältnis sehr wichtig, weil die ihnen eigene Volatilität und Bewegungsfähigkeit so unterschiedlich sind, wie bei Schildkröte und Hase. Wenn eines die Schlidkröte ist, ist das andere der Hase. Das Lot-Verhältnis kann das Risiko senken, beeinflusst durch das sich stärker bewegende Paar, oder Hasen-Paar, durch platzieren einer höheren Lot-Größe für das Schildkröten-Paar, um einen geringeren Verlust zu garantieren, wenn sich Hasen-Paar in einer negativen Bewegung befindet. In dem Fall gewinnen Sie mehr von dem der positiven Schildkröte, oder mit anderen Worten, Sie ersetzen den negativen Profit des verlierenden Hasen, durch den Gewinn der Schildkröte. Und so kann die Hedging-Technik sicherstellen, dass Sie nichtmehr verlieren, als wenn Sie nur einen Trade auf der negativen Seite öffnen.

Übrigens, haben Sie sich jemals gefragt, wie ein Hedger aus seinem Handelsstil Gewinne erzielt? Keine Sorge, es wird immer eine Überschneidung zwischen den zwei Währungspaaren geben, die Korrelation ist keine konstante Regel in der Natur, es wird häufig eine Verzögerung bei einem Paar geben, eins beginnt die Bewegung, dann wird eins hinterher folgen, noch einmal: wie Hase und Schlidkröte - ein Hase wird eine Pause machen, auf die Schildkröte warten, um sie zu schlagen und zu gewinnen. Deshalb erzielen Hedger einen schönen Gewinn von ihnen. Und heutzutage verwenden viele Menschen den Hedging-Stil um Geld in Forex zu verdienen, nichts um sich Sorgen zu machen. Hedge, warten, schließen wenn ein positives Ergebnis ausgewiesen wird. Das ist alles.



Das Hedge Konzept

Bevor wir anfangen den virtuellen Tester zu codieren, versuchen wir das Hedging-Konzept in einem Experiment zu verstehen. Ohne das Hedging-Konzept werden wir nie verstehen, welche Art von Daten exportiert, aufgezeichnet und berechnet werden muss. Diese Daten können uns zeigen, welche Art der Order virtuell erzeugt werden muss. In diesem Experiment klge ich die Hedging-Regeln wie folgt fest.

Nach diesen Regeln benötigen die virtuellen Ordern tägliche Eröffnungskurse (beider Paare) zur Verwendung als Order-Eröffnungskurs. Um dem Intraday-Gewinn zu berechnen, muss der Kurs in jeder Stunde, als Tick-Kurs, jeden Tag aufgezeichnet werden, als die Daten für den Order-Schlusskurs (Ask für Sell und Bid für Buy)und aufgezeichnet werden zusammen mit der Tick-Zeit (um sicherzustellen, dass der Tick von dem gleichen Zeit-Wert ist). Und durch das Konzept den Hedge täglich zu öffnen, werde ich alle benötigten Daten in 2 Datei-Arten trennen, und zwar Daily-Open und Tick-Value für beide Paare. Beide Dateitypen werden exportiert als eine String Datei(s) mit eigenem Namen, wie GBPJPY1.csv und GBPJPYTick.csv

Und weil wegen der gewünschten Tick-Daten der virtuelle Tester so ähnlich wie möglich zu dem realen sein soll, muss mit diesen 2 Schritten fortgefahren werden.

Und beide Schritte müssen auch mit EURJPY durchgeführt werden.

Aber ich denke, wir können sie in einem Expert Advisor kombinieren. Dieser EA muss zwei Datentypen in 2 getrennte Dateien exportieren. Dann, nachdem dieser EA den Vorgang der Datenaufzeichnung abgeschlossen hat, wird ein neuer EA zum Erzeugen des virtuellen Trading die Daten der Paare GBPJPY und EURJPY aus allen exportierten Dateien erhalten, um die virtuelle Test-Show vorzuführen.



Die 3 Schritte um die Test-Beschränkung zu durchbrechen


Bei der obigen Idee bin ich zu dem Schluss gekommen, dass unser Traum diese Grenzen zu durchbrechen mit den folgenden drei Schritten umgesetzt werden kann.

  1. Nehmen Sie mit einem EA die Kursdaten und geben Sie diese an einige Dateien aus.
  2. Erzeugen Sie virtuelles Trading mit einem weiteren separaten EA, der auch die Ergebnisse als Datei exportiert.
  3. Bewerten Sie die Ergebnisse als Indikator in einem separaten Fenster.

Also, fangen wir mit dem ersten Schritt an.



Schritt 1: Export der Kursdaten

Im Folgenden ist ein Expert Advisor zum Export der täglichen Eröffnungskurse des angehangenen Symbols in eine Datei, benannt "GBPJPYD1.csv" für GBPJPY und "EURJPYD1.csv" für EURJPY, in der Zwischenzeit wird er auch den Tick-Kurs in eine Datei exportieren, benannt wie "symbolT.csv" (das gleiche wie die D1 Datei). Bitte lesen Sie die Kommentare, um zu erfahren wie der EA funktioniert.

Anmerkung: Alle von diesem EA erzeugten Dateien werden exportiert in das Verzeichnis "MetaTrader 4/tester/files".

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

Schritt 2: Erzeugen des Virtuellen Trading

Dieser Schritt ist der spannendste Schritt. Der Schritt den EA überprüfbar durch den Strategietester zu machen. Sehen Sie sich das Skript unten an, um zu wissen wie es aussieht. Und vergessen Sie nicht die Kommentare zu lesen, um zu wissen, wie es funktioniert. Und wie bei dem ersten EA, wird die Ergebnis-Datei exportiert in das "MetaTrader 4/tester/files" Verzeichnis.

//|                                                 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---------------------------------------------//



Schritt 3: Bewerten des Resultats

Nachdem die virtuellen Ordern ausgeführt und die Hedging-Ergebnisse aufgezeichnet wurden, können wir deren Daten nehmen, um unser Absicherungskonzept vorzuführen. Um das z machen, habe ich entschieden alle aufgezeichneten Daten wie einen Indikator zu exportieren, um die Performance-Kurve in einem separaten Fenster zu zeichnen, wie in vielen Indikatoren wie CCI, RSI oder ATR, usw. Und alle Dateien von dem zweiten EA sollten in das Verzeichnis "MetaTrader 4/experts/files" kopiert werden.

Um diese Kurve abzuschließen, wird der folgende Indikator benötigt.

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



Wie man sie verwendet

Bevor Sie die Kopie von meinem Code herunterladen, machen wir eine kurze Anleitung, "wie man sie verwendet", als Mini-Handbuch.

Um unsere Erwartungen wahr werden zu lassen, gibt es 5 einfache Schritte, die nicht ignoriert werden können. Diese sind:

  1. In dem Tester (keine Notwendigkeit den visuellen Modus zu nehmen), wählen Sie das symbol-D1.mq4 in dem "Expert Advisor:" Menü, und in dem "Symbol:" wählen Sie das erste Hedge Symbol von unserem favorisierten Hedging-Paar, stellen Sie die Datum-Zeit Periode ein und den "For_OP_SELL" Wert auf true, wenn das Symbol für eine Sell-Order ist, oder auf false, wenn dieses Symbol für eine Buy-Order ist, wählen Sie den stündlichen Zeitrahmen für die" Periode:" Menü, klicken Sie "Start" um den Aufzeichnungsprozess zu starten.
  2. Machen Sie das gleiche wie in Schritt 1, aber für das zweite Hedge-Symbol, ***VERGESSEN SIE NICHT DEN "For_OP_SELL" PARAMETER ZU ÄNDERN*** um den Order-Typ dieses Symbols anzupassen.
  3. Wählen Sie VirtualHedge.mq4, setzen Sie alle Variablen und wählen Sie das Test-Symbol (jedes Symbol, das Sie möchten). Aber hier wird der visuelle Modus benötigt um die Hedge-Performance zu sehen.
  4. Kopieren Sie alle verwandten Dateien, zur Anzeige der Hedge-Performance von "program files/metatrader 4/tester/files" in das "program files/metatrader 4/experts/files" Verzeichnis (vllt. einschließlich GBPJPY_EURJPY_result1.csv und p.csv, wenn dort mehr als ein Ergebnis ist, müssen Sie alle kopieren.)
  5. Hängen performance.mq4 an jedes aktuell aktive Chart, um echt wirkende Hedge-Performance zu sehen.

Und dies ist die Performance-Kurve meiner experimentellen Regeln.

Oops! Das ist hässlich, aber ich denke, Ihrer wird besser sein.



Fazit

Ich bin froh, dass wir nun in die neue Welt des Hedge EA Tests hinaustreten. Das Limit des Testers ist für Hedger kein Problem mehr. Übrigens, nebenbei bemerkt, das Konzept des Hedging in diesem Artikel ist nur ein Beispiel, und erzeugt um die Testdauer zu verkürzen. Um den virtuellen Tester mit Ihrer Hedging-Strategie arbeiten zu lassen, müssen Sie Ihre wesentlichen Daten auflisten, wie Eröffnung und Schluss von jedem Tag, Hoch, Tief und alle anderen Arten. Und wenn Sie mit der Korrelation handeln, müssen alle Korrelationswerte von jedem bestimmten Zeitpunkt ebenfalls exportiert werden. Durch diese Liste werden Sie wissen, welche Daten aufgezeichnet werden müssen, welche Daten berechnet werden müssen und welche Daten als Ergebnis ausgegeben werden. Und zum Verkürzen der Daten-Verarbeitungszeit, empfehle ich den Testzeitraum in kleine Abschnitte zu unterteilen - es ist besser als alle auf einmal zu verarbeiten. Zum Beispiel, wenn Sie einen EA über einen Zeitraum von 1 Jahr testen wollen, wäre das Aufteilen des Tests in 4 Abschnitte von jeweils drei Monaten besser. Ich hoffe, dass Ihre Performance-Kurve aussieht wie eine sexy Frau in Rot und dieser Artikel Ihnen hilft - Hedger, zumindest ein Teil von ihm, oder er inspiriert Sie wenigstens zu einem herrlichen Heging-Ergebnis. Schließlich hoffe ich, sie mögen ihn.