Tutorials

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.

Tom Hartman

Marketing

11 Min Read Reviewed by Tom Hartman Fact-checked by Tom Hartman
BluSky — The Future of Trading. Prop firm futures trading. Sign up at BluSky.pro.

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 transp argument 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

All In Tutorials
  • Tutorials Oct 10, 2026

    AI Pine Script Moving Average Indicators

    Learn to prompt AI for working Pine Script v6 moving average, Hull MA, and Supertrend code, catch its common bugs, and turn the result into an alert.

  • Tutorials Oct 9, 2026

    Using AI to Write a Pine Script Futures Strategy for Webhooks

    Learn to prompt AI for a Pine Script v6 futures strategy with webhook-ready alerts, and catch the alert_message, session, and contract mistakes AI makes.

  • Tutorials Oct 9, 2026

    AI Pine Script DCA Strategy: Prompts That Work

    Learn to prompt AI for working Pine Script v6 DCA, grid, and scale-in code, plus the pyramiding, exit, and trimming mistakes to catch before you deploy it.

  • Tutorials Oct 9, 2026

    How to Build an AI Pine Script Swing Trading Strategy

    Prompt AI for a Pine Script v6 swing trading strategy, catch repainting and warm-up errors in the output, then route a confirmed signal to a broker.

Start trading at scale today. Sign up for free.

Free 7-day trial

Set-up in 3 minutes

Paper account for testing

By continuing, you agree to the TradersPost Terms of Service and Privacy Policy. This site is protected by reCAPTCHA.

TradersPost operates as a non-custodial automated trading platform, enabling users to connect alerts from their preferred trading platforms to their selected brokerage or exchange accounts. It abstains from the transmission, custody, or management of customer funds, covering both traditional and cryptocurrency assets. Typically, registration requirements set by regulatory entities such as the SEC, FINRA, or FinCEN apply to entities that hold or transmit customer funds. To ensure ongoing compliance, TradersPost regularly engages with regulatory authorities to confirm its adherence to all relevant local and federal laws.

TradersPost does not provide alerts, signals, research, analysis, or trading advice of any kind. It is designed to assist traders and investors in making their own trading decisions based on their alerts. The platform does not offer recommendations regarding securities to buy or sell, nor does it provide trading or investing advice. The platform and its features, capabilities, and tools are provided 'as-is' without any warranty.

Risk Disclosure: The use of automated trading systems involves inherent risks, including the potential for significant financial loss. These systems operate based on predetermined algorithms that may not fully adapt to changing market conditions, possibly making them unsuitable for some investors. Individuals are advised to thoroughly assess their financial situation and risk tolerance before using this platform.

Testimonials appearing on this website may not be representative of other clients or customers and is not a guarantee of future performance or success.

Broker, exchange, trading platform, company names, product names, service marks, trademarks, and logos appearing on this website are the property of their respective owners and are used solely to identify supported connections and technical compatibility. TradersPost is an independent third-party platform and is not affiliated with, endorsed by, sponsored by, or authorized by any of these organizations unless expressly stated. Technical compatibility does not imply a commercial partnership, sponsorship, endorsement, or authorization. See Important Disclosures for trademark information.

© 2026 TradersPost, Inc. All rights reserved.