Keltner Breakout FxFishermanFiltered





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

BackTest : EURUSD on H1

From 2009-08-01 to 2009-10-01 Profit Factor:0.35 Total Net Profit:-9779.50

BackTest : EURUSD on H1

From 2009-12-01 to 2010-01-17 Profit Factor:0.69 Total Net Profit:-4773.00

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.52 Total Net Profit:-10014.00

BackTest : USDCAD on H1

From 2009-12-01 to 2010-01-01 Profit Factor:0.30 Total Net Profit:-7911.80

BackTest : USDJPY on H1

From 2009-11-01 to 2009-11-30 Profit Factor:0.63 Total Net Profit:-2542.81

Request Backtest for Keltner Breakout FxFishermanFiltered


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

Pair: Period: