############################################
# ATR Trailing Stop
############################################
input agg = AggregationPeriod.DAY;
input trailType = {default modified, unmodified};
input ATRPeriod = 5;
input ATRFactor = 2.5;
input firstTrade = {default long, short};
input tsAverageType = AverageType.WILDERS;
Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor);
def HiLo = Min(high(period = agg) - low(period = agg), 1.5 * Average(high(period = agg) - low(period = agg), ATRPeriod));
def HRef = if low(period = agg) <= high(period = agg)[1]
then high(period = agg) - close(period = agg)[1]
else (high(period = agg) - close(period = agg)[1]) - 0.5 * (low(period = agg) - high(period = agg)[1]);
def LRef = if high(period = agg) >= low(period = agg)[1]
then close(period = agg)[1] - low(period = agg)
else (close(period = agg)[1] - low(period = agg)) - 0.5 * (low(period = agg)[1] - high(period = agg));
def trueRange;
switch (trailType) {
case modified:
trueRange = Max(HiLo, Max(HRef, LRef));
case unmodified:
trueRange = TrueRange(high(period = agg), close(period = agg), low(period = agg));
}
def loss = ATRFactor * MovingAverage(averageType, trueRange, ATRPeriod);
def state = {default init, long, short};
def trail;
switch (state[1]) {
case init:
if (!IsNaN(loss)) {
switch (firstTrade) {
case long:
state = state.long;
trail = close(period = agg) - loss;
case short:
state = state.short;
trail = close(period = agg) + loss;
}
} else {
state = state.init;
trail = Double.NaN;
}
case long:
if (close(period = agg) > trail[1]) {
state = state.long;
trail = Max(trail[1], close(period = agg) - loss);
} else {
state = state.short;
trail = close(period = agg) + loss;
}
case short:
if (close(period = agg) < trail[1]) {
state = state.short;
trail = Min(trail[1], close(period = agg) + loss);
} else {
state = state.long;
trail = close(period = agg) - loss;
}
}
plot tsBuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE);
plot tsSellSignal = Crosses(state == state.short, 0, CrossingDirection.ABOVE);
plot TrailingStop = trail;
TrailingStop.SetPaintingStrategy(PaintingStrategy.POINTS);
TrailingStop.DefineColor("Buy", GetColor(0));
TrailingStop.DefineColor("Sell", GetColor(1));
TrailingStop.AssignValueColor(if state == state.long
then TrailingStop.Color("Sell")
else TrailingStop.Color("Buy"));