Tutorials

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.

Tom Hartman

Marketing

12 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.

Getting an AI assistant to write a Pine Script futures strategy that sends webhook alerts works only when the prompt specifies Pine Script v6, futures-specific symbol behavior, confirmed-bar entries, and a valid per-order JSON message. Without those constraints, the code can compile and still send empty alerts, misread futures sessions, or route a continuous contract differently than expected.

This tutorial extends the Best AI for Pine Script series with a prompt, a corrected moving-average strategy, and an audit checklist. The goal is not to evaluate profitability. It is to produce code that can move safely from the Pine Editor to a paper-trading webhook.

What This Category Covers

Webhook-Ready Futures Strategies

This category covers Pine Script v6 strategies whose strategy.entry(), strategy.exit(), strategy.close(), or strategy.order() calls include an alert_message argument. The argument defines a custom message for the corresponding order fill event and accepts a series string that can be assembled from script variables.1

Pine has no built-in function that produces JSON, so scripts construct JSON-shaped messages through string concatenation and conversions such as str.tostring().2 TradersPost can receive this JSON, read fields such as ticker, action, and quantity, then process the signal through the connected account's subscription settings.

Why Futures Need Special Handling

Futures expose symbol-specific properties that equity-focused examples may ignore. Pine provides values including syminfo.pointvalue, syminfo.mintick, syminfo.root, and contract expiration data for applicable symbols.3 Tick-based stops, point-based targets, contract quantities, and session filters must respect those properties.

Continuous 1! charts also introduce rollover behavior. TradingView sets each symbol's switching rule using historical volume behavior, principally when the next contract's daily volume exceeds the current contract's volume, rather than applying one universal expiration offset.4 An AI assistant trained on equity examples may miss both this rollover model and the meaning of named futures sessions.

Where This Fits

The same review process applies to trend following strategies, mean reversion strategies, breakout and opening range strategies, and momentum strategies. Entry logic changes, but version control, confirmed-bar execution, contract identity, sessions, and webhook formatting remain common review points.

Prompt Template For Webhook-Ready Code

Pin The Pine Version

Start the prompt with an explicit requirement for //@version=6. Also prohibit deprecated v4 or v5 syntax. This prevents the model from mixing old function names, obsolete examples, and current strategy parameters in one draft.

Name Inputs And Conditions

List every input's type, default, and purpose. Define the exact crossover, position-state, stop, and target conditions instead of requesting a generic moving-average strategy. Name the intended futures root and whether the script will run on an explicit contract or a continuous chart.

  • Fast EMA: integer, default 20
  • Slow EMA: integer, default 50
  • Quantity: integer, default 1
  • Stop distance: float, default 8.0 points
  • Target distance: float, default 16.0 points
  • Webhook ticker: string, default explicit contract symbol

Require Confirmed-Bar Logic

Ask the model to gate entries with barstate.isconfirmed. Historical bars execute differently from developing realtime bars, where values can change before confirmation. Strategies recalculate at bar close by default, while calc_on_every_tick = true permits intrabar recalculation and can create behavior that historical bars do not reproduce.1

State whether the strategy should use order fill events, alert() calls, or both. If using alert(), specify its frequency and whether intrabar calculation is intentional.

Specify The Alert Payload

Tell the model to build dynamic values with str.tostring(). Place strategy placeholders such as {{strategy.order.action}} or {{strategy.position_size}} in the alert's Message field when needed, not inside the alert_message argument. Most importantly, require {{strategy.order.alert_message}} in the Message field or compiler annotation so the custom per-order string reaches the notification.2

Worked Example: Prompt To Code

The Submitted AI Prompt

A sufficiently constrained prompt could read:

Write a Pine Script strategy using //@version=6.

Target a CME E-mini S&P 500 futures chart with root ES. Use a 20-period EMA and a 50-period EMA. Enter long when the fast EMA crosses above the slow EMA. Enter short when it crosses below. Allow entries only when barstate.isconfirmed and the strategy is flat.

Use an integer quantity input with default 1. Use a float stop-distance input with default 8.0 points and a float take-profit input with default 16.0 points. Set calc_on_every_tick to false.

Add strategy.exit orders for both directions. Build valid JSON strings for every strategy.entry and strategy.exit alert_message using string concatenation and str.tostring(). Entry messages use the fields ticker, action, quantity, orderType, stopLoss, and takeProfit. Exit messages use ticker, action set to exit, and cancel set to true. Add a string input for an explicit futures contract ticker, default ESZ2026.

Do not put TradingView placeholders such as {{close}} inside alert_message. Add a //@strategy_alert_message annotation containing {{strategy.order.alert_message}}. Use no deprecated v4 or v5 syntax.

Reviewing The First Draft

Do not accept the first draft because it looks plausible. Check whether it embeds {{close}} or other placeholders in alert_message, labels session.regular as daytime trading, or sends the chart's continuous symbol as the executable ticker.

Also inspect any use of syminfo.current_contract. TradingView added this variable in July 2025 for identifying the underlying contract on continuous futures charts.5 Its documentation is inconsistent for non-continuous symbols: the release notes describe na, while the chart-information page describes an empty string.3 Robust code must guard against both states.

Corrected Pine Script V6

//@version=6
//@strategy_alert_message {{strategy.order.alert_message}}
strategy("ES Webhook EMA Cross", overlay = true, pyramiding = 0, calc_on_every_tick = false)

int fastLength = input.int(20, "Fast EMA Length", minval = 1)
int slowLength = input.int(50, "Slow EMA Length", minval = 2)
int orderQuantity = input.int(1, "Contract Quantity", minval = 1)
float stopPoints = input.float(8.0, "Stop Distance", minval = 0.25, step = 0.25)
float targetPoints = input.float(16.0, "Target Distance", minval = 0.25, step = 0.25)
string webhookTicker = input.string("ESZ2026", "Explicit Contract Ticker")

float fastEMA = ta.ema(close, fastLength)
float slowEMA = ta.ema(close, slowLength)

bool correctRoot = syminfo.root == "ES"
bool enterLong = correctRoot and barstate.isconfirmed and strategy.position_size == 0 and ta.crossover(fastEMA, slowEMA)
bool enterShort = correctRoot and barstate.isconfirmed and strategy.position_size == 0 and ta.crossunder(fastEMA, slowEMA)

string quantityText = str.tostring(orderQuantity)

if enterLong
    float plannedStop = close - stopPoints
    float plannedTarget = close + targetPoints
    string longMessage = "{\"ticker\":\"" + webhookTicker + "\",\"action\":\"buy\",\"quantity\":" + quantityText + ",\"orderType\":\"market\",\"stopLoss\":{\"type\":\"stop\",\"stopPrice\":" + str.tostring(plannedStop, format.mintick) + "},\"takeProfit\":{\"limitPrice\":" + str.tostring(plannedTarget, format.mintick) + "}}"
    strategy.entry("Long", strategy.long, qty = orderQuantity, alert_message = longMessage)

if enterShort
    float plannedStop = close + stopPoints
    float plannedTarget = close - targetPoints
    string shortMessage = "{\"ticker\":\"" + webhookTicker + "\",\"action\":\"sell\",\"quantity\":" + quantityText + ",\"orderType\":\"market\",\"stopLoss\":{\"type\":\"stop\",\"stopPrice\":" + str.tostring(plannedStop, format.mintick) + "},\"takeProfit\":{\"limitPrice\":" + str.tostring(plannedTarget, format.mintick) + "}}"
    strategy.entry("Short", strategy.short, qty = orderQuantity, alert_message = shortMessage)

if strategy.position_size > 0
    float longStop = strategy.position_avg_price - stopPoints
    float longTarget = strategy.position_avg_price + targetPoints
    string longExitMessage = "{\"ticker\":\"" + webhookTicker + "\",\"action\":\"exit\",\"cancel\":true}"
    strategy.exit("Long Exit", from_entry = "Long", stop = longStop, limit = longTarget, alert_message = longExitMessage)

if strategy.position_size < 0
    float shortStop = strategy.position_avg_price + stopPoints
    float shortTarget = strategy.position_avg_price - targetPoints
    string shortExitMessage = "{\"ticker\":\"" + webhookTicker + "\",\"action\":\"exit\",\"cancel\":true}"
    strategy.exit("Short Exit", from_entry = "Short", stop = shortStop, limit = shortTarget, alert_message = shortExitMessage)

plot(fastEMA, "Fast EMA", color = color.aqua)
plot(slowEMA, "Slow EMA", color = color.orange)

The entry message carries a broker-side bracket, so the stop and target rest at the broker once the entry fills. The chart's strategy.exit() calls mirror that bracket, and their fill alerts send an exit as a backup. The exit message sets cancel to true so TradersPost cancels the resting bracket orders before it exits. If the broker's bracket has already closed the position, TradersPost rejects the later exit because there is no open position, which its documentation describes as a safeguard. The bracket prices are anchored to the signal bar's close, while the chart's exits use the average fill price, so the two can differ by the gap between that close and the fill.

Paste the corrected script into the Pine Editor and compile it before creating an alert. Confirm the chart uses the intended ES dataset, then replace the default webhook ticker when the explicit contract changes. Compilable code is only the beginning of the review, not proof that the order semantics are correct.

Common AI Futures Mistakes

Misusing alert_message

The alert_message expression is evaluated when its order executes, not when the script initially places the order. Other placeholders cannot be evaluated inside that argument, and an order without an alert_message supplies an empty custom message.1

Even a correct custom string remains unavailable unless the alert's Message field, or the //@strategy_alert_message annotation, contains {{strategy.order.alert_message}}. If either part is missing, the webhook body arrives empty instead of carrying your JSON.

Confusing Futures Sessions

For most futures contracts, the longer electronic trading session is the default named regular. Selecting RTH on a CME futures chart changes the active name to us_regular, while session.extended is equivalent to session.regular where no separate extended session exists.6

Therefore, code that tests session.regular to isolate daytime bars can include the electronic session instead. Ask the AI to inspect syminfo.session and define the intended named session explicitly.

Mishandling Continuous Contracts

On a continuous chart, syminfo.current_contract identifies the underlying contract ticker. Because its documented non-continuous fallback is inconsistent, test both na and an empty string before using it.

Do not infer rollover from a fixed number of days before expiration. TradingView's documented example switches GC1! from GCQ2022 to GCZ2022 on July 28, 2022, ahead of the August 29 expiration, based on the symbol's volume-derived switching rule.4 Explicit contract tickers make the intended destination unambiguous.

AI Pine Script Review Checklist

Compile And Alert Checks

  • Compile in the Pine Editor under version 6.
  • Remove deprecated syntax and unresolved type errors.
  • Verify every dynamic value uses str.tostring().
  • Confirm the Message field contains {{strategy.order.alert_message}}.
  • Inspect the resulting body as JSON, not merely as a Pine string.

Session And Symbol Checks

  • Confirm whether the logic targets regular, us_regular, or another named session.
  • Verify syminfo.root, syminfo.mintick, and syminfo.pointvalue where relevant.
  • Distinguish the chart symbol from the explicit contract sent in the webhook.
  • Guard both na and empty-string results before using syminfo.current_contract.

Order And Payload Checks

  • Verify entry and exit actions match the receiving service's field specification.
  • Confirm numeric JSON values are not accidentally quoted as strings.
  • Test that fill alerts occur only for realtime executions, not historical orders.
  • Delete and recreate the alert after changing code, inputs, symbol, or timeframe.
  • Validate JSON before enabling automated submission.

Strategy fill notifications are generated for realtime executions, not orders on historical bars. A running alert also uses an independent server-side copy, so subsequent chart or input changes do not update it.7

From Chart To Live Execution

Create The Strategy Alert

Add the compiled strategy to the intended chart, open Create Alert, and select order fills, alert() calls, or both. For this example, select order fills and leave the Message field as {{strategy.order.alert_message}}. Pine code exposes alert events, but it does not create the running alert by itself.2

Enable webhook delivery in Notifications and enter the destination URL. TradingView sends the alert body with an application/json content type when the message is valid JSON; otherwise, it sends text/plain.8

Route The Webhook

TradersPost can parse the incoming ticker, action, and quantity, process the signal under the strategy subscription, and submit the resulting trade to the connected broker, exchange, or prop firm account. For futures, always send an explicit contract such as ESZ2026 instead of ES1!, for the reasons in the FAQ below. Review the signal record and resulting trade information to confirm that the payload was interpreted as intended.

Paper Trade First

Connect the alert to a paper account before risking capital. The TradersPost paper broker supports futures but has no futures data by default, so set a connected broker with live futures data, such as TradeStation, as its market data source. Webhook alerts require two-factor authentication, and TradingView publishes the source IP addresses used for webhook POST requests.8 During testing, watch the alert log for excessive activity. TradingView stops a strategy alert if it triggers more than 15 times within three minutes.7

Paper trade the corrected strategy through the complete webhook path. Compare the TradingView alert body, the receiving platform's parsed signal, and the paper account's order before enabling live submission.

Bottom Line

  • Prompt for Pine Script v6, exact typed inputs, explicit futures symbols, and confirmed-bar conditions.
  • Build alert_message values through concatenation and str.tostring().
  • Include {{strategy.order.alert_message}} in the alert Message field or compiler annotation.
  • Treat regular, us_regular, and continuous-contract rollover as futures-specific review items.
  • Recreate alerts after changes and verify the entire route with paper trading.

Use the broader Best AI for Pine Script framework to evaluate the assistant that generates your code, then paper trade this corrected strategy through a TradersPost webhook before considering live execution.

Frequently Asked Questions

What Does The Placeholder Do?

{{strategy.order.alert_message}} inserts the string supplied to the executed order's alert_message parameter. It must appear in the alert's Message field or the //@strategy_alert_message annotation. Without it, the custom string does not appear in the delivered notification.

Does strategy.close Support alert_message?

Yes. Pine Script v6 supports alert_message on strategy.close(), strategy.entry(), strategy.exit(), and strategy.order().1 It accepts a series string, so script values can be converted with str.tostring(). Do not embed alert placeholders such as {{close}} inside the argument.

Why Is My Message Missing?

Confirm that the Message field includes {{strategy.order.alert_message}} and that the order executed in realtime. If you changed the script, inputs, chart symbol, or timeframe after creating the alert, delete the old alert and create a new one.

Why Is Regular Session Wrong?

On many futures charts, regular identifies the default electronic session rather than daytime RTH. A CME futures chart configured for RTH reports us_regular. Session filters copied from equity scripts can therefore classify futures bars incorrectly.

Should Webhooks Use Continuous Symbols?

No. Our futures documentation recommends against continuous symbols such as NQ1!: we do not yet reliably resolve the contract behind them, and around roll periods our platform and TradingView may reference different contracts. Send an explicit contract ticker, such as NQZ2026, so there is no disagreement about which contract receives the order.

References

1 TradingView Pine Script Alerts
2 TradingView Pine Script Alerts FAQ
3 TradingView Chart Information
4 Continuous Futures Switching Dates
5 TradingView Pine Script Release Notes
6 TradingView Pine Script Sessions
7 TradingView Strategy Alerts
8 TradingView Webhook Configuration

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

    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.

  • Tutorials Oct 9, 2026

    Coding an AI Pine Script Scalping Strategy

    Prompt an AI for a Pine Script v6 scalping strategy, then audit the backtest for the fill, cost, and bar-detail mistakes AI assistants make most.

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.