//+-----------------------------------------------------------------------------------+ //| Bogie-HedgeHog-v4f.mq4 | //| | //| 2010.01.04 - Modified PlumCrazy code to trade ""HedgeHog"" Trade Rules | //| from www.ForexTradersDaily.com | //+-----------------------------------------------------------------------------------+ ///Please, do not sell this EA because its FREE #property copyright "Copyright © 2010, Bogie Enterprises" // Added by Robert for better error messages #include #include extern string INFO=" Bogie-HedgeHog-v4f "; extern int GMTOffSet = 2; extern int DaysOpen = 7; // EA will close all trades extern double StopLoss2 = 25; // when DaysOpen and StopLoss2 limits are exceeded. extern double step = 0.17; // Percent price change to execute trades. //Added by wackena, period selection for New Bar Start determination extern int BarPeriod = 0; // 0=NULL, 1=M1, 2=M5, 3=M15, 4=M30, 5=H1, 6=H4, 7=D1 extern double MATrendPeriod = 5; // Daily Moving Average averaging bars. extern double MA_Mode = 0; // Choose 0=mode SMA, 1=mode EMA, 2=mode SMMA, 3=mode LWMA"; extern double MA_Price = 0; // Choose Price- 0=Close, 1=Open, 2=High, 3=Low, 4=Medium Price, 5=Typical Price extern string sb="--TRADE SETTING--"; extern double Lots = 0.01; // We start with this lots number int TakeProfit; extern double multiply=2.0; // Factor to increase lot size from initial trade extern int MaxTrades=4; // Maximum number of orders to open extern int StopLoss = 175; // StopLoss extern int TrailingStop = 72; // Pips to trail the StopLoss extern string MM="--MOney Management--"; // (from order 2, not from first order extern string MMSwicth="if one the lots size will increase based on account size"; extern int mm=1; // if one the lots size will increase based on account size extern string riskset="risk to calculate the lots size (only if mm is enabled)"; extern int risk=10; // risk to calculate the lots size (only if mm is enabled) extern string accounttypes="0 if Normal Lots, 1 for mini lots, 2 for micro lots"; extern int AccountType=2; // 0 if Normal Lots, 1 for mini lots, 2 for micro lots extern bool BrokerIsIBFX = false; // Added by Robert to handle IBFX type lots extern bool BrokerPermitsFractionalLots = true; extern string magicnumber="--MAgic No--"; extern int MagicNumber=54321; // Magic number for the orders placed extern bool RecordData=False; // If true, records trade open time and MaxDD when using Strategy Tester // and stores file in ...tester/files folder. extern int BacktestSpread=3; // Adjusts Market Stops from fixed backtest spread to current Demo/Live spread color ArrowsColor=Black; // color for the orders arrows bool ContinueOpening=True; int OpenOrders=0, cnt=0; int MarketOpenOrders=0; int slippage=5; double sl=0, tp=0; double BuyPrice=0, SellPrice=0; double lotsi=0, mylotsi=0; int mode=0, myOrderType=0, myOrderTypetmp=0; double LastPrice=0; int PreviousOpenOrders=0; double Profit=0; int LastTicket=0, LastType=0; double LastClosePrice=0, LastLots=0; // Added by Robert double myPoint; double myMaxLots; // Added by Robert for proper money management double myMinLots; // Added by Robert for proper money management int LotDigits; // Added by Robert to fix lot digits problem double myLotStep; // Added by David int err; int slgap=0; int t; double PreviousClose; int nBars; double PreSellPrice, PreBuyPrice; double MaCurrent, MaPrevious; string Broker=""; int BarPer; bool result; string text=""; string version="Bogie-HedgeHog-v4f"; double NewSL, NewTP, BrokerSL, BrokerTP; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- myPoint = SetPoint(); // Added by Robert myMaxLots = MarketInfo(Symbol(), MODE_MAXLOT); // Added by Robert myMinLots = MarketInfo(Symbol(), MODE_MINLOT); // Added by Robert myLotStep = MarketInfo(Symbol(), MODE_LOTSTEP); // Added by David if(myMinLots==1) { LotDigits = 0; } if(myMinLots==0.1) { LotDigits = 1; } if(myMinLots==0.01) { LotDigits = 2; } //Added by wackena, used to select periood for iBars(). switch (BarPeriod) { case 1: BarPer=1; break; case 2: BarPer=5; break; case 3: BarPer=15; break; case 4: BarPer=30; break; case 5: BarPer=60; break; case 6: BarPer=240; break; case 7: BarPer=1440; break; default: BarPer=0; break; } nBars=iBars(NULL,BarPer); // Modified by Robert to save time on backtest if(_OrdersTotal()<1) { PreviousClose = iClose(NULL,PERIOD_H1,(Hour()+1)+(2-GMTOffSet)); GlobalVariableSet("PreviousClose"+Symbol()+MagicNumber,PreviousClose); } else { if (!IsTesting()) PreviousClose = GlobalVariableGet("PreviousClose"+Symbol()+MagicNumber); } GlobalVariableSet("MagicNumber"+Symbol()+MagicNumber,MagicNumber); GlobalVariableSet("Step"+Symbol()+MagicNumber,step); Broker = AccountCompany(); //---- return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { //---- DeleteAllObjects(); //---- return(0); } //+------------------------------------------------------------------+ //| Get number of lots for this trade | //| Moved from start and code added to handle IBFX type lots | //+------------------------------------------------------------------+ double GetLots() { double lot; if(mm == 0) { lot = Lots; if (Lots < myMinLots) lot = myMinLots; if (Lots > myMaxLots) lot = myMaxLots; return(lot); } if (AccountType==0) { lot=MathCeil(AccountBalance()*risk/10000); } if (AccountType==1) { // then is mini lot=MathCeil(AccountBalance()*risk/10000)/10; } if (AccountType==2) { lot=MathCeil(AccountBalance()*risk/10000)/100; } // lot=NormalizeDouble(MathCeil((AccountBalance()*risk/10000))/10,2); if (BrokerIsIBFX == true) { // Use at least 1 micro lot if (AccountType==2) { lot = lot * 10; lot = MathFloor(lot*100)/100; if (lot < 0.1) lot = 0.1; if (lot > myMaxLots) lot = myMaxLots; return(lot); } // Use at least 1 mini lot if(AccountType==1) { lot = lot * 10; lot = MathFloor(lot*10)/10; if (lot < 1) lot = 1; if (lot > myMaxLots) lot = myMaxLots; return(lot); } // Standard Account if(BrokerPermitsFractionalLots == true) lot = StrToDouble(DoubleToStr(lot, 2)); else lot = MathFloor(lot); if (lot < myMinLots) lot = myMinLots; if (lot > myMaxLots) lot = myMaxLots; return(lot); } // Use at least 1 micro lot if (AccountType==2) { lot = MathFloor(lot*100)/100; if (lot < 0.01) lot = 0.01; if (lot > myMaxLots) lot = myMaxLots; return(lot); } // Use at least 1 mini lot if(AccountType==1) { lot = MathFloor(lot*10)/10; if (lot < 0.1) lot = 0.1; if (lot > myMaxLots) lot = myMaxLots; return(lot); } // Standard account if( BrokerPermitsFractionalLots == false) { if (lot >= 1.0) lot = MathFloor(lot); else lot = 1.0; } if (lot < 1.0) lot = 1.0; if (lot > myMaxLots) lot = myMaxLots; return(lot); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { // Moved by wackena, moved Chart Comments to before Bar End check. // ==================== COMMENT LINE =========================================== if (myOrderType==3 ) { text="No Signal"; } if (myOrderType==1 ) { text="SELL Signal"; } if (myOrderType==2 ) { text="BUY Signal"; } // Modified by Robert to save time on backtest if (IsVisualMode() || !IsTesting()) { Comment(Broker," - Server Time = ",TimeToStr(TimeCurrent(),TIME_SECONDS),"\nTrade Signal = ",text, "\nMA Previous = ",MaPrevious," MA Current = ",MaCurrent, "\nMaxLots : " + DoubleToStr(myMaxLots,2) + " MinLots : " + DoubleToStr(myMinLots,2)); } if(!IsBarEnd()) { return(0); } CloseTrades(); //---- lotsi = GetLots(); // Modified by Robert to handle IBFX type lots OpenOrders=0; MarketOpenOrders=0; for(cnt=0;cntOpenOrders) { for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { if (OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES)) { mode=OrderType(); if ((OrderSymbol()==Symbol() && OrderMagicNumber() == MagicNumber) ) { if (mode==OP_BUY || mode==OP_SELL) { double ClosePrice=NormalizeDouble(OrderClosePrice(),Digits); OrderClose(OrderTicket(),OrderLots(),ClosePrice,slippage,ArrowsColor); return(0); } } } } } PreviousOpenOrders=OpenOrders; if (OpenOrders>=MaxTrades) { ContinueOpening=False; } else { ContinueOpening=True; } if (LastPrice==0) { for(cnt=0;cnt=0) { if(OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES)==false) break; if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber) // && Reversed==False) { //Print("Ticket ",OrderTicket()," modified."); if (OrderType()==OP_SELL) { if (myOrderTypetmp==2) { PreviousOpenOrders=OpenOrders+1; ContinueOpening=False; text = text +"\nClosing all orders because Indicator triggered another signal."; Print("Closing all orders because Indicator triggered another signal."); //return(0); } if (TrailingStop>0) { if ((OrderOpenPrice()-OrderClosePrice())>=(TrailingStop*myPoint)) { if (OrderStopLoss()>(OrderClosePrice()+TrailingStop*myPoint)) { // Robert added code to prevent error 1 - No Result NewSL = NormalizeDouble(OrderClosePrice()+TrailingStop*myPoint, Digits); NewTP = NormalizeDouble(OrderClosePrice()-TakeProfit*myPoint-TrailingStop*myPoint, Digits); BrokerSL = NormalizeDouble(OrderStopLoss(), Digits); BrokerTP = NormalizeDouble(OrderTakeProfit(), Digits); if (NewSL != BrokerSL || NewTP != BrokerTP) { result=OrderModify(OrderTicket(),OrderOpenPrice(),NewSL,NewTP,0,Purple); if(result!=TRUE) { // Added by Robert, I like a description err = GetLastError(); Print("LastError (", err, ")", ErrorDescription(err) ); } else OrderPrint(); } return(0); } } } } if (OrderType()==OP_BUY) { if (myOrderTypetmp==1) { PreviousOpenOrders=OpenOrders+1; ContinueOpening=False; text = text +"\nClosing all orders because Indicator triggered another signal."; Print("Closing all orders because Indicator triggered another signal."); //return(0); } if (TrailingStop>0) { if ((OrderClosePrice()-OrderOpenPrice())>=(TrailingStop*myPoint)) { if (OrderStopLoss()<(OrderClosePrice()-TrailingStop*myPoint)) { // Robert added code to prevent error 1 - No Result NewSL = NormalizeDouble(OrderClosePrice()-TrailingStop*myPoint, Digits); NewTP = NormalizeDouble(OrderClosePrice()+TakeProfit*myPoint+TrailingStop*myPoint, Digits); BrokerSL = NormalizeDouble(OrderStopLoss(), Digits); BrokerTP = NormalizeDouble(OrderTakeProfit(), Digits); if (NewSL != BrokerSL || NewTP != BrokerTP) { result=OrderModify(OrderTicket(),OrderOpenPrice(),NewSL,NewTP,0,ArrowsColor); if(result!=TRUE) { // Added by Robert, I like a description err = GetLastError(); Print("LastError (", err, ")", ErrorDescription(err) ); } else OrderPrint(); } return(0); } } } } } cnt--; } if(IsTesting() && RecordData) { if(OpenOrders==0 && t==1) { int handle; int orderOpen=OrderOpenTime(); int orderClose=TimeCurrent(); int TimeOpen=TimeCurrent()-OrderOpenTime(); handle=FileOpen("Bogie-HedgeHog-v4a data", FILE_CSV|FILE_READ|FILE_WRITE, ','); if(handle>0) { FileSeek(handle,0,SEEK_END); FileWrite(handle,TimeToStr(orderOpen),TimeToStr(orderClose),TimeOpen,slgap); FileClose(handle); } slgap=0; t=0; } if( SellGap() < slgap && OpenOrders==MaxTrades) { slgap=SellGap(); t=1; } } if (OpenOrders<1) OpenMarketOrders(); else OpenMarketOrders(); //---- return(0); } //+------------------------------------------------------------------+ void OpenMarketOrders() { // --------------------------------- // Added by Robert for Market Orders bool result; int ticket,ticket2, err,spread; double TPprice,STprice, tp, sl; // --------------------------------- int cnt=0; if (myOrderType==1 && ContinueOpening) { if (Bid>=LastPrice * (1 + (step/100)) || (OpenOrders<1 )) { SellPrice=NormalizeDouble(MarketInfo(Symbol(),MODE_BID),Digits); spread=MarketInfo(Symbol(),MODE_SPREAD); LastPrice=0; if (OpenOrders!=0) { mylotsi=lotsi; for(cnt=0;cnt12) { mylotsi=NormalizeDouble(mylotsi*multiply,2); } // else { mylotsi=NormalizeDouble(mylotsi*multiply,2); } if (MaxTrades>12) { mylotsi=NormalizeDouble(mylotsi*multiply,LotDigits); } else { mylotsi=NormalizeDouble(mylotsi*multiply,LotDigits); } } } else { mylotsi=lotsi; } // Robert modified to fix lots issue // mylotsi = NormalizeDouble(mylotsi*Bid,Digits); // Wackena commeted out, so EA will run on Minimum Lot Size = 0.1 // mylotsi = NormalizeDouble(mylotsi*Bid,2); mylotsi = NormalizeDouble(mylotsi*Bid,LotDigits); // Fixed by Robert // Modified by Robert to handle brokers who do not allow .01 or 100 lots // if (mylotsi>100) { mylotsi=100; } // if (mylotsi<0.01) { mylotsi=0.01; } mylotsi = MathCeil(mylotsi / myLotStep) * myLotStep; // Added by David if (mylotsi < myMinLots) mylotsi = myMinLots; if (mylotsi > myMaxLots) mylotsi = myMaxLots; ticket = OrderSend(Symbol(),OP_SELL,mylotsi,SellPrice,slippage,0,0,version,MagicNumber,0,Red); // --------------------------------- // Added by Robert for Market Orders if (ticket > 0) { if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) { Print("Sell order opened : ", OrderOpenPrice()); GlobalVariableSet("OrderType"+Symbol()+MagicNumber,2); if (StopLoss != 0 || TakeProfit != 0) { TPprice = 0; if (TakeProfit > 0) { if(OpenOrders<1) { TPprice = PreviousClose + (spread*myPoint - BacktestSpread*myPoint); PreSellPrice=SellPrice; } else {TPprice=PreSellPrice; PreSellPrice=SellPrice;} } STprice = 0; if (StopLoss > 0 && OpenOrders==MaxTrades-1) { STprice=OrderOpenPrice() + StopLoss*myPoint; STprice = ValidStopLoss(OP_SELL,Ask, STprice); } // Normalize stoploss / takeprofit to the proper # of digits. // Modified by wackena, cannot have variable = same variable in start() if (Digits > 0 ) { sl = NormalizeDouble( STprice, Digits); tp = NormalizeDouble( TPprice, Digits); } // Added by wackena, only modifred order when if(sl != OrderStopLoss() || tp != OrderTakeProfit()) { result = OrderModify(ticket, OrderOpenPrice(), sl, tp, 0, LightGreen); // Robert moved bracket to prevent error 0 message when OrderModify is not called // } if(result!=TRUE) { // Added by Robert, I like a description err = GetLastError(); Print("Modify error (", err, ")", ErrorDescription(err) ); } } // New bracket by Robert } } } else { err = GetLastError(); if(err==0) { return; } else { if(err==4 || err==137 ||err==146 || err==136) //Busy errors { Sleep(5000); } else //normal error { Print("Error opening Sell order (" + err + ") " + ErrorDescription(err)); } } } // --------------------------------- return(0); } // Sleep(6000); ////aku letak // RefreshRates(); } if (myOrderType==2 && ContinueOpening) { if (Ask<=LastPrice * (1 - (step/100)) || (OpenOrders<1 )) { BuyPrice=NormalizeDouble(MarketInfo(Symbol(),MODE_ASK),Digits); LastPrice=0; if (OpenOrders!=0) { mylotsi=lotsi; for(cnt=0;cnt12) { mylotsi=NormalizeDouble(mylotsi*multiply,2); } // else { mylotsi=NormalizeDouble(mylotsi*multiply,2); } if (MaxTrades>12) { mylotsi=NormalizeDouble(mylotsi*multiply,LotDigits); } else { mylotsi=NormalizeDouble(mylotsi*multiply,LotDigits); } } } else { mylotsi=lotsi; } // Robert modified to fix lots issue // mylotsi = NormalizeDouble(mylotsi*Ask,Digits); // Wackena commeted out, so EA will run on Minimum Lot Size = 0.1 // mylotsi = NormalizeDouble(mylotsi*Ask,2); mylotsi = NormalizeDouble(mylotsi*Ask,LotDigits); // Fixed by Robert // Modified by Robert to handle brokers who do not allow .01 or 100 lots // if (mylotsi>100) { mylotsi=100; } // if (mylotsi<0.01) { mylotsi=0.01; } mylotsi = MathCeil(mylotsi / myLotStep) * myLotStep; // Added by David if (mylotsi < myMinLots) mylotsi = myMinLots; if (mylotsi > myMaxLots) mylotsi = myMaxLots; ticket = OrderSend(Symbol(),OP_BUY,mylotsi,BuyPrice,slippage,0,0,version,MagicNumber,0,Blue); // --------------------------------- // Added by Robert for Market Orders if (ticket > 0) { if (OrderSelect( ticket,SELECT_BY_TICKET, MODE_TRADES) ) { Print("BUY order opened : ", OrderOpenPrice( )); GlobalVariableSet("OrderType"+Symbol()+MagicNumber,1); if (StopLoss != 0 || TakeProfit != 0) { TPprice = 0; if (TakeProfit > 0) { if(OpenOrders<1) { TPprice = PreviousClose-(spread*myPoint - BacktestSpread*myPoint); PreBuyPrice=BuyPrice; } else {TPprice=PreBuyPrice; PreBuyPrice=BuyPrice;} } STprice = 0; if(sl != OrderStopLoss() || tp != OrderTakeProfit()) { STprice = OrderOpenPrice() - StopLoss*myPoint; STprice = ValidStopLoss(OP_BUY,Bid, STprice); } // Normalize stoploss / takeprofit to the proper # of digits. // Modified by wackena, cannot have variable = same variable in start() if (Digits > 0) { sl = NormalizeDouble( STprice, Digits); tp = NormalizeDouble( TPprice, Digits); } // Added by wackena, only modifred order when if(sl != OrderStopLoss() || tp != OrderTakeProfit()) { result = OrderModify(ticket, OrderOpenPrice(), sl, tp, 0, LightGreen); // Robert moved bracket to prevent error 0 message when OrderModify is not called // } if(result!=TRUE) { // Added by Robert, I like a description err = GetLastError(); Print("Modify error (", err, ")", ErrorDescription(err) ); } } // New bracket by Robert } } } else { err = GetLastError(); if(err==0) { return; } else { if(err==4 || err==137 ||err==146 || err==136) //Busy errors { Sleep(5000); } else //normal error { Print("Error opening BUY order (" + err + ") " + ErrorDescription(err)); } } } // --------------------------------- return(0); } } } void DeleteAllObjects() { int obj_total=ObjectsTotal(); string name; for(int i=0;i= PreviousClose *(1 + (step/100))) { // Moved here by Robert to save time on backtest MaCurrent=iMA(NULL,PERIOD_D1,MATrendPeriod,0,MA_Mode,MA_Price,1); MaPrevious=iMA(NULL,PERIOD_D1,MATrendPeriod,0,MA_Mode,MA_Price,2); if (MaCurrent < MaPrevious) myOrderType=1; } //buy order if (Ask <= PreviousClose *(1 - (step/100))) { // Moved here by Robert to save time on backtest MaCurrent=iMA(NULL,PERIOD_D1,MATrendPeriod,0,MA_Mode,MA_Price,1); MaPrevious=iMA(NULL,PERIOD_D1,MATrendPeriod,0,MA_Mode,MA_Price,2); if (MaCurrent > MaPrevious) myOrderType=2; } return(myOrderType); } // Functions added by Robert double SetPoint() { double mPoint; if (Digits < 4) mPoint = 0.01; else mPoint = 0.0001; return(mPoint); } double ValidStopLoss(int type, double price, double SL) { double minstop; double newSL; minstop = MarketInfo(Symbol(),MODE_STOPLEVEL); if (Digits == 3 || Digits == 5) minstop = minstop / 10; newSL = SL; if (type == OP_BUY) { if((price - SL) < minstop*myPoint) newSL = price - minstop*myPoint; } if (type == OP_SELL) { if((SL-price) < minstop*myPoint) newSL = price + minstop*myPoint; } newSL = NormalizeDouble(newSL,Digits); return(newSL); } int SellGap() { double value=0; for (int i=0; i= PreviousClose || (TimeCurrent()-OrderOpenTime()>(86400*DaysOpen) && OrderOpenPrice()-Close[0]>StopLoss2*myPoint)) { PreviousOpenOrders=OpenOrders+1; } } if(OrderType()==OP_SELL) { if(Ask <= PreviousClose || (TimeCurrent()-OrderOpenTime()>(86400*DaysOpen) && Close[0]-OrderOpenPrice()>StopLoss2*myPoint)) { PreviousOpenOrders=OpenOrders+1; } } } } return(0); } int _OrdersTotal() { int _total=0; for (int i=0; i