Hey @SleepyZThe following has the horizontal lines you requested added to the bottom of the ATR trailing stop code.
How can I keep the horizontal lines extended until the price touches the line? Thank you
Hey @SleepyZThe following has the horizontal lines you requested added to the bottom of the ATR trailing stop code.
Join useThinkScript to post your question to a community of 21,000+ developers and traders.
This script is mainly an extension of 1 line, the trail. To terminate the extensions, it will require creating a seperate horizontal for each of them, requiring a lot of coding. There are other studies doing that may be of interest. Here is one https://usethinkscript.com/threads/extend-point-of-control-line-volume-profile.10893/post-109395Hey @SleepyZ
How can I keep the horizontal lines extended until the price touches the line? Thank you
#
# TD Ameritrade IP Company, Inc. (c) 2009-2023
#
input trailType = {default modified, unmodified};
input ATRPeriod = 5;
input ATRFactor = 3.5;
input firstTrade = {default long, short};
input averageType = AverageType.WILDERS;
Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor);
def HiLo = Min(high - low, 1.5 * Average(high - low, ATRPeriod));
def HRef = if low <= high[1]
then high - close[1]
else (high - close[1]) - 0.5 * (low - high[1]);
def LRef = if high >= low[1]
then close[1] - low
else (close[1] - low) - 0.5 * (low[1] - high);
def trueRange;
switch (trailType) {
case modified:
trueRange = Max(HiLo, Max(HRef, LRef));
case unmodified:
trueRange = TrueRange(high, close, low);
}
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 - loss;
case short:
state = state.short;
trail = close + loss;
}
} else {
state = state.init;
trail = Double.NaN;
}
case long:
if (close > trail[1]) {
state = state.long;
trail = Max(trail[1], close - loss);
} else {
state = state.short;
trail = close + loss;
}
case short:
if (close < trail[1]) {
state = state.short;
trail = Min(trail[1], close + loss);
} else {
state = state.long;
trail = close - loss;
}
}
def BuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE);
def SellSignal = 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"));
Default TOS ATR Trailing Stop code is shown below.
Problem
The indication will change mid-bar as price changes.
Solution
Change the study so that it does not update until AFTER the bar closes/new bar Opens.
Question
How does TOS determine that a new bar has opened?
Code:# # TD Ameritrade IP Company, Inc. (c) 2009-2023 # input trailType = {default modified, unmodified}; input ATRPeriod = 5; input ATRFactor = 3.5; input firstTrade = {default long, short}; input averageType = AverageType.WILDERS; Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor); def HiLo = Min(high - low, 1.5 * Average(high - low, ATRPeriod)); def HRef = if low <= high[1] then high - close[1] else (high - close[1]) - 0.5 * (low - high[1]); def LRef = if high >= low[1] then close[1] - low else (close[1] - low) - 0.5 * (low[1] - high); def trueRange; switch (trailType) { case modified: trueRange = Max(HiLo, Max(HRef, LRef)); case unmodified: trueRange = TrueRange(high, close, low); } 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 - loss; case short: state = state.short; trail = close + loss; } } else { state = state.init; trail = Double.NaN; } case long: if (close > trail[1]) { state = state.long; trail = Max(trail[1], close - loss); } else { state = state.short; trail = close + loss; } case short: if (close < trail[1]) { state = state.short; trail = Min(trail[1], close + loss); } else { state = state.long; trail = close - loss; } } def BuySignal = Crosses(state == state.long, 0, CrossingDirection.ABOVE); def SellSignal = 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"));
Thank you. That looks like what I want. I will test on Monday.is this what you want ?
this will plot the ATR, but not on the current bar
# atr_prev
declare lower;
def na = double.nan;
def bn = barnumber();
def lastbar = !isnan(close[0]) and isnan(close[-1]);
input length = 14;
input averageType = AverageType.WILDERS;
def ATR1 = MovingAverage(averageType, TrueRange(high, close, low), length);
plot atr = if lastbar then na else atr1;
ATR.SetDefaultColor(GetColor(8));
#
# Trend Chaser - (9-16-2023) Creator: Ricky Gaspard
# trendType: The choice between using modified or unmodified True Range depends on the specific trading strategy and the trader's preferences. The modified method may provide smoother values when there are gaps or sudden changes in price, whereas the unmodified method is simpler and more commonly used. In the provided code, you can choose between these two methods using the trendType input parameter.
# ATRPeriod: Traders often experiment with different ATR periods to tailor the indicator to their trading style and the specific assets they are analyzing. A shorter ATR period might be suitable for short-term traders looking for quick signals, while a longer ATR period might be preferred by longer-term investors looking for a more stable assessment of volatility. Changing this will tell the script how many candles you want the script to look back before calculating a decision to plot an arrow. Defaut is 2 ATRPeriod.
# ATRFactor: It's important to note that the ATRFactor parameter is a key part of risk management in trading. By adjusting this factor, traders can control the level of risk they are willing to take on each trade, helping to protect their capital and manage their overall portfolio risk. It's a good practice to test different ATRFactor values and analyze their impact on your trading strategy's performance before using them in live trading. Think of it as a stop loss. Adjusting this will affect arror placement. Changing this to 1 will plot and arrow sooner after a trend reversal is detected. Default is 1.5 ATR.
# WARNING: Just like all indicators, if a stock is channeling, squeezing or consolidating you will get multiple up and down arrows. Wait for a breakout up or down to get the larger trend run. If you are in a trend take profits as the trend takes place. Do not wait on an arrow to sell or cover all held shares.
# Important: If you change the defualt ATRPeriod and ATRFactor you will also need to go into the scan code and change those settings to match.
input trendType = {default modified, unmodified};
input ATRPeriod = 2;
input ATRFactor = 1.5;
input TradeType = {default long, short};
input averageType = AverageType.WILDERS;
Assert(ATRFactor > 0, "'atr factor' must be positive: " + ATRFactor);
def HiLo = Min(high - low, 1.5 * Average(high - low, ATRPeriod));
def HRef = if low <= high[1]
then high - close[1]
else (high - close[1]) - 0.5 * (low - high[1]);
def LRef = if high >= low[1]
then close[1] - low
else (close[1] - low) - 0.5 * (low[1] - high);
def trueRange;
switch (trendType) {
case modified:
trueRange = Max(HiLo, Max(HRef, LRef));
case unmodified:
trueRange = TrueRange(high, close, low);
}
def loss = ATRFactor * MovingAverage(averageType, trueRange, ATRPeriod);
def direction = {default init, long, short};
def trend;
switch (direction[1]) {
case init:
if (!IsNaN(loss)) {
switch (TradeType) {
case long:
direction = direction.long;
trend = close - loss;
case short:
direction = direction.short;
trend = close + loss;
}
} else {
direction = direction.init;
trend = Double.NaN;
}
case long:
if (close > trend[1]) {
direction = direction.long;
trend = Max(trend[1], close - loss);
} else {
direction = direction.short;
trend = close + loss;
}
case short:
if (close < trend[1]) {
direction = direction.short;
trend = Min(trend[1], close + loss);
} else {
direction = direction.long;
trend = close - loss;
}
}
def BuySignal = Crosses(direction == direction.long, 0, CrossingDirection.ABOVE);
def SellSignal = Crosses(direction == direction.short, 0, CrossingDirection.ABOVE);
plot ArrowUp = if BuySignal then 1 else 0;
arrowUp.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_UP);
arrowUp.SetDefaultColor(Color.YELLOW);
plot ArrowDown = if SellSignal then 1 else 0;
arrowDown.SetPaintingStrategy(PaintingStrategy.BOOLEAN_ARROW_DOWN);
arrowDown.SetDefaultColor(Color.YELLOW);
Start a new thread and receive assistance from our community.
useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.
We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.
If you are new, or just looking for guidance, here are some helpful links to get you started.