/* Source of info - http://articles.mql4.com/616 v005: 24Jan2013 - Translated most of the Spanish comments - Removed TP setting for Strategy tester - Included option to enable Spread correction when moving SL into BE - Released to ForexFactory Millipede forum thread v004: 29Nov2012 - Corrections in Partial close and order modify routines - Added option to ignoring trades with a Magic Number because they have TP or should no be partially closed v002 EA mayordomo - Adds SL when trade does not have it - Sets the SL to BE after some pips in the green side - Does partial close when some pips in the green side v001: - Auto correction for broker digits - Does partial close as percentage of trade size. To avoid errors please ensure initial trade size is big enough for the MT4 server to accept the new partial size - Partial close will happen once per trade. Resulting trades with reduced size should not be partially closed. - Does set SL to break even after some pips in green - Adds SL when the trade has no */ #property copyright "#copyright#" #property link "#link#" #include // User Variables extern string info01="----- EA Settings-----"; extern string info02="EA corrects for digits, pips without piplets"; extern int Skip.Magic= 990099; // Ignoring trades with this Magic extern bool SpreadtoBE= True; // Spread is added to the SL when moving into BE extern double _SLpips= 23; // StopLoss extern int _Slippage= 5; // Slippage extern int _BEpips= 15; // Number of green pips to move SL to BE //extern bool _BEplus= FALSE; // TRUE, adds to BE the amount due to Swap y Commission extern int _PCpips= 12; // Number of green pips triggering partial close extern double _PClose= 0.75; // Percentage of trade size to close // Globally used Variables double vPOINT,vBID,vASK; int MagicNumber=19750915, _PipValue=1; // Using different MagicNumber ID for this EA int vDIGITS; double Lotes,Slippage; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { Print("New run of EA -------------------<"); Print("LotStep=",DoubleToStr(MarketInfo(Symbol(), MODE_LOTSTEP),Digits), "; MinLot=",DoubleToStr(MarketInfo(Symbol(), MODE_MINLOT),Digits), "; POINT=",DoubleToStr(MarketInfo(Symbol(), MODE_POINT),Digits), "; DIGITS=",DoubleToStr(MarketInfo(Symbol(), MODE_DIGITS),Digits), "; LOTSIZE=",DoubleToStr(MarketInfo(Symbol(), MODE_LOTSIZE),Digits), "; STOPLEVEL=",DoubleToStr(MarketInfo(Symbol(), MODE_STOPLEVEL),Digits) ); // v004 Print("TickValue=",DoubleToStr(MarketInfo(Symbol(), MODE_TICKVALUE),Digits), "; TickSize=",DoubleToStr(MarketInfo(Symbol(), MODE_TICKSIZE),Digits), "; 1Lot_MarginReq=",DoubleToStr(MarketInfo(Symbol(), MODE_MARGINREQUIRED),Digits), "; Spread=",DoubleToStr(MarketInfo(Symbol(), MODE_SPREAD),Digits), "; FreezeLevel=",DoubleToStr(MarketInfo(Symbol(), MODE_FREEZELEVEL),Digits), "; SwapType=",DoubleToStr(MarketInfo(Symbol(), MODE_SWAPTYPE),Digits) ); // v004 // Corregimos el numero de decimales usados if (Digits == 3 || Digits == 5) _PipValue = 10; _BEpips=_BEpips*_PipValue; _SLpips=_SLpips*_PipValue; _PCpips=_PCpips*_PipValue; Slippage=_Slippage*_PipValue*Point; if (IsTesting() || IsOptimization()) { //TP = TP * _PipValue*Point; Slippage = 0; } //else TP = 0; return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- //---- return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { //v002: Rutina de Mayordomo. Mira en cada operadion abierta y determina si debe realizar alguna tarea int cnt=-1; // Contador de bucle. for(cnt=OrdersTotal()-1 ; cnt>=0; cnt--) { if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)) { vASK=MarketInfo(OrderSymbol(),MODE_ASK); vBID=MarketInfo(OrderSymbol(),MODE_BID); vPOINT=MarketInfo(OrderSymbol(),MODE_POINT); // smallest price change 0.0001 / 0.00001 / 0.001 / 0.01 vDIGITS = MarketInfo(OrderSymbol(),MODE_DIGITS); // Number of decimal positions //v004, I supose stoplevel is the minimum distance for placing a SL or TP int StopLevel = MarketInfo(OrderSymbol(), MODE_STOPLEVEL); // Some brokers set this as minimum distance from BID price if (SpreadtoBE == true) StopLevel =+ MarketInfo(OrderSymbol(), MODE_SPREAD); // Adding up the Spread to new SL if (_SLpips < StopLevel) _SLpips = StopLevel; // v004, from here ignores trades with magic 990099 that have a TP so we do want them to be partially closed if(OrderMagicNumber()== Skip.Magic) continue; //v001, preparing the prices to be use later using the Order's data double b.SL = NormalizeDouble(OrderOpenPrice() - _SLpips * vPOINT,vDIGITS); double s.SL = NormalizeDouble(OrderOpenPrice() + _SLpips * vPOINT,vDIGITS); double b.BE = NormalizeDouble(OrderOpenPrice() + _BEpips * vPOINT,vDIGITS); double s.BE = NormalizeDouble(OrderOpenPrice() - _BEpips * vPOINT,vDIGITS); double b.PC = NormalizeDouble(OrderOpenPrice() + _PCpips * vPOINT,vDIGITS); double s.PC = NormalizeDouble(OrderOpenPrice() - _PCpips * vPOINT,vDIGITS); double new.SL = 0; //v004, using stoplevel as minimum distance from current price for adding SL double use.stoplevel = NormalizeDouble(StopLevel * vPOINT,vDIGITS); //v002, adding SL when it is not present. This should work with ECN criminals if(OrderStopLoss()==0 && OrderType()==1 && (s.SL-vASK)> use.stoplevel) ModifyOrder(s.SL, Red, "adding SL "+OrderSymbol()+"@ "); if(OrderStopLoss()==0 && OrderType()==0 && (vBID-b.SL)> use.stoplevel) ModifyOrder(b.SL, Green, "adding SL "+OrderSymbol()+"@ "); switch(OrderType()) { case OP_BUY: // Bloque de BUY vBID=MarketInfo(OrderSymbol(),MODE_BID); // Moving SL to BE if(_BEpips>0 && vBID>b.BE && OrderStopLoss() < OrderOpenPrice()) { new.SL=OrderOpenPrice()+ vPOINT * MarketInfo(OrderSymbol(),MODE_SPREAD); ModifyOrder(new.SL, Green, "moving SL to BE "+OrderSymbol()+"@ "); } // Partial close when price is above minimum distance and comment does not contain the word "From" if(_PCpips>0 && vBID>b.PC && StringFind(OrderComment(),"from #",0)==-1) { ClosePartialOrder(vBID, CloseSize(_PClose,OrderLots()),Green, "partial closing "+OrderSymbol()+"@ "); } break; case OP_SELL: // Bloque de SELL vASK=MarketInfo(OrderSymbol(),MODE_ASK); // Moving SL to BE if(_BEpips>0 && vASK OrderOpenPrice()) { new.SL=OrderOpenPrice()- vPOINT * MarketInfo(OrderSymbol(),MODE_SPREAD); ModifyOrder(new.SL, Red, "moving SL to BE "+OrderSymbol()+"@ "); } // Partial close when price is above minimum distance and comment does not contain the word "From" if(_PCpips>0 && vASK execution continues out the loop break; } } } // Final bucle FOR return(0); } // Routine to modify orders void ModifyOrder( double precio, color colour, string texto) { int k=0; Print("Ticket: ",OrderTicket(), " => Attempt ",texto, DoubleToStr(precio,vDIGITS)); while (k==0) { if(IsTradeAllowed()) { if(OrderModify(OrderTicket(), OrderOpenPrice(), precio, OrderTakeProfit(), colour)) { Print("Ticket: ",OrderTicket(), " => SUCCESS ",texto,DoubleToStr(precio,vDIGITS)," ... OLE!"); break; } else Print("Ticket: ",OrderTicket(), " => When ",texto,DoubleToStr(precio,vDIGITS),", following ERROR was FOUND: ",ErrorDescription(GetLastError())); } Sleep(200); } return(0); } void ClosePartialOrder(double precio, double Lots, color colour, string texto) { int k=0; Print("Ticket: ",OrderTicket(), " => Attempt ",texto, DoubleToStr(precio,vDIGITS), " of ",Lots, " lots."); while (k==0) { if(IsTradeAllowed()) { if(OrderClose(OrderTicket(), Lots, precio, Slippage, colour)) { Print("Ticket: ",OrderTicket(), " => SUCESS ",texto,DoubleToStr(precio,vDIGITS), " of ",Lots, " lots ... OLE!"); break; } else Print("Ticket: ",OrderTicket(), " => When ",texto,DoubleToStr(precio,vDIGITS), " of ",Lots," lots, following ERROR was FOUND: ",ErrorDescription(GetLastError())); } Sleep(200); } return(0); } // Routine for calculating the lot size to close // Input: Lot Percentage and OrderLots // Source: http://forum.mql4.com/21205/page2 // v002 double CloseSize(double Percent, double Lots) { double lotstep, minlot, Z; int steps; if (Percent==1) return(Lots); //close all ! if (Percent==0) return(0); //close none ! lotstep = MarketInfo(OrderSymbol(), MODE_LOTSTEP); minlot = MarketInfo(OrderSymbol(), MODE_MINLOT); steps = MathRound(NormalizeDouble(Lots * Percent,2) / lotstep); if (steps<1) steps=1; //force the minimum size if (Lots <= minlot) return (Lots); //v004, forces to close the minimum lot size set by broker if (Lots - (steps * lotstep) >= minlot) //compare remainder to minlot return(steps * lotstep); //OK! else //not OK! return((steps * lotstep)-lotstep); //could be zero if steps=1 }