Romper o limite do verificador de estratégia em testes de cobertura do EA
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.
- 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).
- 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.
- Pegue os dados de preços e coloque-os como saída em alguns arquivos utilizando um EA.
- Gere o trading virtual com outro EA separado que também exporte o resultado como um arquivo.
- 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:
- 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.
- 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.
- 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.
- 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.)
- 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
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Você concorda com a política do site e com os termos de uso