//+------------------------------------------------------------------+ //| Keltner Breakout 1 FxFisherman | //| Scorpion | //| www.fxfisherman.com | //| | //| 7/23/2008 Changed made by Robert Hill | //| Added code to select us eof parameter 300 in iCustom call to | //| Keltner Channels indicator | //| Changed CurTime() to TimeCurrent() | //| Added code to handle extra digit in prices by using myPoint | //| in place of Point | //| Added code to use Damiani_Volatmeter as a possible filter | //| Modified code to handle sessions that cross day boundary | //| Added prompts for ts_mode | //| Changed UseDamiani switches from bool to int for easier Backtest | //+------------------------------------------------------------------+ #property copyright "Scorpion" #property link "http://www.fxfisherman.com" #include #define TS_MODE_DISABLE 0 #define TS_MODE_FIXED_SL 1 #define TS_MODE_ATR 2 #define TS_MODE_HALF_VOLATILITY 3 #define TS_MODE_BREAKOUT 4 #define TS_MODE_BREAKEVEN 5 //---- input parameters extern string _______Position_______; extern double Lots=1; extern double Lots_PCT=10; extern bool Use_Lots_PCT=false; extern int TP=0; extern int SL=30; extern int SL_Mode=0; extern int Breakeven_Pips=0; extern string ______TrailingStop_____; extern string tss0 = "0 = disabled, 1 = Fixed SL, 2 = ATR"; extern string tss1 = "3 = Half Volatility"; extern string tss2 = "4 = Breakout Yesterday Hi/Lo"; extern string tss3 = "5 = Breakeven"; extern int TS_Mode=0; // 0 = disabled, 1 = Fixed SL, 2 = ATR, 3 = Half Volatility, 4 = Breakout Yesterday Hi/Lo extern int TS_Trigger=30; extern int TS_Sensitivity=3; extern double TS_DynamicFactor=0.5; // applied only if TrailingStopMode = 2 or 3 extern int Evaluate_Interval=1; // -1 chart, 0 tick, > 0 specified min extern string _______Indicators______; extern int Extra_Pips=1; extern int Keltner_Period = 10; extern bool Use300 = false; extern string _______Damiani________; extern int Filter_Damiani_15=0; extern int Filter_Damiani_30=0; //extern int Viscosity_15 = 7; //extern int Sedimentation_15 = 40; //extern double Threshold_15 = 1.40; //extern bool Lagsuppressor_15 = True; extern string _______Session_______; extern bool Filter_Session=false; extern int From_Hour=13; extern int From_Min=0; extern int To_Hour=18; extern int To_Min=0; string expert_name = "Keltner Breakout"; int main_magic; int open_slippage=5; int close_slippage=10; int orderType; double orderPrice; datetime timeNextEval; // Robert Hill Added following variables double myPoint; int TradeStart; // Start trades after time int TradeStop; // Stop trading after time bool YesStop; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { main_magic = 1120000 + GetTimeframeConstant(Period()) + GetSymbolConstant(Symbol()); myPoint = SetPoint(Symbol()); // Correct times for using my functions for session filter TradeStart = From_Hour * 100 + From_Min; TradeStop = To_Hour * 100 + To_Min; return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { double r0, s0; double d0, d2; // set breakeven and trailing stops int ticket = OrderTicketByMagicNum(main_magic); if (ticket > 0 && Breakeven_Pips > 0) ControlTrailingStop(ticket, SL, TS_MODE_BREAKEVEN, Breakeven_Pips, TS_DynamicFactor, TS_Sensitivity); if (ticket > 0 && TS_Mode > 0) ControlTrailingStop(ticket, SL, TS_Mode, TS_Trigger, TS_DynamicFactor, TS_Sensitivity); // analyse now? bool isAnalyseNow=false; datetime timeNow = TimeCurrent(); int intervalEval = Evaluate_Interval; if (Evaluate_Interval == -1) intervalEval = Period(); if (!(intervalEval > 0 && timeNow < timeNextEval)) isAnalyseNow=true; // analyse chart static bool isBuy, isSell, isCloseBought, isCloseSold; if (isAnalyseNow) { timeNextEval = timeNow - (timeNow % (intervalEval*60)) + (intervalEval*60); ticket = OrderTicketByMagicNum(main_magic); // Code added to use parameter 300 or not if (Use300 == true) { r0 = iCustom(Symbol(), Period(), "Keltner_Channels", Keltner_Period, 300, 0, 0); s0 = iCustom(Symbol(), Period(), "Keltner_Channels", Keltner_Period, 300, 2, 0); } else { r0 = iCustom(Symbol(), Period(), "Keltner_Channels", Keltner_Period, 0, 0); s0 = iCustom(Symbol(), Period(), "Keltner_Channels", Keltner_Period, 2, 0); } double pipsExtra = Extra_Pips * myPoint; isBuy = (Bid > r0 + pipsExtra); isSell = (Bid < s0 - pipsExtra); isCloseBought = (Bid < s0 - pipsExtra); isCloseSold = (Bid > r0 + pipsExtra); // filter out entries if not in trading session if (Filter_Session) { // double From_Time = From_Hour + (From_Min/60); // double To_Time = To_Hour + (To_Min/60); // double Cur_Time = Hour() + (Minute()/60); // if (!(From_Time <= Cur_Time && Cur_Time <= To_Time)) YesStop = CheckTradingTimes(); if (YesStop) { isBuy = False; isSell = False; } } // Code to use Damiani_volatmeter as filter on 15 and 30 minute timeframes if (Filter_Damiani_15 == 1) { // d0 = iCustom(Symbol(), PERIOD_M15, "Damiani_volatmeter", Viscosity_15,Sedimentation_15,Threshold_15,Threshold_15, 0, 0); // d2 = iCustom(Symbol(), PERIOD_M15, "Damiani_volatmeter", Viscosity_15,Sedimentation_15,Threshold_15,Threshold_15, 2, 0); d0 = iCustom(Symbol(), PERIOD_M15, "Damiani_volatmeterNoInputs", 0, 0); d2 = iCustom(Symbol(), PERIOD_M15, "Damiani_volatmeterNoInputs", 2, 0); if (d0 > d2) { isBuy = False; isSell = False; } } if (Filter_Damiani_30 == 1) { d0 = iCustom(Symbol(), PERIOD_M30, "Damiani_volatmeter", 0, 0); d2 = iCustom(Symbol(), PERIOD_M30, "Damiani_volatmeter", 2, 0); if (d0 > d2) { isBuy = False; isSell = False; } } } // close orders ticket = OrderTicketByMagicNum(main_magic); if (ticket > 0 && (isCloseBought || isCloseSold)){ if (OrderSelectEx(ticket,SELECT_BY_TICKET,MODE_TRADES)==false) return(0); if (OrderType() == OP_BUY && isCloseBought){ CloseNow(ticket); }else if (OrderType() == OP_SELL && isCloseSold){ CloseNow(ticket); } } // enter orders ticket = OrderTicketByMagicNum(main_magic); if (ticket==0){ static int lastType; static int lastDay; if (isBuy && !isSell && !(lastType == 1 && lastDay == Today())){ if (BuyNow()>0) { isBuy = false; lastType = 1; lastDay = Today(); } }else if(isSell && !isBuy && !(lastType == 2 && lastDay == Today())){ if (SellNow()>0) { isSell = false; lastType = 2; lastDay = Today(); } }else if(isSell && isBuy){ Print("Error: Buy and sell signals are issued at the same time!"); } } return(0); } //+------------------------------------------------------------------+ //| Buy | //+------------------------------------------------------------------+ int BuyNow() { double trueSL, trueTP, lotSize; lotSize = GetLots(Symbol(), Lots, Lots_PCT, Use_Lots_PCT); trueSL = Get_SL(OP_BUY, Ask, Ask, SL, SL_Mode, TS_DynamicFactor); if (TP > 0) trueTP = Bid+(TP*myPoint); int ticket = OrderSendEx(Symbol(), OP_BUY, lotSize, Ask, open_slippage*myPoint, trueSL, trueTP, expert_name + " " + Symbol() + Period(), main_magic, 0, Yellow); if (ticket > 0) orderType = OP_BUY; orderPrice = Bid; return(ticket); } //+------------------------------------------------------------------+ //| Sell | //+------------------------------------------------------------------+ int SellNow() { double trueSL, trueTP, lotSize; lotSize = GetLots(Symbol(), Lots, Lots_PCT, Use_Lots_PCT); trueSL = Get_SL(OP_SELL, Bid, Bid, SL, SL_Mode, TS_DynamicFactor); if (TP > 0) trueTP = Bid-(TP*myPoint); int ticket = OrderSendEx(Symbol(), OP_SELL, lotSize, Bid, open_slippage*myPoint, trueSL, trueTP, expert_name + " " + Symbol() + Period(), main_magic, 0, Yellow); if (ticket > 0) orderType = OP_SELL; orderPrice = Bid; return(ticket); } //+------------------------------------------------------------------+ //| Control trailing stop | //+------------------------------------------------------------------+ void ControlTrailingStop(int ticket, double SL, int TS_Mode, int TS_Trigger, double TS_DynamicFactor, int TS_Sensitivity) { if (ticket == 0 || TS_Mode == 0) return; double ts; if (OrderSelectEx(ticket, SELECT_BY_TICKET, MODE_TRADES)==false) return; if (OrderType() == OP_BUY){ ts = Get_SL(OP_BUY, OrderOpenPrice(), Bid, SL, TS_Mode, TS_DynamicFactor); if ((ts >= OrderStopLoss() + TS_Sensitivity*myPoint) && (ts > 0) && (Bid >= OrderOpenPrice() + TS_Trigger*myPoint )) { if (Bid - ts >= 5 * myPoint) { OrderModifyEx(ticket, OrderOpenPrice(), ts, OrderTakeProfit(), 0, Red); }else if(Bid <= ts){ CloseNow(ticket); } } }else if(OrderType() == OP_SELL){ ts = Get_SL(OP_SELL, OrderOpenPrice(), Ask, SL, TS_Mode, TS_DynamicFactor); if ((ts <= OrderStopLoss() - TS_Sensitivity*myPoint) && (ts > 0) && (Ask <= OrderOpenPrice() - TS_Trigger*myPoint)){ if (ts - Ask >= 5 * myPoint) { OrderModifyEx(ticket, OrderOpenPrice(), ts, OrderTakeProfit(), 0, Red); }else if(ts <= Ask){ CloseNow(ticket); } } } } double Get_SL(int order_type, double order_price, double price, double sl, int sl_mode, double sl_dynamicfactor) { if (sl_mode == 0) return(0); double ts; double ma_0, hh, ll; if (order_type == OP_BUY){ switch (sl_mode){ case TS_MODE_FIXED_SL: if(sl > 0) ts = price-(myPoint*sl); break; case TS_MODE_ATR: ts = Low[0] - (sl_dynamicfactor * iATR(NULL,0,14,0)); break; case TS_MODE_HALF_VOLATILITY: ts = Low[0] - (sl_dynamicfactor *(High[0]-Low[0])); break; case TS_MODE_BREAKOUT: ts = Low[1] - myPoint; break; case TS_MODE_BREAKEVEN: ts = order_price; break; } }else if(order_type == OP_SELL){ switch (sl_mode){ case TS_MODE_FIXED_SL: if(sl > 0) ts = price+(myPoint*sl); break; case TS_MODE_ATR: ts = High[0] + (sl_dynamicfactor * iATR(NULL,0,14,0)); break; case TS_MODE_HALF_VOLATILITY: ts = High[0] + (sl_dynamicfactor *(High[0]-Low[0])); break; case TS_MODE_BREAKOUT: ts = High[1] + myPoint; break; case TS_MODE_BREAKEVEN: ts = order_price; break; } } return(ts); } //+------------------------------------------------------------------+ //| Close at market price | //+------------------------------------------------------------------+ bool CloseNow(int ticket) { if (OrderSelectEx(ticket, SELECT_BY_TICKET)) { if (OrderType() == OP_BUY) { OrderCloseEx(ticket, OrderLots(), Bid, close_slippage); }else if (OrderType() == OP_SELL){ OrderCloseEx(ticket, OrderLots(), Ask, close_slippage); } } } //+------------------------------------------------------------------+ //| Lots size functions (fixed lot, compound lot, etc) | //+------------------------------------------------------------------+ double GetLots(string symbol, double lots, double lots_pct, bool use_lots_pct) { if (!use_lots_pct) { return(lots); }else{ double lotStep = MarketInfo(symbol, MODE_LOTSTEP); double lotSize = MarketInfo(symbol, MODE_LOTSIZE) / AccountLeverage(); double lot = (AccountBalance() * (lots_pct/100)) / lotSize; double leftover = MathMod(lot, lotStep); if (MathMod(lot/lotStep, 1) >= 0.00001) lot = lot - leftover; return(lot); } } //+------------------------------------------------------------------+ //| Extended order execution functions for used in multiple pairs | //| with automatic retry attempts. | //+------------------------------------------------------------------+ int OrderSendEx(string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment, int magic, datetime expiration=0, color arrow_color=CLR_NONE) { if(!WaitWhileBusy()) { Print("Error in OrderSendEx(): Timeout encountered"); return(-1); } SetBusyState(); int ticket = OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrow_color); Sleep(6000); ReleaseBusyState(); return(ticket); } bool OrderCloseEx(int ticket, double lots, double price, int slippage, color Color=CLR_NONE) { if(!WaitWhileBusy()) { Print("Error in OrderCloseEx(): Timeout encountered"); return(false); } SetBusyState(); bool ret = OrderClose(ticket, lots, price, slippage, Color); Sleep(6000); ReleaseBusyState(); return(ret); } bool OrderModifyEx( int ticket, double price, double stoploss, double takeprofit, datetime expiration, color arrow_color=CLR_NONE) { if(!WaitWhileBusy()) { Print("Error in OrderModifyEx(): Timeout encountered"); return(false); } SetBusyState(); bool ret = OrderModify(ticket, price, stoploss, takeprofit, expiration, arrow_color); if(ret) { Sleep(6000); }else{ Print("Error in OrderModifyEx(): ", LastErrorText()); } ReleaseBusyState(); return(ret); } bool OrderSelectEx(int index, int select, int pool = MODE_TRADES) { if (OrderSelect(index,select,pool)==true) { return(true); }else{ Print("Error: Order #", index ," cannot be selected. ", LastErrorText()); } } //+------------------------------------------------------------------+ //| Calling state functions | //+------------------------------------------------------------------+ bool WaitWhileBusy() { datetime OldCurTime; int timeoutsec=6; OldCurTime=TimeCurrent(); while (GlobalVariableCheck("InTrade") || !IsTradeAllowed()) { if(OldCurTime + timeoutsec <= TimeCurrent()) { return(false); } Sleep(1000); } return(true); } void SetBusyState() { GlobalVariableSet("InTrade", TimeCurrent()); // set lock indicator } void ReleaseBusyState() { GlobalVariableDel("InTrade"); // clear lock indicator } //+------------------------------------------------------------------+ //| Get order ticket by magic number | //+------------------------------------------------------------------+ int OrderTicketByMagicNum(int magic_number) { for(int i=0;i EndHour) return(true) ; } else { if(ct > EndHour && ct < StartHour) return(true) ; } return(false) ; }