![Desarrollo del tester de estrategia limit para probar un AE hedge](https://c.mql5.com/i/articles/overlay.png)
Desarrollo del tester de estrategia limit para probar un AE hedge
Introducción
En este artículo se ofrecerá una idea para probar un AE hedge en el tester de estrategia. Como sabe, el tester de estrategia tiene su propio límite que le impide abrir cualquier orden de otro símbolo. Los usuarios que quisieran probar su propio Asesor experto hedge, sólo deben hacerlo en directo. ¿Limita esto sus capacidades? Seguro que cada hedge trader necesita probar su AE antes del trading real. Por lo que voy a explicar la idea de generar una estrategia virtual de prueba de comportamiento (como el tester) con la esperanza de que pueda ayudar a desarrollar el tester de estrategia límite mt4 y de que sea útil en un futuro.
El concepto de tester virtual
La idea de un tester virtual se me ocurrió mientras trabajaba con "Archivos" de función en mq4. Se me ocurrió coger algunos datos importantes de un archivo para configurar un esquema de trading virtual: "¿Puede ser la respuerta para la prueba de mi AE hedge?". Probémoslo.
Mi tester virtual no necesita ningún programa o software externo. Todo se puede hacer mediante los parámetros mq4. El concepto de este tester virtual es dejar que los parámetros indicados de apertura o cierre de órdenes hedge digan de recopilar los datos necesarios. Como precio de apertura y de cierre, hora de apertura y de cierre... y otros datos importantes. Tras la configuración de los datos necesarios, éstos se utilizarán para comprarlos con los últimos valores de tick de cualquier tipo compatible, como la apertura de precio y la última puja; o precio de apertura y último Ask. Estos valores pueden dirigir al método de cálculo de beneficios, que guiarán a la recolección de nuevos datos después de que hayan llegado a la condición de hedge de cierre.
Estos datos se exportarán a un archivo para utilizarlos en un futuro. Tras realizar la prueba y después de tener todos los tipos de datos recopilados en un(os) archivo(s), se podrá ver cómo "se ejecuta el AE hedge". Obteniendo estos datos de esos archivos y agrupándolos como un indicador de la curva de ejecución, se puede finalizar la prueba virtual del AE hedge.
Por este concepto, doy por hecho que se pueden obtener unos resultados de la prueba similares a los resultados del tester de estrategia real. Por cierto, esto es sólo una idea de creación de un tester para los Asesores expertos hedge. No puedo garantizar que los resultados sean exactamente iguales que los del tester real. Pero espero que sea una buena referencia para utilizarlo en un futuro.
Vamos a empezar.
El sencillo significado del hedge trading
Antes de empezar, hablemos un poco de "HEDGE" (esto es de mi propio blog ubicado aquí ).
La forma fácil de explicar el hedging es: habrir dos trades contrarios de dos pares de divisas al mismo tiempo. Esto se hace para disminuir el riesgo. Si uno sube, el otro seguramente bajará, pero no hay nada de lo que preocuparse porque hemos abierto las órdenes de comprar y vender al mismo tiempo, por lo que si se pierde una, está la otra; por eso se llama "de bajo riesgo". Hay muchos tipos de estilos de trade contrario en el mundo Forex.
- Para 2 pares de divisas que siempre se mueven en la misma dirección, como EURUSD y GBPUSD abrir buy-EURUSD y sell-GBPUSD al mismo tiempo es hedging.
- Para 2 pares de divisas que siempre se mueven en dirección contraria, como EURUSD y USDCHF, abrir buy-EURUSD y buy-USDCHF al mismo tiempo también es hedging.
- O incluso abrir tanto buy como sell EURUSD al mismo tiempo, también es hedging, pero a veces se le llama "arbitrar".
Hay algunos hechos en el hedge trading de los que no se puede dudar.
- La correlación: es la medida estadística de la relación entre dos divisas. El rango de coeficiente de correlación entre -1 y +1. Una correlación de +1 implica que los dos pares de divisas se moverán en la misma dirección el 100% de las veces. Una correlación de -1 implica que los dos pares de divisas se moverán en dirección opuesta el 100% de las veces. Una correlación de cero implica que la relación entre los pares de divisas es totalmente aleatoria (leer más). También se puede obtener el valor de la correlación en esta página web gratuita: mataf.com. También ofrecen muchos parámetros de trading interesantes.
- La proporción de tamaño del lote: Para hacer trading con dos pares de divisas que no se mueven ni en la misma dirección, ni en dirección opuesta, la proporción de tamaño es necesaria porque la volatilidad y la capacidad de movimiento son diferentes, como una tortuga y un conejo: si uno es la tortuga, el otro será el conejo. La proporción puede disminuir el riesgo, que se ve afectado por el par con más movimiento, o par conejo, colocando el lote más alto en el par tortuga, para garantizar menos pérdida, cuando el par conejo esté en un movimiento negativo. Por lo tanto, se puede ganar más con la tortuga positiva, o en otras palabras, se puede reemplazar ese beneficio negativo del conejo no rentable por la tortuga rentable. Y de este modo, la técnica de hedging puede asegurar que no se perderá más que la apertura de un sólo trade en el lado negativo.
Por cierto, ¿se ha preguntado alguna vez cómo un hedger sale ganando con este estilo de trading? No se preocupe, siempre hay dos pares de divisas que se solapan. La correlación no es un esquema constante, siempre habrá algún retraso en un par, uno empieza a moverse, luego el otro lo seguirá, como el conejo y la tortuga: un conejo descansará, y esperará a que la tortuga le alcance y gane. Por eso los hedgers consiguen bastante beneficio. Y hoy en día mucha gente utiliza el estilo hedging para ganar dinero en Forex, no hay nada de lo que preocuparse. Hedge, espera, cierra cuando se muestra el beneficio positivo. Eso es todo.
El concepto hedge
Antes de empezar a codificar el tester virtual, hay que comprender el concepto hedging con un experimento. Sin el concepto de hedging nunca se sabrá qué tipo de datos hay que exportar, grabar y calcular. Estos datos pueden mostrarnos el tipo de orden que se debe generar virtualmente. En este experimento configuraré las reglas de hedging así.
- Abrir el hedge diario al principio del día.
- Cerrarlo cuando llegue a 100 dólares (con los tamaños de lote 1 y 2)
- Recolectar todos los datos de precios de ticks por horas***
- Limpiarlos a diario cuando empiece un nuevo día, incluso si no llegaron al beneficio establecido.
- Comprar sólo 2 lotes de EURJPY y vender 1 lote de GBPJPY.
Según estar reglas, las órdenes virtuales necesitan precios de apertura diarios (en ambos pares) para usarlos como una orden de apertura de precio. Para calcular el beneficio diario, el precio a cada hora, como precio de tick, se debe grabar como los datos de la orden de cierre de precio (pedir vender y pujar por comprar) y se debe grabar junto a la hora del tick (para asegurar que el precio del tic es de la misma hora). Debido al concepto de abrir el hedge diariamente, separaré todos los datos necesarios en dos tipos de archivo que se abren diariamente, y el valor de tick de ambos pares. Ambos tipos de datos se exportarán como archivosde serie con nombres separados, como GBPJPDY1.csv y GBPJPYTick.csv.
Y como quiere que los datos de tick del tester virtual sean lo más similar posible a los reales, hay que realizar estos dos pasos:
- Hacer un script para exportar las aperturas de precio diarias de GBPJPY en un archivo.
- Hacer un script para exportar el precio diario de los ticks de GBPJPY en un archivo.
Y ambos pasos deben hacerse también para EURJPY.
Pero creo que se pueden combinar en un asesor experto, que debería exportar ambos tipos de datos en dos archivos separados. Luego, una vez terminado que este AE finalice el proceso de grabación de datos, un nuevo AE para generar trading virtual, obtendrá los datos de BGPJPY u EURJPY de todos los archivos exportados para ejecutar la prueba virtual.
Tres pasos para eliminar el límite de la prueba
Por la idea anterior, deduje que el sueño de eliminar este límite podría realizarse en tres pasos:
- Coger los datos de precios y sacarlos en algunos archivos utilizando un AE.
- Generar el trading virtual con otro AE diferente que exporte los resultados también como un archivo.
- Revisar los resultados como un indicador en una ventana a parte.
Empecemos con el primer paso:
Paso 1: Exportar los datos de precio
Below is the Expert Advisor to export the daily-open-price of attached symbol into a file, named "GBPJPYD1.csv" for GBPJPY and "EURJPYD1.csv" for EURJPY, in the mean time it will export the tick price into a file too, named like this "symbolT. csv" (the same as D1 file). Por favor, lea los comentarios para aprender cómo funciona el AE.
Nota: Todos los archivos que cree este AE, se exportarán al directorio "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); } //+------------------------------------------------------------------+
Paso 2: Generar el trading virtual
Este paso es el más emocionante. El de hacer el AE hedge estable a través del tester de estrategía. Mire el script de abajo para ver cómo es. Y no se olvide de leer los comentarios para comprender cómo funciona. Y como en el primer AE, el archivo resultante se exportará al directorio "MetaTrader 4/tester/files".
//| 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---------------------------------------------//
Paso 3: Revisar el resultado.
Después de que se ejecuten las órdenes virtuales y se hayan grabado los resultados de hedging, se pueden coger esos datos para mostrar el concepto de hedging. Para ello, dedicí exportar todos los datos grabados como un indicador, para agrupar la información que se realizará en la curva en una ventana a parte, como muchos indicadores (CCI, RSI, ATR, etc.). Y todos los archivos del segundo AE deberían copiarse en el directorio "MetaTrader 4/experts/files".
Para terminar la curva, se necesita el indicador de abajo.
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Cómo utilizarlos
Antes de descargar una copia de mi código, hay que detallar el "¿Cómo se usan?" como un pequeño manual de usuario.
Para que las espectativas se hagan realidad, hay cinco sencillos pasos que no se pueden ignorar. Son:
- En el tester (no es necesario el modo visual): seleccione symbol-D1.mq4 en el menú "Asesor experto", y en "Símbolo": seleccione el primer símbolo de hedge de su par favorito de hedging, establezca la fecha y la hora y el valor "For_OP_SELL" para verificar si este símbolo es para la orden de vender o desmentir que este símbolo esté configurado para la orden comprar; seleccione el periodo por horas en el menú "Periodo", haga clic en "Inicio" para empezar el proceso de grabación.
- Haga lo mismo que en el paso 1, pero para el segundo símbolo hedge, ***NO OLVIDE CAMBIAR EL PARÁMETRO "For_OP_SEL"*** para que el tipo de orden encaje en el símbolo.
- Seleccione VirtualHedge.mq4, configure las variables, y seleccione probar el símbolo (cualquier símbolo que quiera). Para esto sí es necesario que modo visual para ver el funcionamiento de hedge.
- Copie todos los archivos relacionados con la muestra del funcionamiento de hedge de "program files/metatrader 4/tester/files" a "program files/metatrader 4/experts/files". (puede incluir quizás GBPJPY_EURJPY_result1.csv y p.cvs si hay más de un archivo de resultados, tiene que copiarlos todos).
- Adjunte performance.mq4 en cualquier gráfico activo para ver el funcionamiento del hedge como el real.
Y esta es la curva de mis reglas experimentales.
¡Ups! Es fea. Pero creo que la suya será mejor.
Conclusión
Me alegra que estemos un paso más allá en el nuevo mundo de probar el EA hedge. El límite del tester ya no es problema del hedger. Pero, por cierto, el concepto de hedging en este artículo sólo es un ejemplo y está generado sólo para un proceso corto de prueba. Para que el tester virtual funcione con su estrategia hedging, tiene que anotar sus datos importantes, como apertura y cierre de cada día, alto, bajo, o cualquier tipo. Y si hace trading con la correlación, también tiene que exportar todos los valores de cada valor de correlación de cada hora específica. Con esta lista sabrá qué datos tiene que grabar, qué datos tiene que calcular y qué datos tiene que enviar como resultado. Y para acortar el tiempo de procesamiento de datos, recomiendo separar el periodo de prueba en partes pequeñas: es mejor que procesarlos todos al mismo tiempo. Por ejemplo, si quiere probar el AE durante 1 año, sería mejor separarlo en 4 partes de 3 meses. Espero que su curva de funcionamiento sea tan sexy como una mujer de rojo, y que este artículo les sirva, hedgers, aunque sólo sea una sección; o que, al menos, les inspire a crear maravillosos resultados de hedging. Espero que le guste. A continuación hay un vídeo de 2 minutos del funcionamiento de mi hedge. (del 19/03 2007 al 19/04/2007).
Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/1493
![Plantilla universal de Asesor experto](https://c.mql5.com/2/14/451_25.gif)
![Matemáticas de trading. Cómo evaluar los resultados de las transacciones comerciales](https://c.mql5.com/2/14/442_223.gif)
![Lenguaje MQL4 para principiantes. Los indicadores técnicos y las funciones integradas](https://c.mql5.com/2/15/466_27.gif)
![El tester en la terminal MetaTrader 4: Debería saberse](https://c.mql5.com/2/14/424_77.gif)
![MQL5 - Lenguaje de estrategias comerciales para el terminal de cliente MetaTrader 5](https://c.mql5.com/i/registerlandings/logo-2.png)
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso