//+------------------------------------------------------------------+ //| OverHedgeTrend.mq4 | //| Copyright © 2006, | //| | //| Written by MrPip (Robert Hill) for kmrunner | //| 3/7/06 Added check of direction for first trade Buy or Sell | //| 3/21/07 Added modification of Lots calculation to use number | //| of open trades + 1 instead of using power of 2 | //+------------------------------------------------------------------+ #property copyright "Copyright © 2005" #property link "http://www.strategtbuilderfx.com" #include extern string Expert_Name = "OverHedgeTrend"; extern double Lots = 0.1; extern double MaxLots = 13; extern bool useDoubleLots = false; extern double HedgeBase = 2.0; extern int Slippage = 5; extern bool shutdownGrid = false; extern int TunnelWidth=20; extern double profitTarget = 100; // if > 0, will close out all positions once the pip target has been met extern int LSMAPeriod = 21; extern int LSMA_TimeFrame = 15; extern int PauseSeconds = 6; // Number of seconds to "sleep" before closing the next winning trade extern int MillisPerSec = 1000; // DO NOT CHANGE - Standard multiplier to convert seconds to milliseconds double TunnelSize; string setup; int MagicNumber; double startBuyRate, startSellRate; int currentOpen; int NumBuyTrades, NumSellTrades; // Number of buy and sell trades in this symbol bool myWantLongs; double lotMM; double Profit; bool OK2Buy,OK2Sell, FirstDirSell; //+------------------------------------------------------------------+ //| expert initialization function | //+------------------------------------------------------------------+ int init() { //---- MagicNumber = 3000 + func_Symbol2Val(Symbol())*100 + func_TimeFrame_Const2Val(Period()); setup = Expert_Name + "-" + Symbol() + "_" + func_TimeFrame_Val2String(func_TimeFrame_Const2Val(Period())); return(0); } //+------------------------------------------------------------------+ //| expert deinitialization function | //+------------------------------------------------------------------+ int deinit() { return(0); } //+------------------------------------------------------------------+ //| script program start function | //+------------------------------------------------------------------+ int start() { //---- //---- test if we want to shutdown if (shutdownGrid ) // close all orders. then exit.. there is nothing more to do { CloseOpenPositions(); return(0); } TunnelSize = GetTunnelSize(); // Check for new trade cycle // First check if profit target is reached // If yes then there will be no open positions // So a new trade cycle will begin CheckProfit(); currentOpen = CheckOpenPositions("BOTH"); if (currentOpen == 0) { // Start trades based on confirmation direction, was daily if (CheckDirection() == 0) return(0); if (CheckDirection() == 1) { OK2Buy = true; OK2Sell = false; FirstDirSell = false; } if (CheckDirection() == -1) { OK2Buy = false; OK2Sell = true; FirstDirSell = true; } if (OK2Buy) { startBuyRate = MarketInfo(Symbol(), MODE_ASK) ; startSellRate = MarketInfo(Symbol(), MODE_BID) - TunnelSize*Point; } if (OK2Sell) { startSellRate = MarketInfo(Symbol(), MODE_BID) ; startBuyRate = MarketInfo(Symbol(), MODE_BID) + TunnelSize*Point; } } else { OK2Buy = true; OK2Sell = true; } // Determine how many lots for next trade based on current number of open positions if (useDoubleLots) lotMM = Lots * MathPow(HedgeBase,currentOpen); else lotMM = Lots * (currentOpen+1); lotMM = MathFloor(lotMM*10)/10; if (lotMM == 0) return (0); // if MaxLots is reached do not allow more trades if (lotMM > MaxLots) return(0); // Determine if next trade should be long or short based on current number of open positions myWantLongs = true; if (MathMod(currentOpen,2) > 0.1) myWantLongs = false; if (FirstDirSell) myWantLongs = !myWantLongs; // added to match starting trade direction if (myWantLongs) { if (MarketInfo(Symbol(), MODE_ASK) >= startBuyRate ) { OpenBuyOrder(); } } else { if (MarketInfo(Symbol(), MODE_BID) <= startSellRate) { OpenSellOrder(); } } return(0); } double GetTunnelSize() { double val; double myBid, myAsk; int digits; digits = MarketInfo(Symbol(), MODE_DIGITS) ; myBid = MarketInfo(Symbol( ), MODE_BID); if (digits > 0) myBid = NormalizeDouble( myBid, digits); myAsk = MarketInfo(Symbol( ), MODE_ASK); if (digits > 0) myAsk = NormalizeDouble( myAsk, digits); val = ((2*(myAsk-myBid)/Point)+TunnelWidth); return(val); } //+------------------------------------------------------------------------+ //| LSMAConfirmation is use by CheckDirection to allow trades only in | //| the direction of the confirmation time frame, was Daily | //| LSMA - Least Squares Moving Average function calculation | //| LSMA_In_Color Indicator plots the end of the linear regression line | //+------------------------------------------------------------------------+ double LSMAConfirmation(int Rperiod, int shift) { int i; double sum; int length; double lengthvar; double tmp; double wt; length = Rperiod; sum = 0; for(i = length; i >= 1 ; i--) { lengthvar = length + 1; lengthvar /= 3; tmp = 0; tmp = ( i - lengthvar)*iClose(NULL, LSMA_TimeFrame, length-i+shift); sum+=tmp; } wt = sum*6/(length*(length+1)); wt = NormalizeDouble(wt,MarketInfo(Symbol(),MODE_DIGITS)); return(wt); } //+------------------------------------------------------------------+ //| CheckDirection | //| Check direction for trade | //| Now uses Confirmation, was Daily | //| return 1 for up, -1 for down, 0 for flat | //+------------------------------------------------------------------+ int CheckDirection() { double SlowEMA, FastEMA; double Dif; Dif = LSMAConfirmation(LSMAPeriod,1) - LSMAConfirmation(LSMAPeriod,2); if(Dif > 0 ) return(1); if(Dif < 0 ) return(-1); return(0); } //+------------------------------------------------------------------+ //| Close Open Positions | //| Close all open positions | //| Losing trades are closed first so that | //| another trade is not triggered. | //+------------------------------------------------------------------+ void CloseOpenPositions() { int cnt, err, digits; double myPrice; digits = MarketInfo(Symbol(), MODE_DIGITS) ; // First close losing trades for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS,MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_BUY && OrderProfit() < 0) { Sleep(PauseSeconds*MillisPerSec); myPrice = MarketInfo(Symbol( ), MODE_BID); if (digits > 0) myPrice = NormalizeDouble( myPrice, digits); if (OrderClose(OrderTicket(),OrderLots(),myPrice,Slippage,Violet)) { Print("Buy Order closed for " + Symbol() + " at " + myPrice + "."); } else { err=GetLastError(); Print("Error closing order : (", err , ") " + ErrorDescription(err)); } } if(OrderType() == OP_SELL && OrderProfit() < 0) { Sleep(PauseSeconds*MillisPerSec); myPrice = MarketInfo(Symbol( ), MODE_ASK); if (digits > 0) myPrice = NormalizeDouble( myPrice, digits); if (OrderClose(OrderTicket(),OrderLots(),Ask,Slippage,Violet)) { Print("Sell Order closed for " + Symbol() + " at " + Ask + "."); } else { err=GetLastError(); Print("Error closing order : (", err , ") " + ErrorDescription(err)); } } } // Then close winning trades for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS,MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_BUY && OrderProfit() > 0) { Sleep(PauseSeconds*MillisPerSec); myPrice = MarketInfo(Symbol( ), MODE_BID); if (digits > 0) myPrice = NormalizeDouble( myPrice, digits); if (OrderClose(OrderTicket(),OrderLots(),myPrice,Slippage,Gold)) { Print("Buy Order closed for " + Symbol() + " at " + myPrice + "."); } else { err=GetLastError(); Print("Error closing order : (", err , ") " + ErrorDescription(err)); } } if(OrderType() == OP_SELL && OrderProfit() > 0) { Sleep(PauseSeconds*MillisPerSec); myPrice = MarketInfo(Symbol( ), MODE_ASK); if (digits > 0) myPrice = NormalizeDouble( myPrice, digits); if (OrderClose(OrderTicket(),OrderLots(),myPrice,Slippage,Gold)) { Print("Sell Order closed for " + Symbol() + " at " + myPrice + "."); } else { err=GetLastError(); Print(" Error closing order : (", err , ") " + ErrorDescription(err)); } } } } //+------------------------------------------------------------------------+ //| counts the number of open positions | //| type BUY returns number of long positions | //| type SELL returns number of short positions | //| type BOTH returns number of long and short positions | //+------------------------------------------------------------------------+ int CheckOpenPositions(string type) { int cnt, NumPositions; int NumBuyTrades, NumSellTrades; // Number of buy and sell trades in this symbol NumBuyTrades = 0; NumSellTrades = 0; for(cnt=OrdersTotal()-1;cnt>=0;cnt--) { OrderSelect (cnt, SELECT_BY_POS, MODE_TRADES); if ( OrderSymbol() != Symbol()) continue; if ( OrderMagicNumber() != MagicNumber) continue; if(OrderType() == OP_BUY ) { NumBuyTrades++; } else if(OrderType() == OP_SELL) { NumSellTrades++; } } NumPositions = NumBuyTrades + NumSellTrades; if (type == "BUY") return (NumBuyTrades); if (type == "SELL") return (NumSellTrades); return (NumPositions); } //+------------------------------------------------------------------+ //| GetProfit | //| Return Open Profit from all open positions | //+------------------------------------------------------------------+ double GetProfit( ) { int i; double openProfit = 0; openProfit = 0; for(i=OrdersTotal()-1;i>=0;i--) { OrderSelect(i, SELECT_BY_POS ); if ( OrderSymbol() == Symbol() && OrderMagicNumber() == MagicNumber ) { openProfit = openProfit + MathRound(OrderProfit()/MarketInfo(Symbol(),MODE_TICKVALUE)*10); } } return (openProfit); } //+------------------------------------------------------------------+ //| OpenBuyOrder | //+------------------------------------------------------------------+ void OpenBuyOrder() { int err,ticket, digits; double myPrice; myPrice = MarketInfo(Symbol(), MODE_ASK); digits = MarketInfo(Symbol( ), MODE_DIGITS) ; if (digits > 0) { myPrice = NormalizeDouble( myPrice, digits); } ticket = OrderSend(Symbol(),OP_BUY,lotMM,myPrice,Slippage,0,0,setup,MagicNumber,0,Blue); if(ticket<=0) { err = GetLastError(); Print("Error opening BUY order [" + setup + "]: (" + err + ") " + ErrorDescription(err)); } } //+------------------------------------------------------------------+ //| OpenSellOrder | //+------------------------------------------------------------------+ void OpenSellOrder() { int err,ticket, digits; double myPrice; myPrice = MarketInfo(Symbol(), MODE_BID); digits = MarketInfo(Symbol( ), MODE_DIGITS) ; ticket = OrderSend(Symbol(),OP_SELL,lotMM,myPrice,Slippage,0,0,setup,MagicNumber,0,Red); if(ticket<=0) { err = GetLastError(); Print("Error opening Sell order [" + setup + "]: (" + err + ") " + ErrorDescription(err)); } } //+------------------------------------------------------------------+ //| Check Profit | //| Output comment showing progit, longs, shorts, etc | //| If profit target is reached close all open positions | //+------------------------------------------------------------------+ void CheckProfit() { double Profit; int openLongs,openShorts; Profit = GetProfit(); if ( Profit >= profitTarget ) { CloseOpenPositions(); } } //+------------------------------------------------------------------+ //| Time frame interval appropriation function | //+------------------------------------------------------------------+ int func_TimeFrame_Const2Val(int Constant ) { switch(Constant) { case 1: // M1 return(1); case 5: // M5 return(2); case 15: return(3); case 30: return(4); case 60: return(5); case 240: return(6); case 1440: return(7); case 10080: return(8); case 43200: return(9); } } //+------------------------------------------------------------------+ //| Time frame string appropriation function | //+------------------------------------------------------------------+ string func_TimeFrame_Val2String(int Value ) { switch(Value) { case 1: // M1 return("PERIOD_M1"); case 2: // M1 return("PERIOD_M5"); case 3: return("PERIOD_M15"); case 4: return("PERIOD_M30"); case 5: return("PERIOD_H1"); case 6: return("PERIOD_H4"); case 7: return("PERIOD_D1"); case 8: return("PERIOD_W1"); case 9: return("PERIOD_MN1"); default: return("undefined " + Value); } } int func_Symbol2Val(string symbol) { string mySymbol = StringSubstr(symbol,0,6); if(mySymbol=="AUDCAD") return(1); if(mySymbol=="AUDJPY") return(2); if(mySymbol=="AUDNZD") return(3); if(mySymbol=="AUDUSD") return(4); if(mySymbol=="CHFJPY") return(5); if(mySymbol=="EURAUD") return(6); if(mySymbol=="EURCAD") return(7); if(mySymbol=="EURCHF") return(8); if(mySymbol=="EURGBP") return(9); if(mySymbol=="EURJPY") return(10); if(mySymbol=="EURUSD") return(11); if(mySymbol=="GBPCHF") return(12); if(mySymbol=="GBPJPY") return(13); if(mySymbol=="GBPUSD") return(14); if(mySymbol=="NZDUSD") return(15); if(mySymbol=="USDCAD") return(16); if(mySymbol=="USDCHF") return(17); if(mySymbol=="USDJPY") return(18); Comment("unexpected Symbol"); return(19); }