//+------------------------------------------------------------------+ //| Keltner Breakout 1 FxFisherman | //| Scorpion | //| www.fxfisherman.com | //+------------------------------------------------------------------+ #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 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 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; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { main_magic = 1120000 + GetTimeframeConstant(Period()) + GetSymbolConstant(Symbol()); return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { return(0); } //+------------------------------------------------------------------+ //| expert start function | //+------------------------------------------------------------------+ int start() { // 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 = CurTime(); 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); double r0 = iCustom(Symbol(), Period(), "Keltner_Channels", Keltner_Period, 300, 0, 0); double s0 = iCustom(Symbol(), Period(), "Keltner_Channels", Keltner_Period, 300, 2, 0); double pipsExtra = Extra_Pips * Point; 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)) { 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*Point); int ticket = OrderSendEx(Symbol(), OP_BUY, lotSize, Ask, open_slippage*Point, 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*Point); int ticket = OrderSendEx(Symbol(), OP_SELL, lotSize, Bid, open_slippage*Point, 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*Point) && (ts > 0) && (Bid >= OrderOpenPrice() + TS_Trigger*Point )) { if (Bid - ts >= 5 * Point) { 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*Point) && (ts > 0) && (Ask <= OrderOpenPrice() - TS_Trigger*Point)){ if (ts - Ask >= 5 * Point) { 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-(Point*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] - Point; 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+(Point*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] + Point; 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=CurTime(); while (GlobalVariableCheck("InTrade") || !IsTradeAllowed()) { if(OldCurTime + timeoutsec <= CurTime()) { return(false); } Sleep(1000); } return(true); } void SetBusyState() { GlobalVariableSet("InTrade", CurTime()); // 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(CurTime())); }
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:
Keltner_Channels
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: