//+------------------------------------------------------------------+ //| 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 <stdlib.mqh> #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<OrdersTotal();i++) { if (OrderSelect(i, SELECT_BY_POS) == false) continue; if (OrderMagicNumber() == magic_number) return(OrderTicket()); } } //+------------------------------------------------------------------+ //| Time frame interval appropriation function | //+------------------------------------------------------------------+ int GetTimeframeConstant(int chart_period) { switch(chart_period) { case 1: // M1 return(50); case 5: // M5 return(100); case 15: return(150); case 30: return(200); case 60: return(250); case 240: return(300); case 1440: return(350); case 10080: return(400); case 43200: return(450); } } //+------------------------------------------------------------------+ //| Symbol to index | //+------------------------------------------------------------------+ int GetSymbolConstant(string symbol) { if(symbol=="EURUSD" || symbol=="mEURUSD" || symbol=="EURUSDm") { return(1); } else if(symbol=="GBPUSD" || symbol=="GBPUSDm") { return(2); } else if(symbol=="USDCHF" || symbol=="USDCHFm") { return(3); } else if(symbol=="USDJPY" || symbol=="USDJPYm") { return(4); } else if(symbol=="USDCAD" || symbol=="USDCADm") { return(5); } else if(symbol=="AUDUSD" || symbol=="AUDUSDm") { return(6); } else if(symbol=="CHFJPY" || symbol=="CHFJPYm") { return(7); } else if(symbol=="EURAUD" || symbol=="EURAUDm") { return(8); } else if(symbol=="EURCAD" || symbol=="EURCADm") { return(9); } else if(symbol=="EURCHF" || symbol=="EURCHFm") { return(10); } else if(symbol=="EURGBP" || symbol=="EURGBPm") { return(11); } else if(symbol=="EURJPY" || symbol=="EURJPYm") { return(12); } else if(symbol=="GBPCHF" || symbol=="GBPCHFm") { return(13); } else if(symbol=="GBPJPY" || symbol=="GBPJPYm") { return(14); } else if(symbol=="GOLD" || symbol=="GOLDm") { return(15); } else {Print("Error: Unexpected symbol."); return(0); } } //+------------------------------------------------------------------+ //| Get last error description | //+------------------------------------------------------------------+ string LastErrorText() { return(ErrorDescription(GetLastError())); } datetime StripTime(datetime dt) { return (dt - (TimeHour(dt)*3600) - (TimeMinute(dt)*60) - TimeSeconds(dt)); } datetime Today() { return (StripTime(TimeCurrent())); } double SetPoint(string mySymbol) { double mPoint, myDigits; myDigits = MarketInfo (mySymbol, MODE_DIGITS); if (myDigits < 4) mPoint = 0.01; else mPoint = 0.0001; return(mPoint); } bool CheckTradingTimes() { bool StopTrading; int ct; ct = Hour() * 100 + Minute(); StopTrading = true; StopTrading = CheckOutsideSession(TradeStart, TradeStop, ct); return(StopTrading); } // Return true if time is not in session for trading // Handles start and end times that cross day boundary bool CheckOutsideSession( int StartHour, int EndHour, int ct) { if(StartHour<=EndHour) { if(ct < StartHour || ct > EndHour) return(true) ; } else { if(ct > EndHour && ct < StartHour) return(true) ; } return(false) ; }
Sample
Analysis
Market Information Used:
Series array that contains the lowest prices of each bar
Series array that contains the highest prices of each bar
Indicator Curves created:
Indicators Used:
Indicator of the average true range
Custom Indicators Used:
Damiani_volatmeter
Keltner_Channels
Damiani_volatmeterNoInputs
Order Management characteristics:
It automatically opens orders when conditions are reached
It Closes Orders by itself
It can change open orders parameters, due to possible stepping strategy
Checks for the total of open orders
Other Features: