AI Pine Script Order Block Indicators
How to prompt an AI for Pine Script v6 order block, break of structure and fair value gap indicators, then catch the v6 and pivot-delay mistakes in the code it returns.
Marketing
An ai pine script order block indicator is only as reliable as the definitions supplied to the AI. Break of structure, change of character, order blocks, and fair value gaps are labels, not built-in Pine Script concepts. Your prompt must convert each label into conditions that can be compiled, reviewed, and tested.
The process starts with precise market structure rules, Pine Script v6 constraints, and confirmed-bar logic. It ends with compiler review, repainting checks, and paper testing. For broader prompting guidance, see our best AI for Pine Script guide.
The worked example below shows a common v6 user-defined type error, corrects it, and adds JSON alerts that can later connect the indicator to an automated trading workflow.
Market Structure and Order Blocks Defined
Dow Theory's Market Structure
"Market structure" is an old idea under a new name. Dow Theory, developed by Charles Dow, refined by William Hamilton and articulated by Robert Rhea, describes an uptrend as a series of higher highs and higher lows, and holds that once the primary trend has been identified it remains in effect until proved otherwise.1
Smart Money Concepts scripts relabel this idea as market structure. Dow and Hamilton also identified three types of price movement: primary movements, secondary movements and daily fluctuations.1 That distinction matters when an indicator claims to detect meaningful structure on every bar. A two-bar fluctuation is not a primary trend change.
SMC Terms Need Definitions
Break of structure (BOS), change of character (CHoCH), order block and fair value gap (FVG) have no single agreed definition, and what counts as a valid order block varies from trader to trader. None of them is a built-in Pine Script concept either. One author might define BOS as a close above a confirmed pivot. Another might accept a wick above the high. Order blocks might use the full opposing candle, its body, or a selected price range.
Treat each term as a name for your mechanical rule. A generic AI prompt otherwise leaves the model to choose its own interpretation.
Ambiguity Changes the Output
Without exact instructions, an AI assistant must guess the swing length, break threshold, order block candle, box boundaries, mitigation rule, and invalidation rule. Those guesses can produce code that compiles while behaving differently from what you intended.
Define these decisions before requesting code:
- Swing highs and lows, including separate left and right pivot lengths.
- Whether BOS requires a close, wick, crossover, or fixed buffer.
- Which opposing candle becomes the order block.
- Whether boxes use the candle body or full range.
- How an FVG is identified, filled, and deleted.
- Whether mitigation requires a touch, close, or full traversal.
Writing a Prompt That Compiles
Pin the Pine Version
Start the prompt with a requirement for //@version=6. TradingView's v6 migration guide lists two changes that matter here: "int" and "float" values are no longer implicitly cast to "bool", and the history-referencing operator [] can no longer be used directly on fields of user-defined types.2 AI assistants trained on older examples can reproduce either pattern. Our guide to Pine v6 breaking changes covers the rest of the list.
Also require a clean Pine Editor compilation. The same guide says the Pine Editor converter handles many v5 changes automatically, but in rare cases the converted v6 script still has compilation errors.2
Name Inputs and Conditions
Use named inputs rather than asking for configurable swings. For example, request leftBars, rightBars, orderBlockSearch, and quantity. Then state that bullish BOS means a confirmed close crossing above the latest confirmed pivot high.
Define a bullish order block as the most recent bearish candle before bullish BOS, using that candle's full high-low range. Define a bullish FVG as low > high[2] and a bearish FVG as high < low[2]. These rules may not match another trader's vocabulary, but they are auditable.
Require Confirmed-Bar Logic
Gate visual signals and alerts with barstate.isconfirmed. TradingView's repainting page calls adding and barstate.isconfirmed to a cross condition "a simple way to avoid repainting", because the condition can then only be true when the bar closes and its prices are confirmed.3
Confirmed bars do not remove pivot delay. A pivot with five right bars becomes known five bars after the bar where it formed. The prompt should require the script to disclose that delay and distinguish it from avoidable open-bar fluctuation.
Worked Example: Prompt to Corrected Code
Initial Prompt and Output
A useful prompt can be compact while remaining mechanical:
Write a Pine Script v6 overlay indicator.
Inputs:
- leftBars and rightBars for pivot detection
- orderBlockSearch for the opposing-candle search
- quantity for alert messages
Definitions:
- Bullish BOS is a confirmed close crossing above the latest confirmed pivot high.
- Bearish BOS is a confirmed close crossing below the latest confirmed pivot low.
- Compare each close with the swing levels stored on the previous bar.
- A bullish order block is the full range of the latest bearish candle before bullish BOS.
- A bearish order block is the full range of the latest bullish candle before bearish BOS.
- A bullish FVG occurs when low > high[2].
- A bearish FVG occurs when high < low[2].
Gate BOS, order blocks, FVGs, boxes, and alerts with barstate.isconfirmed.
Set max_boxes_count explicitly.
Explain that pivots confirm rightBars bars late.
Return code that compiles in Pine Script v6.
A first pass might contain this plausible but invalid fragment:
//@version=6
indicator("AI Order Blocks", overlay = true)
type ZoneData
float top
float bottom
int createdAt
ZoneData currentZone = ZoneData.new(high, low, bar_index)
// Invalid in Pine v6.
float previousTop = currentZone.top[1]
bool bullishFvg = barstate.isconfirmed and low > high[2]
bool bearishFvg = barstate.isconfirmed and high < low[2]
plot(previousTop)
Reviewing the Output
The compiler rejects currentZone.top[1] because Pine v6 does not allow [] directly on a UDT field. TradingView's migration guide gives two supported forms: reference the object's history first, as in (currentZone[1]).top, or assign the field to its own variable and reference that variable's history.2
Next, review the claims about swing timing. In TradingView's pivot label example on the Objects page, pivots "are detected legsInput bars after they occur", so the script must plot each label in the past.4 Code using ta.pivothigh() or ta.pivotlow() must not be described as instantaneous detection.
Finally, inspect drawing limits. TradingView's Lines and boxes page says a script can display up to 500 boxes, and a script with no explicit limit keeps only about the last 50 drawings of a type.5
The Corrected v6 Script
This corrected example applies object-first history access, confirmed-bar signals, explicit box capacity, and alert-ready JSON. It intentionally leaves mitigation and box deletion undefined rather than inventing rules, so a close that crosses the same swing level again later fires another BOS.
//@version=6
indicator("Confirmed Order Blocks and FVGs", overlay = true, max_boxes_count = 300, max_bars_back = 200)
int leftBars = input.int(3, "Pivot left bars", minval = 1)
int rightBars = input.int(3, "Pivot right bars", minval = 1)
int orderBlockSearch = input.int(12, "Order block search", minval = 1, maxval = 100)
float quantity = input.float(1.0, "Alert quantity", minval = 0.0001)
type SwingSnapshot
float highLevel
float lowLevel
findBearishCandle(int maxBars) =>
int found = na
for i = 1 to maxBars
if na(found) and close[i] < open[i]
found := i
found
findBullishCandle(int maxBars) =>
int found = na
for i = 1 to maxBars
if na(found) and close[i] > open[i]
found := i
found
float pivotHigh = ta.pivothigh(high, leftBars, rightBars)
float pivotLow = ta.pivotlow(low, leftBars, rightBars)
var float lastSwingHigh = na
var float lastSwingLow = na
if barstate.isconfirmed and not na(pivotHigh)
lastSwingHigh := pivotHigh
if barstate.isconfirmed and not na(pivotLow)
lastSwingLow := pivotLow
SwingSnapshot snapshot = SwingSnapshot.new(lastSwingHigh, lastSwingLow)
// v6-safe history access: take the object from one bar back, then read its field.
// The bar_index check skips bar 0, where no previous object exists.
float priorHigh = bar_index > 0 ? (snapshot[1]).highLevel : na
float priorLow = bar_index > 0 ? (snapshot[1]).lowLevel : na
bool bullishBos = barstate.isconfirmed and not na(priorHigh) and close > priorHigh and close[1] <= priorHigh
bool bearishBos = barstate.isconfirmed and not na(priorLow) and close < priorLow and close[1] >= priorLow
bool bullishFvg = barstate.isconfirmed and bar_index >= 2 and low > high[2]
bool bearishFvg = barstate.isconfirmed and bar_index >= 2 and high < low[2]
if bullishBos
int candleOffset = findBearishCandle(orderBlockSearch)
if not na(candleOffset)
box.new(
left = bar_index - candleOffset,
top = high[candleOffset],
right = bar_index,
bottom = low[candleOffset],
extend = extend.right,
border_color = color.green,
bgcolor = color.new(color.green, 85)
)
if bearishBos
int candleOffset = findBullishCandle(orderBlockSearch)
if not na(candleOffset)
box.new(
left = bar_index - candleOffset,
top = high[candleOffset],
right = bar_index,
bottom = low[candleOffset],
extend = extend.right,
border_color = color.red,
bgcolor = color.new(color.red, 85)
)
if bullishFvg
box.new(
left = bar_index - 2,
top = low,
right = bar_index,
bottom = high[2],
extend = extend.right,
border_color = color.aqua,
bgcolor = color.new(color.aqua, 88)
)
if bearishFvg
box.new(
left = bar_index - 2,
top = low[2],
right = bar_index,
bottom = high,
extend = extend.right,
border_color = color.orange,
bgcolor = color.new(color.orange, 88)
)
string buyMessage = "{\"ticker\":\"" + syminfo.ticker + "\",\"action\":\"buy\",\"quantity\":" + str.tostring(quantity) + ",\"orderType\":\"market\",\"price\":" + str.tostring(close) + "}"
string sellMessage = "{\"ticker\":\"" + syminfo.ticker + "\",\"action\":\"sell\",\"quantity\":" + str.tostring(quantity) + ",\"orderType\":\"market\",\"price\":" + str.tostring(close) + "}"
if bullishBos
alert(buyMessage, alert.freq_once_per_bar_close)
if bearishBos
alert(sellMessage, alert.freq_once_per_bar_close)
alertcondition(bullishBos, "Bullish BOS", "Confirmed bullish break of structure")
alertcondition(bearishBos, "Bearish BOS", "Confirmed bearish break of structure")
plot(priorHigh, "Stored swing high", color.green, style = plot.style_linebr)
plot(priorLow, "Stored swing low", color.red, style = plot.style_linebr)
The alert message includes ticker, action, quantity, orderType, and price, all fields in the TradersPost webhook payload. Paste the script into the Pine Editor and resolve every compiler error and warning before testing it.
Why AI Gets SMC Wrong
The UDT History Ban
Pine v6 prohibits history access directly on UDT fields. The correct order is to retrieve the historical object and then access its field. SMC scripts commonly store swings, zones and drawings in UDTs, and v5 code that indexed fields directly still compiled, so an assistant that learned from v5 examples can reverse the order.
TradingView's Objects page adds two traps: objects are assigned by reference, and the built-in copy() method produces a shallow copy.4 Check whether two variables point to the same zone object before mutating a field.
Pivot Delay Is Not Realtime
Pivot detection needs bars that come after the pivot. A five-right-bar pivot cannot be confirmed until the fifth bar after it closes. Plotting the pivot marker back at its original location is visually useful, but it can hide when the script learned about it.
TradingView's repainting page lists "most scripts based on pivots" among those with potentially misleading repainting behavior, and asks publishers to mention such behavior in the script description.3 A BOS based on confirmed pivots inherits this delay even when its own close-crossing condition is confirmed.
Training Data Lags Pine
TradingView's release notes date Pine v6 to November 2024. Sorting UDT arrays and matrices by a chosen field with the new sort_field parameter arrived in April 2026, and the once structure and binary search in UDT arrays arrived in August 2026.6 An assistant trained before these releases will not know them.
These features can help manage order block collections, but reading the release note is not enough. The Conditional structures page explains that a once structure that has not fired yet is evaluated on each tick of the realtime bar, and rollback resets its state until the closing tick, so it can execute its statements several times on one realtime bar. That matters for alert() calls, which rollback does not undo. The documented fix is to append and barstate.isconfirmed to the condition.7
Reviewing AI-Generated SMC Code
Compile and Logic Checklist
- Confirm the script declares
//@version=6. - Compile it in the Pine Editor without errors.
- Search for
.field[n]patterns on UDT objects. - Verify every BOS, CHoCH, order block, and FVG rule against the prompt.
- Check pivot labels for an honest description of confirmation delay.
- Verify visual and alert conditions use the same Boolean variables.
Check Box and Line Limits
A script can display up to 500 lines and 500 boxes, set through the max_lines_count and max_boxes_count parameters of indicator(). Without them, the script shows only about the last 50 drawings of each type, and a garbage collector deletes the oldest drawings once the total exceeds the limit.5
Estimate the number of simultaneous order block and FVG boxes across the chart history you intend to inspect. Also decide whether filled or invalidated zones should be deleted manually instead of allowing unrelated old drawings to disappear through garbage collection.
Check Repainting Behavior
Determine whether signals fluctuate on the open bar, plot into the past, or use information unavailable at the historical moment shown. TradingView's repainting page sorts this behavior into four groups: acceptable, potentially misleading, unacceptable and unavoidable.3
If the AI added a request.security() call, inspect it. The same page warns that lookahead = barmerge.lookahead_on without a [1] offset on the requested series returns future data on historical bars, and its non-repainting pattern pairs an offset such as close[1] with barmerge.lookahead_on.3
From Indicator to Automated Alert
Convert Visuals Into Alerts
Boxes and labels do not send signals by themselves. Add alertcondition() for selectable static conditions or alert() for dynamic JSON messages. Tie the call to the exact confirmed Boolean used to create the matching box.
Once the alert is running, check TradingView's alert log against the chart. Every logged message should line up with a BOS and its order block box on the same bar, and every BOS on the chart should have a logged message.
Send Alerts to a Broker
A webhook message can provide ticker, action, quantity, and orderType. Optional takeProfit and stopLoss objects can carry bracket instructions when your rules define those prices mechanically.
{
"ticker": "AAPL",
"action": "buy",
"quantity": 1,
"orderType": "market",
"price": 225.50,
"takeProfit": {
"limitPrice": 230.00
},
"stopLoss": {
"type": "stop",
"stopPrice": 222.00
}
}
TradersPost receives the JSON your TradingView alert sends, applies your strategy subscription settings, and routes the resulting order to the broker account you connected. Connect the corrected indicator to a webhook only after its alert messages match the chart, then use a paper account before enabling live orders.
Paper Trade Before Live Use
Check auto submit, allowed sides and position size in the subscription. With auto submit off, signals wait for you to approve each trade. Run the alert across several realtime sessions and compare each alert's time, action and price with the BOS and order block event on the chart.
Historical bars cannot reproduce every intrabar state. Realtime paper testing can expose duplicate alerts, disappearing open-bar signals, delayed pivots, malformed JSON, and differences between the visual event and the transmitted message.
Bottom Line
- Define BOS, CHoCH, order blocks, and FVGs as exact mechanical conditions.
- Require Pine Script v6 and inspect all UDT history access.
- Use confirmed-bar logic while disclosing pivot confirmation delay.
- Set drawing limits and test garbage collection behavior.
- Compare realtime alerts with chart events before automating orders.
The best AI output comes from a prompt that leaves no trading rule to interpretation. Use the broader AI Pine Script guide for prompting principles, or compare implementation patterns for trend indicators, momentum indicators, volatility indicators, and volume indicators. Once the corrected alert behaves consistently, connect it to a TradersPost webhook and paper trade it before considering live execution.
Frequently Asked Questions
Can AI Code Reliable Order Blocks?
Yes, but only when the prompt defines every concept mechanically. The result still requires manual compilation, v6 review, pivot-delay review, and realtime testing.
Why Does Pine v6 Compilation Fail?
A common cause is applying [] directly to a UDT field. Replace myObject.field[n] with (myObject[n]).field, or assign the field to a separate variable before indexing it.
Why Does BOS Fire Late?
Pivot-based swings confirm only after the configured right-bar count has passed. A BOS that depends on those pivots cannot use the swing before it has been confirmed.
How Many Boxes Can Display?
Pine permits up to 500 boxes per script, but the default is approximately 50 unless max_boxes_count is set. When the limit is exceeded, garbage collection removes the oldest boxes.
Is SMC Independently Validated?
Order blocks and FVGs have no standard definition, so every indicator implements its author's own rules. Treat one as a mechanical version of those rules, not as evidence that they predict future prices.
References
1 StockCharts ChartSchool: Dow Theory
2 TradingView: To Pine Script version 6
3 TradingView: Repainting
4 TradingView: Objects
5 TradingView: Lines and boxes
6 TradingView: Pine Script release notes
7 TradingView: Conditional structures