This script is designed as a sophisticated technical analysis tool for the MetaTrader platform. It combines momentum oscillators, trend-following logic, and dynamic risk management to provide visual cues on a price chart.
Core Logic Overview
The indicator functions by processing three primary layers of data: Trend Analysis, Momentum Filtering, and Dynamic Trailing Stops.
1. Multi-Layered Signal Filtering
The script evaluates market conditions using two major technical indicators: the RSI (Relative Strength Index) and the MACD (Moving Average Convergence Divergence). It doesn't just look at these in isolation; it offers a highly customizable "logic gate" system to determine whether a trend is valid:
- Momentum Analysis: The script can monitor RSI levels, direction, historical highs/lows, and even the speed of momentum (acceleration).
- Trend Confirmation: It uses the MACD to identify long-term trends, checking for signal line intersections, histogram movements, and price direction.
- Combined Logic: By enabling various "Use" switches, a user can require multiple conditions to be met simultaneously—for example, requiring the market to show both an RSI upward acceleration and a positive MACD trend before highlighting a potential move.
2. Dynamic Price Body Tracking
When the specific buy or sell conditions defined above are met, the script identifies the "body" of the price candle. It captures the high and low extremes of these candles to establish a baseline for where the current price action is moving. This provides a visual representation of the "active zone" of the market.
3. Intelligent Trailing Stop System
One of the most complex parts of this script is its Trailing Stop logic. Instead of using a fixed profit target, it calculates a "moving floor" (for long positions) or a "moving ceiling" (for short positions) that adjusts in real-time based on market volatility:
- Volatility Adaptation: It utilizes the ATR (Average True Range) to measure how much the market is currently swinging. This ensures the trailing stop stays wide enough during volatile periods and tightens during calm periods.
- Customizable Calculation Methods: The script offers six different mathematical ways to anchor this trailing stop, ranging from simple moving averages and closing prices to complex weighted median calculations (such as specialized median formulas).
- Protection Mechanisms: It includes logic to ensure the stop loss only moves in your favor (it won't move backward) and can be capped at a maximum distance to prevent it from becoming too wide during extreme market outliers.
Summary of User Experience
For a visitor watching the chart, this script acts as a comprehensive "trend-following" assistant. It filters out "noise" by requiring complex agreement between RSI and MACD indicators before highlighting a move. Once a move is confirmed, it automatically calculates and draws a dynamic safety line (the Trailing Stop) that follows the price action, attempting to lock in profits while protecting against sudden reversals.
#property copyright "Max Berilo"
//----
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_color1 Red
#property indicator_color2 LimeGreen
#property indicator_color3 Black
#property indicator_color4 Red
#property indicator_color5 Green
#property indicator_width1 2
#property indicator_width2 2
#property indicator_width3 0
#property indicator_width4 1
#property indicator_width5 1
//---- input parameters
extern bool ShowBody = True;
extern bool UseRSI = True;
extern bool UseRSIaccel = True;
extern bool UseRSIvalue = False;
extern bool UseRSIdir = True;
extern bool UseRSIhist = True;
extern bool UseRSIisect = True;
extern bool UseRSIsign = False;
extern int RSIperiod = 14;
extern int RSIfast = 12;
extern int RSIslow = 26;
extern int RSIsignal = 9;
extern int RSIbuyThreshold = 40;
extern int RSIsellThreshold = 60;
extern bool UseMACD = True;
extern bool UseMACDaccel = True;
extern bool UseMACDvalue = False;
extern bool UseMACDdir = True;
extern bool UseMACDhist = False;
extern bool UseMACDisect = False;
extern bool UseMACDsign = False;
extern int FastMA = 12;
extern int SlowMA = 26;
extern int SignalMA = 9;
//----
extern bool ShowTrail = True;
extern string TrlComment = "SATL-1,FATL-2,EMA(HLC/3)-3,(HLC/3)-4,EMA(C)-5,C-6";
extern int TrlMethod = 5;
extern int TrlPeriod = 5;
extern double TrlInitMul = 1.0;
extern double TrlMul = 2.0;
extern int TrlAtrPer = 21;
extern int TrlTrap = 0;
extern bool TrlUseMax = False;
extern int TrlMaxTrap = 45;
//---- buffers
double ExtMap1[];
double ExtMap2[];
double TrlBegin[];
double TrlStopDn[];
double TrlStopUp[];
double RSI[];
double RSImacd[];
double MACD[];
//---- defines
int nFATL = 39;
int nSATL = 65;
//---- static parameters
double Spread;
static int nDrawBegin;
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//----
IndicatorBuffers(8);
SetIndexStyle(0, DRAW_HISTOGRAM, EMPTY, 2);
SetIndexStyle(1, DRAW_HISTOGRAM, EMPTY, 2);
SetIndexStyle(2, DRAW_ARROW);
SetIndexStyle(3, DRAW_LINE);
SetIndexStyle(4, DRAW_LINE);
SetIndexArrow(2, 159);
SetIndexBuffer(0, ExtMap1);
SetIndexBuffer(1, ExtMap2);
SetIndexBuffer(2, TrlBegin);
SetIndexBuffer(3, TrlStopDn);
SetIndexBuffer(4, TrlStopUp);
SetIndexBuffer(5, RSI);
SetIndexBuffer(6, RSImacd);
SetIndexBuffer(7, MACD);
//----
nDrawBegin = TrlPeriod + TrlAtrPer;
if(TrlMethod == 1) {
nDrawBegin += nSATL;
}
SetIndexDrawBegin(2, nDrawBegin);
SetIndexDrawBegin(3, nDrawBegin);
SetIndexDrawBegin(4, nDrawBegin);
//---- labels
string short_name = "Simple";
SetIndexLabel(0, short_name);
SetIndexLabel(1, short_name);
SetIndexLabel(2, "TrlBegin");
SetIndexLabel(3, "TrlStopDn");
SetIndexLabel(4, "TrlStopUp");
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator function |
//+------------------------------------------------------------------+
double CalcTrailStop(int shift, bool uptrend, bool initial)
{
double res, atr, sl = TrlTrap;
if(!initial) {
shift++;
}
atr = iATR(NULL, 0, TrlAtrPer, shift) / Point;
if(initial) {
sl += TrlInitMul * atr;
} else {
sl += TrlMul * atr;
}
if(TrlUseMax && sl > TrlMaxTrap) {
sl = TrlMaxTrap;
}
switch(TrlMethod) {
case 1:
res = CalcSATLonMedian(shift);
break;
case 2:
res = CalcFATLonMedian(shift);
break;
case 3:
res = iMA(NULL, 0, TrlPeriod, 0, MODE_EMA, PRICE_TYPICAL, shift);
break;
case 4:
res = (High[shift] + Low[shift] + Close[shift]) / 3.0;
break;
case 5:
res = iMA(NULL, 0, TrlPeriod, 0, MODE_EMA, PRICE_CLOSE, shift);
break;
case 6:
default:
res = Close[shift];
break;
}
if(uptrend) {
res -= sl * Point;
} else {
res += (sl + Spread) * Point;
}
res = NormalizeDouble(res, Digits);
return(res);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int limit, shift, counted_bars = IndicatorCounted();
double val1, val2, ma, signal, prevsign, atr;
bool buy, sell, bRSIbuy, bRSIsell, bMACDbuy, bMACDsell;
//----
double StopLoss;
bool TrlLong, TrlPrevLong, TrlShort, TrlPrevShort;
//----
Spread = MarketInfo(Symbol(), MODE_SPREAD);
if(!ShowTrail) {
SetIndexDrawBegin(2, Bars);
SetIndexDrawBegin(3, Bars);
SetIndexDrawBegin(4, Bars);
}
//---- last counted bar will be recounted
if(Bars <= RSIperiod) return(0);
if(counted_bars > 0) {
counted_bars--;
} else {
ArrayInitialize(TrlBegin, EMPTY_VALUE);
ArrayInitialize(TrlStopDn, EMPTY_VALUE);
ArrayInitialize(TrlStopUp, EMPTY_VALUE);
}
limit = Bars - counted_bars - 1;
//----
for(shift = limit; shift >= 0; shift--) {
if(UseRSI) {
RSI[shift] = iRSI(NULL, 0, RSIperiod, PRICE_CLOSE, shift);
} else {
RSI[shift] = 0;
}
if(UseMACD) {
MACD[shift] = iMACD(NULL, 0, FastMA, SlowMA, SignalMA, PRICE_CLOSE, MODE_MAIN, shift);
} else {
MACD[shift] = 0;
}
}
//----
for(shift = limit; UseRSI && (shift >= 0); shift--) {
if(shift < Bars - (RSIperiod + RSIslow)) {
RSImacd[shift] = iMAOnArray(RSI,0,RSIfast,0,MODE_EMA,shift)-iMAOnArray(RSI,0,RSIslow,0,MODE_EMA,shift);
} else {
RSImacd[shift] = 0;
}
}
//----
for(shift = limit; shift >= 0; shift--) {
val1 = EMPTY_VALUE; val2 = EMPTY_VALUE;
if(UseRSI) {
bRSIbuy = False; bRSIsell = False;
if(shift < Bars - (RSIperiod+RSIslow+2)) {
if(UseRSIaccel) {
prevsign = iMAOnArray(RSImacd,0,RSIsignal,0,MODE_EMA,shift+1);
signal = iMAOnArray(RSImacd,0,RSIsignal,0,MODE_EMA,shift);
bRSIbuy = (RSImacd[shift] - signal) > (RSImacd[shift+1] - prevsign);
bRSIsell = (RSImacd[shift] - signal) < (RSImacd[shift+1] - prevsign);
}
if(UseRSIvalue) {
buy = RSI[shift] > RSIbuyThreshold;
sell = RSI[shift] < RSIsellThreshold;
if(UseRSIaccel) {
bRSIbuy = bRSIbuy && buy;
bRSIsell = bRSIsell && sell;
} else {
bRSIbuy = buy;
bRSIsell = sell;
}
}
if(UseRSIdir) {
buy = (RSImacd[shift] > RSImacd[shift+1]);
sell = (RSImacd[shift] < RSImacd[shift+1]);
if(UseRSIaccel || UseRSIvalue) {
bRSIbuy = bRSIbuy && buy;
bRSIsell = bRSIsell && sell;
} else {
bRSIbuy = buy;
bRSIsell = sell;
}
}
if(UseRSIhist) {
buy = RSImacd[shift] > RSImacd[shift+2];
sell = RSImacd[shift] < RSImacd[shift+2];
if(UseRSIaccel || UseRSIvalue || UseRSIdir) {
bRSIbuy = bRSIbuy && buy;
bRSIsell = bRSIsell && sell;
} else {
bRSIbuy = buy;
bRSIsell = sell;
}
}
if(UseRSIisect) {
if(!UseRSIaccel) {
signal = iMAOnArray(RSImacd,0,RSIsignal,0,MODE_EMA,shift);
}
buy = RSImacd[shift] > signal;
sell = RSImacd[shift] < signal;
if(UseRSIaccel || UseRSIvalue || UseRSIdir || UseRSIhist) {
bRSIbuy = bRSIbuy && buy;
bRSIsell = bRSIsell && sell;
} else {
bRSIbuy = buy;
bRSIsell = sell;
}
}
if(UseRSIsign) {
bRSIbuy = bRSIbuy && (RSImacd[shift] >= 0);
bRSIsell = bRSIsell && (RSImacd[shift] <= 0);
if(UseRSIaccel || UseRSIvalue || UseRSIdir || UseRSIhist || UseRSIisect) {
bRSIbuy = bRSIbuy && buy;
bRSIsell = bRSIsell && sell;
} else {
bRSIbuy = buy;
bRSIsell = sell;
}
}
}
}
if(UseMACD) {
bMACDbuy = False; bMACDsell = False;
if(shift <= Bars - (SlowMA+2)) {
if(UseMACDaccel) {
prevsign = iMAOnArray(MACD,0,SignalMA,0,MODE_EMA,shift+1);
signal = iMAOnArray(MACD,0,SignalMA,0,MODE_EMA,shift);
bMACDbuy = (MACD[shift] - signal) > (MACD[shift+1] - prevsign);
bMACDsell = (MACD[shift] - signal) < (MACD[shift+1] - prevsign);
}
if(UseMACDvalue) {
atr = iATR(NULL, 0, 21, shift);
buy = MACD[shift] > -atr;
sell = MACD[shift] < atr;
if(UseMACDaccel) {
bMACDbuy = bMACDbuy && buy;
bMACDsell = bMACDsell && sell;
} else {
bMACDbuy = buy;
bMACDsell = sell;
}
}
if(UseMACDdir) {
buy = (MACD[shift] > MACD[shift+1]);
sell = (MACD[shift] < MACD[shift+1]);
if(UseMACDaccel || UseMACDvalue) {
bMACDbuy = bMACDbuy && buy;
bMACDsell = bMACDsell && sell;
} else {
bMACDbuy = buy;
bMACDsell = sell;
}
}
if(UseMACDhist) {
buy = MACD[shift] > MACD[shift+2];
sell = MACD[shift] < MACD[shift+2];
if(UseMACDaccel || UseMACDvalue || UseMACDdir) {
bMACDbuy = bMACDbuy && buy;
bMACDsell = bMACDsell && sell;
} else {
bMACDbuy = buy;
bMACDsell = sell;
}
}
if(UseMACDisect) {
if(!UseMACDaccel) {
signal = iMAOnArray(MACD,0,SignalMA,0,MODE_EMA,shift);
}
buy = MACD[shift] > signal;
sell = MACD[shift] < signal;
if(UseMACDaccel || UseMACDvalue || UseMACDdir || UseMACDhist) {
bMACDbuy = bMACDbuy && buy;
bMACDsell = bMACDsell && sell;
} else {
bMACDbuy = buy;
bMACDsell = sell;
}
}
if(UseMACDsign) {
buy = MACD[shift] >= 0;
sell = MACD[shift] <= 0;
if(UseMACDaccel || UseMACDvalue || UseMACDdir || UseMACDhist || UseMACDsign) {
bMACDbuy = bMACDbuy && buy;
bMACDsell = bMACDsell && sell;
} else {
bMACDbuy = buy;
bMACDsell = sell;
}
}
}
}
//----
if((!UseRSI || (UseRSI && bRSIbuy)) && (!UseMACD || (UseMACD && bMACDbuy))) {
if(ShowBody) {
if(Open[shift] < Close[shift]) {
val1 = Open[shift];
val2 = Close[shift];
} else {
val2 = Open[shift];
val1 = Close[shift];
}
}
TrlLong = True;
} else {
TrlLong = False;
}
if((!UseRSI || (UseRSI && bRSIsell)) && (!UseMACD || (UseMACD && bMACDsell))) {
if(ShowBody) {
if(Open[shift] > Close[shift]) {
val1 = Open[shift];
val2 = Close[shift];
} else {
val2 = Open[shift];
val1 = Close[shift];
}
}
TrlShort = True;
} else {
TrlShort = False;
}
ExtMap1[shift] = val1;
ExtMap2[shift] = val2;
//----
if(shift < Bars - nDrawBegin) {
TrlPrevLong = (TrlStopUp[shift+1] != EMPTY_VALUE) &&
((TrlStopUp[shift+1] < Low[shift+1]) || (TrlStopUp[shift+1] == TrlBegin[shift+1]));
TrlPrevShort = (TrlStopDn[shift+1] != EMPTY_VALUE) &&
((TrlStopDn[shift+1] > High[shift+1] + Spread * Point) || (TrlStopDn[shift+1] == TrlBegin[shift+1]));
if(TrlLong || TrlPrevLong) {
StopLoss = CalcTrailStop(shift, true, !TrlPrevLong);
if(TrlPrevLong && StopLoss < TrlStopUp[shift+1]) {
TrlStopUp[shift] = TrlStopUp[shift+1];
} else {
TrlStopUp[shift] = StopLoss;
if(!TrlPrevLong) {
TrlBegin[shift] = StopLoss;
}
}
} else {
TrlStopUp[shift] = EMPTY_VALUE;
}
if(TrlShort || TrlPrevShort) {
StopLoss = CalcTrailStop(shift, false, !TrlPrevShort);
if(TrlPrevShort && StopLoss > TrlStopDn[shift+1]) {
TrlStopDn[shift] = TrlStopDn[shift+1];
} else {
TrlStopDn[shift] = StopLoss;
if(!TrlPrevShort) {
TrlBegin[shift] = StopLoss;
}
}
} else {
TrlStopDn[shift] = EMPTY_VALUE;
}
if((TrlBegin[shift] != EMPTY_VALUE)&&(TrlBegin[shift] != TrlStopUp[shift])&&(TrlBegin[shift] != TrlStopDn[shift])) {
TrlBegin[shift] = EMPTY_VALUE;
}
}
}
//----
return(0);
}
//----
double ATLprice(int i)
{
return((High[i] + Low[i]) / 2.0);
}
//----
double CalcFATLonMedian(int i)
{
double res =
0.4360409450*ATLprice(i+0) +0.3658689069*ATLprice(i+1) +0.2460452079*ATLprice(i+2) +0.1104506886*ATLprice(i+3)
-0.0054034585*ATLprice(i+4) -0.0760367731*ATLprice(i+5) -0.0933058722*ATLprice(i+6) -0.0670110374*ATLprice(i+7) -0.0190795053*ATLprice(i+8)
+0.0259609206*ATLprice(i+9) +0.0502044896*ATLprice(i+10)+0.0477818607*ATLprice(i+11)+0.0249252327*ATLprice(i+12)
-0.0047706151*ATLprice(i+13)-0.0272432537*ATLprice(i+14)-0.0338917071*ATLprice(i+15)-0.0244141482*ATLprice(i+16)-0.0055774838*ATLprice(i+17)
+0.0128149838*ATLprice(i+18)+0.0226522218*ATLprice(i+19)+0.0208778257*ATLprice(i+20)+0.0100299086*ATLprice(i+21)
-0.0036771622*ATLprice(i+22)-0.0136744850*ATLprice(i+23)-0.0160483392*ATLprice(i+24)-0.0108597376*ATLprice(i+25)-0.0016060704*ATLprice(i+26)
+0.0069480557*ATLprice(i+27)+0.0110573605*ATLprice(i+28)+0.0095711419*ATLprice(i+29)+0.0040444064*ATLprice(i+30)
-0.0023824623*ATLprice(i+31)-0.0067093714*ATLprice(i+32)-0.0072003400*ATLprice(i+33)-0.0047717710*ATLprice(i+34)
+0.0005541115*ATLprice(i+35)+0.0007860160*ATLprice(i+36)+0.0130129076*ATLprice(i+37)+0.0040364019*ATLprice(i+38);
return(res);
}
//----
double CalcSATLonMedian(int i)
{
double res = 0.0982862174*ATLprice(i+0)
+0.0975682269*ATLprice(i+1) +0.0961401078*ATLprice(i+2) +0.0940230544*ATLprice(i+3) +0.0912437090*ATLprice(i+4) +0.0878391006*ATLprice(i+5)
+0.0838544303*ATLprice(i+6) +0.0793406350*ATLprice(i+7) +0.0743569346*ATLprice(i+8) +0.0689666682*ATLprice(i+9) +0.0632381578*ATLprice(i+10)
+0.0572428925*ATLprice(i+11)+0.0510534242*ATLprice(i+12)+0.0447468229*ATLprice(i+13)+0.0383959950*ATLprice(i+14)+0.0320735368*ATLprice(i+15)
+0.0258537721*ATLprice(i+16)+0.0198005183*ATLprice(i+17)+0.0139807863*ATLprice(i+18)+0.0084512448*ATLprice(i+19)+0.0032639979*ATLprice(i+20)
-0.0015350359*ATLprice(i+21)-0.0059060082*ATLprice(i+22)-0.0098190256*ATLprice(i+23)-0.0132507215*ATLprice(i+24)-0.0161875265*ATLprice(i+25)
-0.0186164872*ATLprice(i+26)-0.0205446727*ATLprice(i+27)-0.0219739146*ATLprice(i+28)-0.0229204861*ATLprice(i+29)-0.0234080863*ATLprice(i+30)
-0.0234566315*ATLprice(i+31)-0.0231017777*ATLprice(i+32)-0.0223796900*ATLprice(i+33)-0.0213300463*ATLprice(i+34)-0.0199924534*ATLprice(i+35)
-0.0184126992*ATLprice(i+36)-0.0166377699*ATLprice(i+37)-0.0147139428*ATLprice(i+38)-0.0126796776*ATLprice(i+39)-0.0105938331*ATLprice(i+40)
-0.0084736770*ATLprice(i+41)-0.0063841850*ATLprice(i+42)-0.0043466731*ATLprice(i+43)-0.0023956944*ATLprice(i+44)-0.0005535180*ATLprice(i+45)
+0.0011421469*ATLprice(i+46)+0.0026845693*ATLprice(i+47)+0.0040471369*ATLprice(i+48)+0.0052380201*ATLprice(i+49)+0.0062194591*ATLprice(i+50)
+0.0070340085*ATLprice(i+51)+0.0076266453*ATLprice(i+52)+0.0080376628*ATLprice(i+53)+0.0083037666*ATLprice(i+54)+0.0083694798*ATLprice(i+55)
+0.0082901022*ATLprice(i+56)+0.0080741359*ATLprice(i+57)+0.0077543820*ATLprice(i+58)+0.0073260526*ATLprice(i+59)+0.0068163569*ATLprice(i+60)
+0.0062325477*ATLprice(i+61)+0.0056078229*ATLprice(i+62)+0.0049516078*ATLprice(i+63)+0.0161380976*ATLprice(i+64);
return(res);
}
//+------------------------------------------------------------------+
Comments