AlertaScript
Pine Script alternative: run Pine-style scripts in AlertaScript
No converter needed: paste Pine-style code into the AlertaScript editor. What runs unchanged, what returns na, and three tested examples.
If you have written indicators or strategies in Pine Script®, you do not need a converter or a new language to run them on AlertaChart. AlertaScript accepts a broad Pine-compatible syntax — namespaced calls such as ta.ema, arrays, maps, user-defined types and strategies — and you start by pasting your code into its editor as it is.
This guide is for traders deciding whether to move their scripts: what to expect in the first five minutes, what runs unchanged, what quietly returns no data, and three complete examples that we tested on both of AlertaChart's script engines. The reference version of the same material, with an "Open in editor" button on every example, is the documentation page Pine compatibility and migration.
Why no converter is needed
Converters exist because most platforms speak another language. AlertaScript reads the same syntax, so the editor runs exactly the code you paste — it does not rewrite it. The documentation writes functions with an alerta. prefix to tell them apart (alerta.ta.ema), but the original names work too and resolve to the same calculation, without a naming warning. The //@version line of an existing script can stay. No converter does not mean nothing ever changes: now and then a call needs a small edit, and the editor names the line where that is the case.
indicator("EMA spellings", overlay=true)
original = ta.ema(close, 20)
prefixed = alerta.ta.ema(close, 20)
plot(original, "TradingView-compatible")
plot(prefixed, "AlertaScript", color=color.blue)Both lines are the same EMA and lie on top of each other.
Your first five minutes
- Open a chart and, from the Indicators menu, open the AlertaScript editor. It is a window you can move while the chart stays visible.
- Paste your script without changing anything and press Run.
- Read the messages. Errors come with their line. A warning means the script ran but could not supply a value — note it and look it up below.
- A Run that ends without an error also saves the script to your library under My scripts; warnings do not block it.
- Change the inputs from the gear of the script's row on the chart, the same way as any indicator.
Open the chart with the AlertaScript editor →Trader
AlertaScript is included from the Trader plan; alerts on a script's conditions come with Pro and Elite. Pricing compares the plans. The Help Center's AlertaScript article covers the editor, the script library and sharing.
What runs unchanged, what does not
Syntax is rarely the problem. Data is. These limits come from the documentation's limits page and the engine itself:
| Your script uses | What happens |
|---|---|
ta.*, math.*, str.*, arrays, maps, matrices, types, strategy.* | Runs. Search the reference by the name you know if a call fails. |
request.security for another timeframe or symbol | Runs when the symbol exists on AlertaChart and has history for the period. |
request.financial, request.earnings, request.dividends, request.splits | Returns na: there is no fundamentals feed. You see a warning unless the call passes ignore_invalid_symbol = true. |
request.seed, request.quandl | Not supported; returns na with a warning. |
syminfo.current_contract | Not supported; gives no contract code. |
Footprint or open-interest data (request.footprint, tickers such as BINANCE:BTCUSDT.P_OI) | Pro and Elite plans, on supported markets and timeframes; on other plans na with a warning. See order flow data. |
A script that relies on any of these still runs — it just draws an empty line. That is why a migration is checked by looking at the output, not only by the absence of errors.
Example 1: an EMA crossover strategy
Long when the 9-period EMA crosses above the 21-period EMA, flat on the opposite cross, with a protective stop 2 % under the average entry price. The defaults in strategy(...) — 10,000 starting capital, 10 % of equity per order and 0.1 % commission — are what the Strategy tester starts from.
//@version=5
strategy("EMA crossover strategy", overlay=true, initial_capital=10000, default_qty_type=strategy.percent_of_equity, default_qty_value=10, commission_type=strategy.commission.percent, commission_value=0.1)
fastLength = input.int(9, "Fast EMA length", minval=1)
slowLength = input.int(21, "Slow EMA length", minval=2)
stopPercent = input.float(2.0, "Stop loss (%)", minval=0.1, step=0.1)
fast = ta.ema(close, fastLength)
slow = ta.ema(close, slowLength)
crossUp = ta.crossover(fast, slow)
crossDown = ta.crossunder(fast, slow)
if crossUp
strategy.entry("Long", strategy.long)
if crossDown
strategy.close("Long", comment="EMA cross down")
// A protective stop: an absolute price, recalculated from the average entry price.
if strategy.position_size > 0
strategy.exit("Stop", "Long", stop=strategy.position_avg_price * (1 - stopPercent / 100))
plot(fast, "Fast EMA", color=color.teal)
plot(slow, "Slow EMA", color=color.orange)
plotshape(crossUp, title="Cross up", style=shape.triangleup, location=location.belowbar, color=color.teal, size=size.tiny)- Results appear in the Strategy tester under the chart: key stats first (total P&L, maximum drawdown, profitable trades, profit factor), then the list of trades. Its settings change capital, order size, commission and slippage without editing the code.
- In the simulation, an order placed on the signal bar fills at the open of the next bar, so the marker and the fill price differ.
stop=is an absolute price, which is why the input is converted.profit=andloss=would be distances in ticks.- A strategy never sends orders to an exchange. A test on past data says nothing certain about the future.
Example 2: RSI divergence with alert conditions
An indicator in its own pane that compares RSI pivots with price: a lower price low on a higher RSI low is marked bullish, a higher price high on a lower RSI high bearish. Each case is a named alertcondition.
//@version=5
indicator("RSI divergence finder", overlay=false)
rsiLength = input.int(14, "RSI length", minval=2)
pivotBars = input.int(5, "Bars on each side of a pivot", minval=1)
rsi = ta.rsi(close, rsiLength)
// A pivot is only known pivotBars bars after it formed.
rsiLow = ta.pivotlow(rsi, pivotBars, pivotBars)
rsiHigh = ta.pivothigh(rsi, pivotBars, pivotBars)
newLow = not na(rsiLow)
newHigh = not na(rsiHigh)
// RSI and price at the previous pivot of the same kind.
lastRsiLow = ta.valuewhen(newLow, rsi[pivotBars], 1)
lastPriceLow = ta.valuewhen(newLow, low[pivotBars], 1)
lastRsiHigh = ta.valuewhen(newHigh, rsi[pivotBars], 1)
lastPriceHigh = ta.valuewhen(newHigh, high[pivotBars], 1)
// Price makes a lower low while RSI makes a higher low (bullish), or the reverse at highs (bearish).
bullish = newLow and low[pivotBars] < lastPriceLow and rsi[pivotBars] > lastRsiLow
bearish = newHigh and high[pivotBars] > lastPriceHigh and rsi[pivotBars] < lastRsiHigh
plot(rsi, "RSI", color=color.purple)
hline(70, "Upper level")
hline(30, "Lower level")
plot(bullish ? rsi[pivotBars] : na, "Bullish divergence", color=color.green, style=plot.style_circles, linewidth=4, offset=-pivotBars)
plot(bearish ? rsi[pivotBars] : na, "Bearish divergence", color=color.red, style=plot.style_circles, linewidth=4, offset=-pivotBars)
alertcondition(bullish, "Bullish RSI divergence", "{{ticker}}: bullish RSI divergence confirmed")
alertcondition(bearish, "Bearish RSI divergence", "{{ticker}}: bearish RSI divergence confirmed")- A pivot is confirmed only after five more bars (the default input), so on a live chart a mark appears five bars late;
offsetplaces it back on the pivot bar. - To be notified (script alerts come with the Pro and Elite plans), open Create Alert, choose Script as the source and then this script, and pick the condition by its title from the Script alerts list.
{{ticker}}becomes the symbol. - The alert window states it plainly: script alerts are evaluated while AlertaChart is open; they do not run around the clock on the server yet. Price alerts are covered in the alerts article.
Example 3: a higher-timeframe trend filter
request.security calculates the whole expression on the requested timeframe — here a 50-period EMA of 4-hour candles — and lines the result up with your chart. One call returns two values as a tuple.
//@version=5
indicator("Higher-timeframe trend filter", overlay=true)
higherTf = input.timeframe("240", "Higher timeframe")
emaLength = input.int(50, "EMA length on the higher timeframe", minval=1)
// One request returns both values, each calculated on the higher timeframe's own bars.
[htfEma, htfClose] = request.security(syminfo.tickerid, higherTf, [ta.ema(close, emaLength), close], lookahead=barmerge.lookahead_off)
uptrend = htfClose > htfEma
plot(htfEma, "Higher-timeframe EMA", color=uptrend ? color.teal : color.red, linewidth=2)
bgcolor(uptrend ? color.new(color.teal, 92) : color.new(color.red, 92), title="Trend background")- An EMA computed on 4-hour candles is not the same as averaging 4-hour closes on a 1-hour chart.
lookahead_offuses no future bars. While the current 4-hour candle is still open, its value can change.- Pick another timeframe from the gear:
input.timeframemakes it a setting.
Honest differences
- Live versus closed candles. Scripts recalculate while a candle forms; a cross can appear and vanish before the close. Use
barstate.isconfirmedwhen a rule must wait for it. - Data. Compare the same exchange, symbol and timeframe. BTC/USDT on two exchanges is two different price series, so indicator values differ even with identical code.
- History. How far back a chart goes depends on the market and its data source, so long lookbacks may start later than elsewhere.
- Resources. Loops and drawing objects are bounded. The limits page publishes no fixed numbers, so delete objects you no longer need instead of creating new ones on every bar.
Common problems
- "Unknown function": search the reference by the original name and by its
alerta.spelling. A call into a library that is not loaded is different: it returnsnawith a warning. - An empty line: early bars without enough history, an
narequest, or an oscillator that opened in its own pane. - Different trades than elsewhere: match quantity, commission, slippage and the test range first, then the fill rule above.
For a reproducible error, the documentation's troubleshooting page shows how to reduce it to a small example.
Next steps
- The full reference with an "Open in editor" button on each example: Pine compatibility and migration.
- Scripts shared by other traders, installable in one click: Help Center: Community.
- Reading volume by price on the chart, with the tools AlertaChart has built in: volume profile guide.
Sources
- Pine compatibility and migration — AlertaScript documentation (accessed Oct 5, 2026)
- Limits and availability — AlertaScript documentation (accessed Oct 5, 2026)
- Strategies and backtesting — AlertaScript documentation (accessed Oct 5, 2026)
- Multiple symbols and timeframes — AlertaScript documentation (accessed Oct 5, 2026)
- AlertaScript: your own indicators and strategies — AlertaChart Help Center (accessed Oct 5, 2026)
How this guide was made Drafted with AI from AlertaChart's Help Center and source code; product facts checked against the code and the Help Center; external facts from the cited primary sources.
Changes · Version 1.0
- · 1.0 — First version.