Keltner Breakout FxFisherman





//+------------------------------------------------------------------+
//|                                   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:

BackTest : EURUSD on H1

From 2009-08-01 to 2009-10-01 Profit Factor:0.34 Total Net Profit:-9879.60

BackTest : EURUSD on H1

From 2009-12-01 to 2010-01-17 Profit Factor:0.71 Total Net Profit:-4467.60

BackTest : EURUSD on H1

From 2010-03-01 to 2010-03-27 Profit Factor:0.79 Total Net Profit:-2124.50

BackTest : EURUSD on H1

From 2010-04-01 to 2010-04-30 Profit Factor:0.00 Total Net Profit:0.00

BackTest : EURUSD on H1

From 2010-05-01 to 2010-05-31 Profit Factor:0.00 Total Net Profit:0.00

BackTest : EURUSD on H1

From 2010-06-01 to 2010-06-30 Profit Factor:0.00 Total Net Profit:0.00

BackTest : GBPUSD on H1

From 2010-01-01 to 2010-02-27 Profit Factor:0.57 Total Net Profit:-9975.50

BackTest : USDCAD on H1

From 2009-01-01 to 2010-01-01 Profit Factor:0.46 Total Net Profit:-10013.92

BackTest : USDCAD on H1

From 2009-12-01 to 2010-01-01 Profit Factor:0.51 Total Net Profit:-4121.87

BackTest : USDCHF on H1

From 2009-12-01 to 2010-01-01 Profit Factor:0.40 Total Net Profit:-5561.97

BackTest : USDJPY on H1

From 2009-11-01 to 2009-11-30 Profit Factor:0.93 Total Net Profit:-373.27

Request Backtest for Keltner Breakout FxFisherman


From : (yyyy/mm/dd) To: (yyyy/mm/dd)

Pair: Period: