//EA original from Grail_2.mq4 at http://articles.mql4.com/163 //total tailormade by finimej for used at FXCH broker, or AlmaForex #property copyright "Copyright © 2009, finimej" #property link "www.formulatrader.com" extern bool useATR_SL=true; extern double Percentage_ATR_SL = 8; //extern double Percentage_ATR_LOT = 300 ; extern bool UseHourTrade = false; extern int FromHourTrade = 6; extern int ToHourTrade = 18; extern int Slippage = 3; extern bool UseMoneyManagement = false; extern double DecreaseFactor = 5; extern int Risk = 10; extern double InitialLot=0.1; extern bool AccountIsMicro=false; extern int pipsaway = 5; extern int brokerworsefill=0.0001; extern int MA_dis_pips = 1; extern int SL = 180; extern int SLreal = 180; extern int MA_period = 6; extern int TP_pips = 2; extern bool TradeperBar=false; // int TP_Faked=5; extern double MyMaxLot=50; //==0, then use the system lots 1000, >0 then using this lots as max lot. extern bool UseTimeCut=true; extern int LimitTime_1 = 20; //if position hold more than than this minutes, cut! int BL_ticket; int SL_ticket; int HasBuyLimitOrder = 0; int HasSellLimitOrder = 0; int HasBuyOrder = 0; int HasSellOrder = 0; double stoploss; double stoplossReal; double LimitEntryDistance; double MAMinDist; double Mode_stop_level; double BL_openprice; double SL_openprice; double TakeProfit; double TakeProfitFaked; double MA; double Spread; double LotSize; bool BuyLimitOrderEntered=false; double BuyLiMitOpenprice=0.0; bool SellLimitOrderEntered=true; double SellLiMitOpenprice=0.0; double TakeProfitsFaked; string Expert_Name="grail2"; int MagicBase = 626898; int OrderAttemps=3; //avoid news Extern & Global variables extern bool Avoid_News = true; extern int MinsBeforeNews = 30; extern int MinsAfterNews = 30; int New_Bar, // 0/1 The fact of new bar forming Time_0, // The new bar beginning time ret, // Intersection direction total; // Count of open orders extern string hd = " --Delay time--"; extern int useDelay = 1; extern int MinutesToDelay = 5; datetime StopTime; // Time to wait after a trade is stopped out bool StoppedOut=false; extern int accoutlimit=1900; void init() { MagicBase = 3000 + func_Symbol2Val(Symbol())*100 + func_TimeFrame_Const2Val(Period()); Mode_stop_level = MarketInfo(Symbol(), MODE_STOPLEVEL); if (Mode_stop_level==0) Mode_stop_level=5; Mode_stop_level = (Mode_stop_level + 1.0) * Point; // this is the MODESTOPLEVEL setting stoploss = SL * Point; LimitEntryDistance = pipsaway * Point; MAMinDist = MA_dis_pips * Point; //TakeProfitFaked = TP_Faked * Point; TakeProfit=TP_pips*Point; Spread = Ask - Bid; stoplossReal=SLreal* Point; } int start() { if (AccountEquity()<accoutlimit) {ForceCloseAll(); return (0); } if (Avoid_News==true) { if (GetNews()==true) {ForceCloseAll(); return (0); } } if (useDelay == 1) { StoppedOut = LastTradeStoppedOut(); if (CurTime() < StopTime) { Comment("Last trade stopped out, No Trades Until : " + TimeToStr(StopTime,TIME_DATE|TIME_MINUTES)); return(0); } } if (UseHourTrade) { if (!(Hour() >= FromHourTrade && Hour() <= ToHourTrade)) { Comment("This is not trading time."); return (0); } } New_Bar=0; // First zeroize if (Time_0 != Time[0]) // If the bar beginning time changed { New_Bar= 1; // Here we have a new bar Time_0 = Time[0]; // Remember the new bar beginning time } ScreenComments(); HasBuyLimitOrder = false; HasSellLimitOrder = false; HasBuyOrder = false; HasSellOrder = false; if (useATR_SL==true) { if (stoploss<=1*Percentage_ATR_SL*iATR(NULL,15,14,0)) stoploss= 1*Percentage_ATR_SL*iATR(NULL,15,14,0); // Print("stoploss is "+DoubleToStr(stoploss,4)); } OpenLimitOrder(); if (BuyLimitOrderEntered==true) { BL_openprice = NormalizeDouble(BuyLiMitOpenprice, Digits); HasBuyLimitOrder = true; } if (SellLimitOrderEntered==true) { SL_openprice = NormalizeDouble(SellLiMitOpenprice, Digits); HasSellLimitOrder = true; } MA = iMA(NULL, 0, MA_period, 0, MODE_LWMA, PRICE_TYPICAL, 0); //SMA on close price of current bar on current time frame. Modify_order(); for (int k = OrdersTotal(); k >= 0; k--) { if (OrderSelect(k, SELECT_BY_POS) == true && OrderSymbol() == Symbol()&& (OrderMagicNumber() == MagicBase)) { if (OrderType() == OP_BUY) { HasBuyOrder = true; Close_B(OrderTicket(), OrderLots()); } if (OrderType() == OP_SELL) { HasSellOrder = true; Close_S(OrderTicket(), OrderLots()); } } } if( TradeperBar==true) { if (Avoid_News==true) { if (GetNews()!=true&&New_Bar==1&&AccountEquity()>accoutlimit) OpenMarketOrder();} if (Avoid_News==false) { if (New_Bar==1&&AccountEquity()>accoutlimit) OpenMarketOrder();} } else { if (Avoid_News==true) { if (GetNews()!=true&&AccountEquity()>accoutlimit) OpenMarketOrder();} if (Avoid_News==false) { if (AccountEquity()>accoutlimit) OpenMarketOrder();} } return; } // end of start int CloseOrder(int ticket,double numLots, double price) { int CloseCnt, err; CloseCnt = 0; while (CloseCnt < 3)// try to close 3 Times { if (!OrderClose(ticket,numLots,price,3,Yellow)) { err=GetLastError(); Print(CloseCnt," Error closing order : (", err , ") " + ErrorDescription(err)); if (err > 0) CloseCnt++; } else { CloseCnt = 3; } } } void Close_B(int ticket, double lot) { bool closecondition=false; if (UseTimeCut==true) closecondition=NormalizeDouble(Bid - OrderOpenPrice(), Digits) >= TakeProfit||NormalizeDouble(OrderOpenPrice()-Bid, Digits)>stoplossReal||TimeCurrent() - OrderOpenTime() > 60 * LimitTime_1; else closecondition=NormalizeDouble(Bid - OrderOpenPrice(), Digits) >= TakeProfit||NormalizeDouble(OrderOpenPrice()-Bid, Digits)>stoplossReal; if (closecondition==true) { CloseOrder(ticket, lot, Bid); //OrderClose(ticket, lot, Bid, 1, Yellow); HasBuyOrder = false; } } void Close_S(int ticket, double lot) { bool closecondition=false; if (UseTimeCut==true) closecondition=NormalizeDouble(OrderOpenPrice() - Ask, Digits) >= TakeProfit||NormalizeDouble(Ask-OrderOpenPrice(), Digits)>stoplossReal||TimeCurrent() - OrderOpenTime() > 60 * LimitTime_1; else closecondition=NormalizeDouble(OrderOpenPrice() - Ask, Digits) >= TakeProfit||NormalizeDouble(Ask-OrderOpenPrice(), Digits)>stoplossReal; if (closecondition==true) { CloseOrder(ticket, lot, Ask); //OrderClose(ticket, lot, Ask, 1, Yellow); HasSellOrder = false; } } void Modify_order() { double AveragePrice = 0; if (HasBuyLimitOrder == true) { AveragePrice = MA - MAMinDist; if (MathAbs(BL_openprice - AveragePrice) > Point / 2.0) BuyLiMitOpenprice=AveragePrice; BL_openprice=BuyLiMitOpenprice; // OrderModify(BL_ticket, AveragePrice, AveragePrice - stoploss, AveragePrice + LimitEntryDistance, 0, DeepSkyBlue); } if (HasSellLimitOrder == true) { AveragePrice = MA + Spread + MAMinDist; if (MathAbs(SL_openprice - AveragePrice) > Point / 2.0) SellLiMitOpenprice=AveragePrice; SL_openprice=SellLiMitOpenprice; // OrderModify(SL_ticket, AveragePrice, AveragePrice + stoploss, AveragePrice - LimitEntryDistance, 0, Pink); } } void OpenLimitOrder() { double AveragePrice = 0; double SL = 0; double MA_dis_pips = 0; if (HasBuyOrder == false && HasBuyLimitOrder == false) { AveragePrice = MA - Spread - MAMinDist; SL = AveragePrice - stoploss; MA_dis_pips = AveragePrice + LimitEntryDistance; if (AveragePrice > Ask - MA_dis_pips) AveragePrice = Ask - MA_dis_pips; AveragePrice = NormalizeDouble(AveragePrice, Digits); BuyLimitOrderEntered=true; BuyLiMitOpenprice=AveragePrice; //OrderSend(Symbol(), OP_BUYLIMIT, Lots(), AveragePrice, Slippage, SL, MA_dis_pips, "ISEA_Buy", MagicBase, 0, Blue); HasBuyLimitOrder = true; } if (HasSellOrder == false && HasSellLimitOrder == false) { AveragePrice = MA + Spread + MAMinDist; SL = AveragePrice + stoploss; MA_dis_pips = AveragePrice - LimitEntryDistance; if (AveragePrice < Bid + MA_dis_pips) AveragePrice = Bid + MA_dis_pips; AveragePrice = NormalizeDouble(AveragePrice, Digits); SellLimitOrderEntered=true; SellLiMitOpenprice=AveragePrice; //OrderSend(Symbol(), OP_SELLLIMIT, Lots(), AveragePrice, Slippage, SL, MA_dis_pips, "ISEA_Sell", MagicBase, 0, Red); HasSellLimitOrder = true; } } void OpenBuyOrder() { int err,ticket; int cnt=0; // while (OrderSend(Symbol(),OP_BUY,Lots(),Ask,Slippage,Ask-stoploss,Ask+TakeProfitFaked,"",MagicBase,0,Green)==FALSE&&cnt<OrderAttemps) while (OrderSend(Symbol(),OP_BUY,Lots(),Ask,Slippage,Ask-stoploss,0,"",MagicBase,0,Green)<=0&&cnt<OrderAttemps) { err = GetLastError(); Print("Error Modify BUY order: (" + err + ") " + ErrorDescription(err)); cnt++; Sleep(100); } } void OpenSellOrder() { int err, ticket; int cnt=0; //while (OrderSend(Symbol(),OP_SELL,Lots(),Bid,Slippage,Bid+stoploss,Bid-TakeProfitFaked,"",MagicBase,0,Red)<=0 && cnt<OrderAttemps) while (OrderSend(Symbol(),OP_SELL,Lots(),Bid,Slippage,Bid+stoploss,0,"",MagicBase,0,Red)<=0 && cnt<OrderAttemps) { err = GetLastError(); Print("Error Modify SELL order : (" + err + ") " + ErrorDescription(err)); cnt++; Sleep(100); } } void OpenMarketOrder() { //buy at ask, sell at bid if (Ask<(BuyLiMitOpenprice-brokerworsefill) && HasBuyOrder==false) { OpenBuyOrder(); BuyLimitOrderEntered=false; BL_openprice=0.0; BuyLiMitOpenprice=0.0; } if (Bid>(SellLiMitOpenprice+brokerworsefill)&&HasSellOrder==false) { OpenSellOrder(); SellLimitOrderEntered=false; SL_openprice=0.0; SellLiMitOpenprice=0.0; } } double Lots() { if(UseMoneyManagement==false) return(InitialLot); double lots; int orders=HistoryTotal(); int losses=0; int decimalPlaces=1; if(AccountIsMicro==true) decimalPlaces=2; lots=NormalizeDouble((AccountFreeMargin()*Risk/1000.0)/100,decimalPlaces); //lots=lots/(Percentage_ATR_LOT*iATR(NULL,15,14,0)); StoppedOut = LastTradeStoppedOut(); if (StoppedOut==true) { if(AccountIsMicro==false) lots=0.1; if(AccountIsMicro==true) lots=0.01; } if(lots<0.1 && AccountIsMicro==false) lots=0.1; if(lots<0.01 && AccountIsMicro==true) lots=0.01; double maxlot = MarketInfo(Symbol(), MODE_MAXLOT); if (MyMaxLot>0) { if (lots>MyMaxLot) return (MyMaxLot); } if(lots>maxlot) lots=maxlot-1; return(lots); } void ScreenComments() { string Msg; if (UseHourTrade) { if (!(Hour() >= FromHourTrade && Hour() <= ToHourTrade)) Msg= "\n " + Expert_Name + "\n\n TRADE SESSION"; else Msg= "\n " + Expert_Name + "\n\n OUT OF SESSION"; } Comment(Msg + "\n" + "------------------------------------------------------" + "\n" + "Broker: " + AccountCompany() + "\n" + "Broker Time = ", Hour() + " : " + Minute() + "\n" + "Time Start Trading = ", FromHourTrade + "\n" + "Time Stop Trading = ", ToHourTrade + "\n" + "-------------------------------------------------------" + "\n" + "ACCOUNT INFORMATION:" + "\n" + "Account Name: " + AccountName() + "\n" + "Account Number: " + AccountNumber() + "\n" + "Account Leverage: " + DoubleToStr(AccountLeverage(), 0) + "\n" + "Account Balance: " + DoubleToStr(AccountBalance(), 2) + "\n" + "Account Equity: " + DoubleToStr(AccountEquity(), 2) + "\n" + "Used Margin: " + DoubleToStr(AccountMargin(), 2) + "\n" + "------------------------------------------------------" + "\n" + "LOTS: " + DoubleToStr(Lots(), 2) + "\n" + "------------------------------------------------------" + "\n" + "SPREAD: " + DoubleToStr(GetSpread(),1) + " pips" + "\n" + "------------------------------------------------------" ); } int func_Symbol2Val(string symbol) { string mySymbol = StringSubstr(symbol,0,6); if(mySymbol=="AUDCAD") return(1); if(mySymbol=="NZDCAD") return(19); if(mySymbol=="AUDCHF") return(20); if(mySymbol=="AUDJPY") return(2); if(mySymbol=="AUDNZD") return(3); if(mySymbol=="AUDUSD") return(4); if(mySymbol=="CHFJPY") return(5); if(mySymbol=="EURAUD") return(6); if(mySymbol=="EURCAD") return(7); if(mySymbol=="EURCHF") return(8); if(mySymbol=="EURGBP") return(9); if(mySymbol=="EURJPY") return(10); if(mySymbol=="EURUSD") return(11); if(mySymbol=="GBPCHF") return(12); if(mySymbol=="GBPJPY") return(13); if(mySymbol=="GBPUSD") return(14); if(mySymbol=="NZDUSD") return(15); if(mySymbol=="USDCAD") return(16); if(mySymbol=="USDCHF") return(17); if(mySymbol=="USDJPY") return(18); Comment("unexpected Symbol"); return(19); } int func_TimeFrame_Const2Val(int Constant ) { switch(Constant) { case 1: // M1 return(1); case 5: // M5 return(2); case 15: return(3); case 30: return(4); case 60: return(5); case 240: return(6); case 1440: return(7); case 10080: return(8); case 43200: return(9); } } double GetSpread() { double Spread; if (Point == 0.00001) // Calculate the spread in pips for symbols quoted to 5 decimal places { Spread = (Ask - Bid) / (Point*10); // Current Spread price for this CurrencyPair in pip form. } if (Point == 0.0001) // Calculate the spread in pips for symbols quoted to 4 decimal places { Spread = (Ask - Bid) / (Point); // Current Spread price for this CurrencyPair in pip form. } if (Point == 0.001) // Calculate the spread in pips for symbols quoted to 3 decimal places { Spread = (Ask - Bid) / (Point*10); // Current Spread price for this CurrencyPair in pip form. } if (Point == 0.01) // Calculate the spread in pips for symbols quoted to 2 decimal places { Spread = (Ask - Bid) / (Point); // Current Spread price for this CurrencyPair in pip form. } return(Spread); } //+------------------------------------------------------------------+ //| return error description | //+------------------------------------------------------------------+ string ErrorDescription(int error_code) { string error_string; //---- switch(error_code) { //---- codes returned from trade server case 0: case 1: error_string="no error"; break; case 2: error_string="common error"; break; case 3: error_string="invalid trade parameters"; break; case 4: error_string="trade server is busy"; break; case 5: error_string="old version of the client terminal"; break; case 6: error_string="no connection with trade server"; break; case 7: error_string="not enough rights"; break; case 8: error_string="too frequent requests"; break; case 9: error_string="malfunctional trade operation"; break; case 64: error_string="account disabled"; break; case 65: error_string="invalid account"; break; case 128: error_string="trade timeout"; break; case 129: error_string="invalid price"; break; case 130: error_string="invalid stops"; break; case 131: error_string="invalid trade volume"; break; case 132: error_string="market is closed"; break; case 133: error_string="trade is disabled"; break; case 134: error_string="not enough money"; break; case 135: error_string="price changed"; break; case 136: error_string="off quotes"; break; case 137: error_string="broker is busy"; break; case 138: error_string="requote"; break; case 139: error_string="order is locked"; break; case 140: error_string="long positions only allowed"; break; case 141: error_string="too many requests"; break; case 145: error_string="modification denied because order too close to market"; break; case 146: error_string="trade context is busy"; break; //---- mql4 errors case 4000: error_string="no error"; break; case 4001: error_string="wrong function pointer"; break; case 4002: error_string="array index is out of range"; break; case 4003: error_string="no memory for function call stack"; break; case 4004: error_string="recursive stack overflow"; break; case 4005: error_string="not enough stack for parameter"; break; case 4006: error_string="no memory for parameter string"; break; case 4007: error_string="no memory for temp string"; break; case 4008: error_string="not initialized string"; break; case 4009: error_string="not initialized string in array"; break; case 4010: error_string="no memory for array\' string"; break; case 4011: error_string="too long string"; break; case 4012: error_string="remainder from zero divide"; break; case 4013: error_string="zero divide"; break; case 4014: error_string="unknown command"; break; case 4015: error_string="wrong jump (never generated error)"; break; case 4016: error_string="not initialized array"; break; case 4017: error_string="dll calls are not allowed"; break; case 4018: error_string="cannot load library"; break; case 4019: error_string="cannot call function"; break; case 4020: error_string="expert function calls are not allowed"; break; case 4021: error_string="not enough memory for temp string returned from function"; break; case 4022: error_string="system is busy (never generated error)"; break; case 4050: error_string="invalid function parameters count"; break; case 4051: error_string="invalid function parameter value"; break; case 4052: error_string="string function internal error"; break; case 4053: error_string="some array error"; break; case 4054: error_string="incorrect series array using"; break; case 4055: error_string="custom indicator error"; break; case 4056: error_string="arrays are incompatible"; break; case 4057: error_string="global variables processing error"; break; case 4058: error_string="global variable not found"; break; case 4059: error_string="function is not allowed in testing mode"; break; case 4060: error_string="function is not confirmed"; break; case 4061: error_string="send mail error"; break; case 4062: error_string="string parameter expected"; break; case 4063: error_string="integer parameter expected"; break; case 4064: error_string="double parameter expected"; break; case 4065: error_string="array as parameter expected"; break; case 4066: error_string="requested history data in update state"; break; case 4099: error_string="end of file"; break; case 4100: error_string="some file error"; break; case 4101: error_string="wrong file name"; break; case 4102: error_string="too many opened files"; break; case 4103: error_string="cannot open file"; break; case 4104: error_string="incompatible access to a file"; break; case 4105: error_string="no order selected"; break; case 4106: error_string="unknown symbol"; break; case 4107: error_string="invalid price parameter for trade function"; break; case 4108: error_string="invalid ticket"; break; case 4109: error_string="trade is not allowed"; break; case 4110: error_string="longs are not allowed"; break; case 4111: error_string="shorts are not allowed"; break; case 4200: error_string="object is already exist"; break; case 4201: error_string="unknown object property"; break; case 4202: error_string="object is not exist"; break; case 4203: error_string="unknown object type"; break; case 4204: error_string="no object name"; break; case 4205: error_string="object coordinates error"; break; case 4206: error_string="no specified subwindow"; break; default: error_string="unknown error"; } //---- return(error_string); } bool GetNews() { static int PrevMinute = -1; bool b.NewsTime=false; int MinSinceNews = iCustom(NULL, 0, "FFCal", 0, 0, 1, 1, 1, 1, 20, 20, 0, 0, 0, 1, 10, 13882323, 3329330, 255, 42495, 65535, 21, 600, 600, 16748574, 12632256, 10, 3, 0, 1, 0); int Min2News = iCustom(NULL, 0, "FFCal", 0, 0, 1, 1, 1, 1, 20, 20, 0, 0, 0, 1, 10, 13882323, 3329330, 255, 42495, 65535, 21, 600, 600, 16748574, 12632256, 10, 3, 0, 1, 1); //now compaire how many minuetes left for the time. if (Minute() != PrevMinute) { PrevMinute = Minute(); b.NewsTime = false; if ((Min2News <= MinsBeforeNews) || (MinSinceNews <= MinsAfterNews)) b.NewsTime = true; } return(b.NewsTime); } datetime LastTradeStoppedOut() { int cnt, total; datetime NextTime; bool Stopped=false; NextTime = 0; total = HistoryTotal(); for (cnt = total - 1; cnt >= 0; cnt--) { OrderSelect (cnt, SELECT_BY_POS, MODE_HISTORY); if(OrderSymbol()==Symbol() && OrderMagicNumber() == MagicBase) { Stopped = false; if (OrderType() == OP_BUY) { if (OrderClosePrice() - OrderOpenPrice() < 0) { Stopped = true; } cnt = 0; } if (OrderType() == OP_SELL) { if (OrderOpenPrice() - OrderClosePrice() < 0) { Stopped = true; } cnt = 0; } } } if (Stopped) { StopTime = OrderCloseTime() + MinutesToDelay*60; } return (Stopped); } void ForceCloseAll() { for (int i = 0; i < OrdersTotal(); i++) { OrderSelect(i, SELECT_BY_POS, MODE_TRADES); if (OrderSymbol() == Symbol() && OrderMagicNumber() == MagicBase) { if (OrderType() == OP_BUY) Close_B(OrderTicket(), OrderLots()); if (OrderType() == OP_SELL) Close_S(OrderTicket(), OrderLots()); if (OrderType()==OP_SELLLIMIT||OrderType()==OP_BUYLIMIT) OrderDelete(OrderTicket()); } } }
Sample
Analysis
Market Information Used:
Series array that contains open time of each bar
Indicator Curves created:
Indicators Used:
Indicator of the average true range
Moving average indicator
Custom Indicators Used:
FFCal
Order Management characteristics:
Checks for the total of open orders
It Closes Orders by itself
It automatically opens orders when conditions are reached
Other Features: