Using AI to Write ATR and Bollinger Bands Indicators in Pine Script
How to prompt an AI assistant for ATR, Bollinger Bands and Keltner Channel code in Pine Script v6, then audit it for repainting stops, removed v5 syntax and silent calculation mismatches.
Marketing
AI-written Pine Script for ATR, Bollinger Bands and Keltner Channels is only useful when the prompt defines the calculations, Pine version, and signal timing precisely. A script can compile while using the wrong Keltner ATR length or standard deviation method, and it can look correct historically while repainting on the live bar.
This guide shows how to prompt an AI assistant, audit its output, correct a Pine Script v6 squeeze indicator, and prepare confirmed alerts for automation. For broader model selection and prompting advice, start with the best AI for Pine Script guide.
What This Indicator Category Covers
Average True Range Measures Volatility
J. Welles Wilder introduced Average True Range in his 1978 book, New Concepts in Technical Trading Systems. True range is the greatest of the current high minus low, the absolute difference between the current high and prior close, or the absolute difference between the current low and prior close.1
ATR commonly uses 14 periods. After initialization, the smoothing formula is the prior ATR multiplied by 13, plus the current true range, divided by 14.1 Because the calculation measures movement magnitude, ATR indicates volatility rather than price direction.
Bollinger Bands Use Standard Deviation
Standard Bollinger Bands use a 20-period simple moving average as the middle band. The outer bands sit two standard deviations above and below it, and the standard deviation uses the same lookback as the average.2
John Bollinger specifies the population standard deviation calculation. The bands expand as volatility increases and contract as volatility decreases.3 That choice matters when comparing AI-generated code with another platform.
Keltner Channels Use ATR Width
Chester Keltner's 1960 version used a 10-day simple moving average of typical price, with a 10-day average of the high-low range added and subtracted. Linda Bradford Raschke later popularized a version using an exponential moving average and ATR.4
A commonly documented configuration is a 20-period EMA plus or minus two times a 10-period ATR.4 StockCharts describes Keltner Channels as smoother than Bollinger Bands, because Bollinger Band width depends on the more volatile standard deviation.4
Squeeze Indicators Compare Band Width
A squeeze indicator compares Bollinger Band width with Keltner Channel width to identify volatility contraction. It does not establish the direction of a later move. Bollinger's dedicated width tool is BandWidth, which is separate from the bands themselves.2
Writing A Precise AI Prompt
Pin The Pine Script Version
Put //@version=6 at the start of the request. Tell the assistant not to use retired parameters or v5 behaviors, and require a complete indicator that compiles without manual adaptation.
Name Exact Inputs And Defaults
Specify every period and multiplier instead of asking for a generic volatility indicator. A practical prompt should define:
- ATR length: 14
- Bollinger length and multiplier: 20 and 2
- Keltner basis length, multiplier, and ATR length: 20, 2, and 10
- Population or sample standard deviation
- User-adjustable input calls for every setting
These details prevent an assistant from silently substituting its preferred defaults. They also make visual comparisons against platform indicators more meaningful.
Specify Confirmed-Bar Conditions
Ask for confirmed-bar logic explicitly. Require alerts to wait for barstate.isconfirmed, or reference prior values such as low[1]. Name the exact condition to evaluate, such as a confirmed squeeze transition or a crossover that remains valid at the close.
Request Valid Plots And Alerts
Require every plot() to use a linewidth of at least 1. Request color.new() for transparency and named alertcondition() calls whose titles and messages identify the event.
Worked Example: Prompt To Code
The Prompt Sent To AI
//@version=6
Create a complete overlay indicator that compiles as written.
Plot Bollinger Bands using a 20-period SMA, multiplier 2, and population standard deviation.
Plot a Keltner Channel using a 20-period EMA, multiplier 2, and a separate 10-period ATR.
Make every setting user-adjustable with typed input calls.
Define squeeze-on when confirmed Bollinger Band width is no greater than confirmed Keltner Channel width.
Only update the squeeze state after the bar closes.
Add one alertcondition() that fires when the confirmed squeeze state changes.
Use color.new() for transparency. Do not use transp.
Set every plot linewidth to 1 or greater.
What The First Draft Got Wrong
A typical first draft from a prompt like this still contains defects such as these:
- A
transpargument remained in a plot call. - One plot used
linewidth = 0. - The squeeze flag used values from the open realtime bar without confirmation.
The first two issues prevent successful v6 compilation. The third is more subtle because the script can compile while producing alerts that disappear or change before the bar closes.
The Corrected V6 Code
//@version=6
indicator("Confirmed BB KC Squeeze", overlay = true)
int bbLength = input.int(20, "BB Length", minval = 1)
float bbMultiplier = input.float(2.0, "BB Multiplier", minval = 0.1)
int kcLength = input.int(20, "KC EMA Length", minval = 1)
float kcMultiplier = input.float(2.0, "KC Multiplier", minval = 0.1)
int kcAtrLength = input.int(10, "KC ATR Length", minval = 1)
float bbBasis = ta.sma(close, bbLength)
float bbDeviation = ta.stdev(close, bbLength, true) * bbMultiplier
float bbUpper = bbBasis + bbDeviation
float bbLower = bbBasis - bbDeviation
float kcBasis = ta.ema(close, kcLength)
float kcAtr = ta.atr(kcAtrLength)
float kcUpper = kcBasis + kcMultiplier * kcAtr
float kcLower = kcBasis - kcMultiplier * kcAtr
float bbWidth = bbUpper - bbLower
float kcWidth = kcUpper - kcLower
var bool squeezeOn = false
if barstate.isconfirmed
squeezeOn := bbWidth <= kcWidth
bool squeezeChanged = barstate.isconfirmed and squeezeOn != squeezeOn[1]
plot(bbBasis, "BB Basis", color = color.blue, linewidth = 1)
plot(bbUpper, "BB Upper", color = color.new(color.blue, 20), linewidth = 1)
plot(bbLower, "BB Lower", color = color.new(color.blue, 20), linewidth = 1)
plot(kcBasis, "KC Basis", color = color.orange, linewidth = 1)
plot(kcUpper, "KC Upper", color = color.new(color.orange, 20), linewidth = 1)
plot(kcLower, "KC Lower", color = color.new(color.orange, 20), linewidth = 1)
bgcolor(squeezeOn ? color.new(color.purple, 88) : na)
alertcondition(squeezeChanged, "Squeeze State Changed", "Confirmed squeeze state changed")
The channel plots can still move while the realtime bar develops, but squeezeOn only commits its new state when the bar is confirmed. The alert therefore follows confirmed state transitions.
Repainting Risks In Volatility Stops
Why Live Bar Values Move
On a realtime bar, only the open is fixed. The high, low, and close can change until the bar closes.5 A stop calculated from the current low can therefore move lower during the bar. Historical bars only retain finalized OHLC data, creating different historical and realtime behavior.
Fix With Confirmed Bar Values
Use a prior closed value such as low[1], a prior ATR, or a condition gated by barstate.isconfirmed. TradingView documents both preceding-bar references and confirmed-bar checks as ways to prevent this form of repainting.5
Confirmation delays the signal relative to intrabar logic. That delay is the unavoidable tradeoff for making realtime alerts consistent with finalized historical bars.
When Repainting Is Acceptable
Repainting is not automatically a defect. Common indicators fluctuate on an open bar and become fixed at its close. The important questions are whether alerts wait for confirmation, whether markers move after appearing, and whether the script draws information into the past.5
Pine V6 Syntax Changes To Check
Transp Parameter Is Removed
Pine v6 removed the transp parameter from applicable visual functions, including bgcolor(), fill(), plot(), plotarrow(), plotchar(), and plotshape(). Apply transparency with color.new(color, transparency) instead.6
Linewidth Needs A Minimum Value
In v6, a linewidth must be at least 1. Search every generated plot call because one invalid value is enough to stop compilation.6
Bool Values Can't Be NA
Pine v6 bool values are limited to true or false. They cannot be na, and na(), nz(), and fixnan() no longer accept bool arguments. A bool-producing if or switch with no matching branch returns false.6
Numbers are no longer implicitly converted to bool conditions. With the example above, writing if kcAtr fails because the condition is a float, not a bool. Use an explicit comparison such as if kcAtr > 0, or apply bool() when that conversion reflects the intended logic.7
Calculation Mismatches Without Compile Errors
ta.kc() Versus Platform Defaults
StockCharts documents its Keltner default as a 20-period EMA, multiplier 2, and a separately set 10-period ATR.4 Pine's built-in ta.kc() does not reproduce that: it builds the band width from an EMA of true range over the same length as the basis, so ta.kc(close, 20, 2) uses a 20-period range average rather than a Wilder-smoothed 10-period ATR. When you want the 20, 2 and 10 configuration, calculate the EMA and ta.atr() components directly, as the corrected code does.
Population Versus Sample Deviation
Population and sample standard deviation both produce valid code, but they do not produce identical bands. Bollinger's documented method uses population standard deviation.3 In Pine, make that choice explicit rather than trusting an AI assistant's unstated assumption.
Verifying Defaults Match Documentation
Audit the numerical configuration before inspecting signals:
- ATR: 14 periods
- Bollinger Bands: 20-period SMA and multiplier 2
- Keltner Channel: 20-period EMA, multiplier 2, and 10-period ATR
- Bollinger deviation: population calculation when matching Bollinger's method
A one-parameter difference changes every subsequent band, squeeze transition, stop level, and alert without producing a compiler error.
A Review Checklist For This Category
Confirm Compile-Readiness First
Verify //@version=6, remove every transp argument, and set linewidths to 1 or greater. Search conditional statements for numeric expressions used where bool values are required.
Confirm Calculation Fidelity Next
Check the standard deviation method, basis type, lookback periods, and multipliers. Confirm that the Keltner ATR length is independent from the EMA length when the intended configuration is 20, 2, and 10.
Confirm Signal Timing Last
Inspect every stop and alert condition for current-bar high, low, or close. Then confirm that alerts are gated by a closed bar and cannot fire repeatedly as the live condition changes.
From Indicator To Automated Alert
Add Alert Conditions To Script
Tie alertcondition() or alert() to the reviewed confirmed-bar logic. Use event-specific names such as squeeze-on, squeeze-off, or band-touch. A generic title such as “signal” makes webhook troubleshooting harder.
Sending The Alert To A Broker
A TradersPost signal is JSON sent to a webhook URL. It can include ticker, action, quantity, and optional order instructions. Strategy subscription settings are then applied, and the Allow signal override controls determine whether incoming values such as quantity are used or replaced by fixed subscription settings.
Verify Signals Before Trading Live
Use the TradingView Alert Log as the record of alerts that actually fired. Chart markers show where a condition was true on finalized bars, not which alerts were delivered. Compare alert timestamps and prices with the chart, then compare them with the signals TradersPost received for the strategy. A chart marker without a matching alert can indicate repainting or incorrect alert configuration.
Bottom Line
- Pin Pine Script v6 and request complete, compile-ready code.
- Define ATR, Bollinger, and Keltner parameters explicitly.
- Audit calculation choices even when the script compiles.
- Gate alerts with confirmed-bar logic before automation.
- Compare the TradingView Alert Log with received webhook signals.
The same audit-first process applies to trend and moving average indicators, momentum and oscillator indicators, and volume and VWAP indicators. Return to the best AI for Pine Script guide for a broader workflow.
After reviewing and correcting the indicator, connect its confirmed alert to a broker through a TradersPost webhook. Start with paper trading, compare every alert with the received signal, and move to live execution only after the timing and payload behave as intended.
Frequently Asked Questions
Why Doesn't ATR Show Direction?
ATR measures movement magnitude rather than direction. True range uses positive distances between the high, low, and prior close, so rising ATR can accompany either upward or downward price movement.
Why Do Bollinger Bands Differ?
Check the moving average period, standard deviation lookback, multiplier, and deviation method. Bollinger's method uses a 20-period SMA, multiplier 2, and population standard deviation. A sample calculation produces slightly different widths.
Why Doesn't My Keltner Match?
The commonly documented configuration pairs a 20-period EMA with a separate 10-period ATR and multiplier 2. Code that ties the ATR period to the basis length will calculate different channel widths.
Why Did V6 Compilation Fail?
Common causes include a retired transp argument, linewidth below 1, bool variables assigned na, or numeric values used directly as conditions. Replace numeric conditions with explicit comparisons or an intentional bool() conversion.
Is Repainting Always Unusable?
No. Indicators commonly fluctuate on an open realtime bar. Ask whether alerts wait for the close, whether markers relocate, and whether the script draws information into the past. Those specific behaviors determine whether repainting is acceptable for your workflow.
References
1 Average True Range and Average True Range Percent
2 Bollinger Bands
3 What Are Bollinger Bands?
4 Keltner Channels
5 Repainting
6 To Pine Script Version 6
7 CE10101: Conditions Must Evaluate To Bool