Last active
September 11, 2022 02:51
-
-
Save currencysecrets/6622644 to your computer and use it in GitHub Desktop.
ATR Trailing Stop method - these are the ATR trailing stop functions I use to calculate my automatic stops. Aspects within this code that need to be added are the checking of the Trading Content being free and (optional) better error reporting.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//+------------------------------------------------------------------+ | |
//| calculate-atr-trailing-stop.mq4 | |
//| Copyright 2013, Currency Secrets | |
//| http://www.currencysecrets.com | |
//+------------------------------------------------------------------+ | |
#property copyright "Copyright 2013, Currency Secrets" | |
#property link "http://www.currencysecrets.com" | |
//--- input parameters | |
extern int extLookBack = 50; // bars to look back for the ATR indicator | |
extern double extATRMult = 2; // ATR multiplier | |
extern int extSlippage = 10; // slippage allowed for trades | |
int start() { | |
string sym = Symbol(); | |
int per = PERIOD_H4; | |
// entry logic here ... | |
// ... | |
// end entry logic! | |
// checking open trades here on every tick... | |
checkOpenTrades( per, sym ); | |
// end check of open trades on every tick! | |
return(0); | |
} | |
void checkOpenTrades( int per, string sym = "" ) { | |
if ( sym == "" ) { sym = Symbol(); } | |
int t = OrdersTotal(); | |
double stop, trail; | |
for ( int i = 0; i < t; i += 1 ) { | |
if ( OrderSelect( i, SELECT_BY_POS, MODE_TRADES) ) { | |
if ( OrderSymbol() == sym ) { | |
stop = OrderStopLoss(); // current stop loss of order | |
if ( OrderType() == OP_BUY ) { | |
// we have an active long position | |
// ideally this is the best and only way to go... | |
trail = Ask - getStopDist( per ); | |
// ... however, we will also check this method too... | |
trail = MathMax( trail, getTrailingStop( per, OrderOpenTime(), true, sym ) ); | |
// check if there's a difference of a least one point in our favour - otherwise don't worry about it | |
if ( trail - stop > Point ) { | |
// check trade context... | |
// ... | |
// end check trade content | |
// check stop price isn't too close to market | |
if ( Bid - trail > MarketInfo( sym, MODE_STOPLEVEL ) * Point ) { | |
// modify active order's stop price | |
if ( OrderModify( OrderTicket(), OrderOpenPrice(), trail, OrderTakeProfit(), 0 ) == false ) { | |
// ALERT ERROR! | |
Print( "ERR in MOD LONG trade for " + sym + " = " + GetLastError() ); | |
} | |
} else { | |
// otherwise may want to check to see if you can exit at market if too close | |
if ( trail > Bid ) { | |
if ( OrderClose( OrderTicket(), OrderLots(), Bid, extSlippage ) == false ) { | |
Print( "ERR in CLOSE LONG at market for " + sym + " = " + GetLastError() ); | |
} | |
} | |
} | |
} | |
} | |
if ( OrderType() == OP_SELL ) { | |
// we have an active short position | |
// ideally this is the best and only way to go... | |
trail = Bid + getStopDist( per ); | |
// ... however, we will check this method too... | |
trail = MathMin( trail, getTrailingStop( per, OrderOpenTime(), false, sym ) ); | |
// check if there's a difference of a least one point in our favour - otherwise don't worry about it | |
if ( stop - trail > Point ) { | |
// check trade context... | |
// ... | |
// end check trade context | |
// check stop price isn't too close to market | |
if ( trail - Ask > MarketInfo( sym, MODE_STOPLEVEL ) * Point ) { | |
// modify active order's stop price | |
if ( OrderModify( OrderTicket(), OrderOpenPrice(), trail, OrderTakeProfit(), 0 ) == false ) { | |
// ALERT ERROR! | |
Print( "ERR in MOD SHORT trade for " + sym + " = " + GetLastError() ); | |
} | |
} else { | |
// otherwise may want to see if you can exit at market if too close | |
if ( Ask > trail ) { | |
if ( OrderClose( OrderTicket(), OrderLots(), Ask, extSlippage ) == false ) { | |
Print( "ERR in CLOSE SHORT at market for " + sym + " = " + GetLastError() ); | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
double getStopDist( int per, int bar = 1, string sym = "" ) { | |
if ( sym == "" ) { sym = Symbol(); } | |
return( N( extATRMult * iATR( sym, per, extLookBack, bar ) ) ); | |
} | |
double getTrailingStop( int per, datetime openTime, bool isLong, string sym = "" ) { | |
if ( sym == "" ) { sym = Symbol(); } | |
// this function will return the trailing stop of the symbol | |
// dir = TRUE for longs; FALSE for shorts | |
double result; | |
int startBar = getOpenBar( openTime, per ); | |
if ( isLong ) { | |
result = iHigh( sym, per, startBar ) - getStopDist( per, startBar, sym ); | |
} else { | |
result = iLow( sym, per, startBar ) + getStopDist( per, startBar, sym ); | |
} | |
for ( int i = startBar; i > 0; i -= 1 ) { | |
if ( isLong ) { | |
// for LONG orders | |
// loop through the bars since opentime | |
result = MathMax( iHigh( sym, per, i ) - getStopDist( per, i, sym ), result ); | |
} else { | |
// for SHORT orders | |
result = MathMin( iLow( sym, per, i ) + getStopDist( per, i, sym ), result ); | |
} | |
} | |
return( N( result ) ); | |
} | |
int getOpenBar( datetime openTime, int per, string sym = "" ) { | |
if ( sym == "" ) { sym = Symbol(); } | |
// each bar has the opening time at the start of the bar | |
// eg if openTime is 12:01PM we will know at 4:00PM (when the | |
// bar is greater than the opening time of trade) | |
int b = iBars( sym, per ); | |
for ( int i = 0; i < b; i += 1 ) { | |
if ( openTime >= iTime( sym, per, i ) ) { | |
return( i ); | |
} | |
} | |
return( 0 ); | |
} | |
double N( double price, int num = -1 ) { | |
if ( num == -1 ) { num = Digits; } | |
return( NormalizeDouble( price, num ) ); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Is there any way to add activation only when a defined number of pips in profit? Thanks!