AlgoBarsX 1 · 297 built-ins · 61 examples · Beta

AlgoBarsX documentation.
Everything the language can do.

Guides for your first script, a complete reference for every function, command and setting, the written rules for how orders fill, every compiler message, and 61 scripts you can copy. Built from the language's own source, so it cannot drift from what the compiler accepts.

Try
ema-cross.abx
strategy "EMA Cross"
market: EURUSD
bars: 15m
input fast = 20
input slow = 50
when crosses_above(ema(close, fast), ema(close, slow)):
buy risk: 1%, stop: 25 pips, target: 2R
when crosses_below(ema(close, fast), ema(close, slow)):
close_all
What the compiler says it does

When the EMA of the close over fast bars crosses above the EMA of the close over slow bars, it buys at market, risking 1% of the balance, with a stop 25 pips from the entry and with a target 2R from the entry.

157 pages

Start Here

4 guides · What AlgoBarsX is, your first script, and how a script is laid out

What AlgoBarsX is

One language for strategies, indicators, alerts and libraries.
2 min

AlgoBarsX is the language AlgoBars runs on. You describe a strategy, an indicator or an alert in a few readable lines, and the same script is used by the chart, the backtester, the alerts engine and live automation. There is one definition of what your rule means, so you never rewrite it for a different tool.

There are four kinds of script. The first word of the file says which one it is.

KindWhat it is forWhat comes back when you run it
strategyPlaces and manages trades.A backtest, a report and a chart. It can be deployed to a demo or live account.
indicatorCalculates and draws. It can publish values for other scripts to use.The chart it draws and the values it exports.
alertWatches a condition and sends a message.The messages it would have sent, and the ones it held back because of its own repeat and cooldown settings.
libraryHolds functions and constants you reuse.It is checked and described. Other scripts import it by name and version.

Every script is also translated back into plain English by the compiler, so you can check that it says what you meant. That text is generated from the compiled code. If the English is wrong, the code is wrong.

You do not have to write code. The AI strategy builder and the generator both produce AlgoBarsX. This documentation is for reading what they wrote, changing it, and building your own from scratch.

Open this page on its own · Markdown

Your first strategy

Write it, read it back, run it.
4 min
Would you rather describe it? Type what you want in plain English in the editor. When the text reads as a description and not as code, a Convert to AlgoBarsX button appears and writes the script for you.
  1. Open the Terminal in AlgoBars and start a new strategy. You get a working starter script, not a blank page.
  2. Replace it with the script below. It buys when a fast average crosses above a slow one, risks 1% of the balance with a 25-pip stop and a target of twice the risk, and closes everything on the opposite cross.
AlgoBarsX
strategy "EMA Cross"
market: EURUSD
bars: 15m
input fast = 20
input slow = 50
when crosses_above(ema(close, fast), ema(close, slow)):
buy risk: 1%, stop: 25 pips, target: 2R
when crosses_below(ema(close, fast), ema(close, slow)):
close_all
  1. Open the description tab. The compiler reads the script back to you:
What this script says

EMA Cross is a strategy that trades EURUSD on 15-minute bars.

You can change 2 inputs: fast (default 20) and slow (default 50).

When the EMA of the close over fast bars crosses above the EMA of the close over slow bars, it buys at market, risking 1% of the balance, with a stop 25 pips from the entry and with a target 2R from the entry.

When the EMA of the close over fast bars crosses below the EMA of the close over slow bars, it closes all trades.

  1. Press Run. A small panel asks what to test on: market, bars, bar type, how far back (1 week to 1 year), lot size and starting balance. The market and bars come filled in from your script, so you are confirming, not retyping.
  2. You get results, a report, a chart and a replay. The replay plays the finished test back so you can watch each trade open and close and the balance move. Every run is kept under versions with the code that produced it, so you can always go back.
  3. Change fast or the stop and run again. Nothing is lost by trying.
About the numbers. Backtest results are hypothetical. Fills carry no spread, commission, fees, swaps or slippage (execution rule E12), so live results will differ. Past performance does not guarantee future results.

Open this page on its own · Markdown

The cheat sheet

Most of the language on one screen. It compiles.
2 min

One script that touches the header, inputs, constants, state, history, another bar size, confirmations, a rule with timing, a managed order, an event and a plot. Copy it into the Terminal and start deleting what you do not need.

AlgoBarsX
1algobarsx 1
2strategy "Cheat Sheet" # or: indicator, alert, library
3market: EURUSD # several: markets: EURUSD, GBPUSD
4bars: 15m # 1m 5m 1h 4h 1d, or renko(5), xray(20)
5max_open: 1
6max_daily_loss: 3%
7
8input length = 20, min: 5, max: 200 # a setting in the panel
9const BUFFER = 2 pips # fixed value
10state wins = 0 # survives between bars
11
12fast = ema(close, length) # worked out again on every bar
13prev_close = close[1] # history: one bar back
14h4 = bars(bars: 4h) # another bar size, closed candles only
15uptrend = h4.close > ema(h4.close, 50)
16
17confirmations setup: # named conditions
18trend: uptrend
19momentum: rsi(close, 14) between 50 and 70
20require: all
21
22when setup.passed and crosses_above(close, fast) max 2 per day cooldown 30m:
23buy risk: 1%, stop: low - BUFFER, target: 2R:
24breakeven at: 1R
25partial 50% at: 1.5R
26trail by: atr(14) * 2, after: 1.5R
27
28when crosses_below(close, fast):
29close_all
30
31on exit(trade):
32if trade.r > 0:
33wins += 1
34log "{trade.tag} closed at {trade.r:0.00}R, {wins} wins so far"
35
36plot fast, color: if uptrend then green else red

For the long version, see the Language Tour example, which uses nearly every construct in the language.

Open this page on its own · Markdown

How a script is laid out

Header, inputs, calculations, rules, drawing.
3 min

A script reads from top to bottom in five parts. Only the header is required.

AlgoBarsX
algobarsx 1
# 1. Header: what kind of script this is, and its settings
strategy "Layout"
market: EURUSD
bars: 15m
# 2. Inputs: what the person running it may change
input length = 20
# 3. Calculations: worked out on every bar
trend_up = close > ema(close, length)
# 4. Rules: when something is true, do something
when starts(trend_up):
buy risk: 1%, stop: 20 pips, target: 2R
# 5. Drawing: what the chart shows
plot ema(close, length), color: blue
  • Blocks are indented with spaces. A line ending in a colon opens a block, and the lines under it are indented. Tabs are an error (AS0003).
  • Comments start with # and run to the end of the line.
  • The optional first line algobarsx 1 names the language version the script was written for.
  • Line breaks inside ( ), [ ] or { } are ignored, so long expressions can span lines there.
  • Names are case-sensitive. A short list of words is reserved, such as when, on, if, state and input. The full list is in the grammar.

At each bar close the runtime works in a fixed order: fills and management inside the bar, then on fill and on exit, then calculations, then confirmations and sequences, then rules in script order, then exports and drawing. Orders your rules create take effect from the next bar. See E21 and E1.

Open this page on its own · Markdown

Coming from Another Language

6 guides · Pine Script, MQL, NinjaScript, EasyLanguage, thinkScript and Python, each with a real import

Coming from Pine Script

A real import, the ideas side by side, and the names that translate.
3 min

This is a real run of the importer on a small Pine Script script. The result compiles. 8 lines were read: 5 carried over exactly, 2 were adapted and 2 came back as decisions for you.

What you paste · Pine Script
//@version=5
strategy("RSI Dip", overlay=true)
len = input.int(14, "RSI Length")
r = ta.rsi(close, len)
if ta.crossover(r, 30)
strategy.entry("L", strategy.long)
if ta.crossunder(r, 70)
strategy.close("L")
plot(ta.ema(close, 200), color=color.orange)
What you get back
1strategy "RSI Dip"
2market: EURUSD
3bars: 1h
4
5input len = 14
6
7r = rsi(close, len)
8
9when crosses_above(r, 30):
10buy size: 1 lot, tag: "L"
11
12when crosses_below(r, 70):
13close_all tag: "L"
14
15plot ema(close, 200), color: orange

Line by line

StatusYour lineWhat happened
Exactstrategy("RSI Dip", overlay=true)strategy() became the script header
Exactlen = input.int(14, "RSI Length")input() became an input
Exactr = ta.rsi(close, len)a calculation was carried over
Your callstrategy.entry("L", strategy.long)strategy.entry() had no size of its own, so it became one lot: set the size or risk you want
Adaptedif ta.crossover(r, 30)an if that places orders became a rule
Exactstrategy.close("L")strategy.close() became close_all
Adaptedif ta.crossunder(r, 70)an if that places orders became a rule
Exactplot(ta.ema(close, 200), color=color.orange)plot() became plot
Your callstrategy(...)Pine scripts carry no market or bar size, so EURUSD on 1h was filled in: set the ones you want

How the ideas translate

In Pine ScriptIn AlgoBarsX
strategy("RSI Dip", overlay=true)strategy "RSI Dip" with market: and bars: stated. Pine takes both from the chart, so they come back as your decision.
len = input.int(14, "RSI Length")input len = 14
ta.rsi(close, len)rsi(close, len)
if cond, then strategy.entry(...) under itwhen cond: with buy under it
strategy.close("L")close_all tag: "L"
plot(x, color=color.orange)plot x, color: orange
var count = 0state count = 0
close[1]close[1], exactly the same
Tip. Pine does not say how big the position is, so the import uses one lot and hands the choice back to you. Replace it with risk: 1% and a stop.

Names the importer translates for you

Their nameAlgoBarsX
ta.smasma
ta.emaema
ta.rmarma
ta.wmawma
ta.hmahma
ta.vwmavwma
ta.demadema
ta.tematema
ta.rsirsi
ta.ccicci
ta.rocroc
ta.mommomentum
ta.stdevstdev
ta.variancevariance
ta.highesthighest
ta.lowestlowest
ta.medianmedian
ta.linreglinreg
ta.correlationcorrelation
ta.atratr
ta.trtrue_range
ta.mfimfi
ta.obvobv
ta.vwapvwap
ta.barssincebars_since
ta.crossovercrosses_above
ta.crossundercrosses_below
ta.crosscrosses
ta.cumcum
ta.trixtrix
ta.cmocmo
math.absabs
math.maxmax
math.minmin
math.roundround
math.floorfloor
math.ceilceil
math.sqrtsqrt
math.loglog
math.expexp
math.powpow
math.signsign
bar_indexbar.index
syminfo.tickeridmarket.symbol
syminfo.tickermarket.symbol
syminfo.mintickmarket.point_size
color.greengreen
color.redred
color.blueblue
color.orangeorange
color.yellowyellow
color.purplepurple
color.tealteal
color.graygray
color.greygray
color.whitewhite
color.blackblack
color.limegreen
color.maroonred
color.silvergray
color.aquateal
strategy.longlong
strategy.shortshort
Read every import before you run it. Compare the plain-English description with what your original did, settle each decision, and backtest before you deploy.

Open this page on its own · Markdown

Coming from MQL4 and MQL5

A real import, the ideas side by side, and the names that translate.
3 min

This is a real run of the importer on a small MQL4 and MQL5 script. The result compiles. 11 lines were read: 6 carried over exactly, 6 were adapted and 2 came back as decisions for you.

What you paste · MQL4
#property strict
input int Fast = 20;
input int Slow = 50;
input double Lots = 0.10;
void OnTick()
{
double f = iMA(NULL, 0, Fast, 0, MODE_EMA, PRICE_CLOSE, 0);
double s = iMA(NULL, 0, Slow, 0, MODE_EMA, PRICE_CLOSE, 0);
if (f > s && OrdersTotal() == 0)
OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, Ask - 250 * Point, Ask + 500 * Point);
}
What you get back
1strategy "Imported expert advisor"
2market: EURUSD
3bars: 1h
4
5input Fast = 20
6input Slow = 50
7input Lots = 0.1 lots
8
9f = ema(close, Fast)
10s = ema(close, Slow)
11
12when f > s and trades.open().len == 0:
13buy size: Lots, stop: close - 250 * market.point_size, target: close + 500 * market.point_size

Line by line

StatusYour lineWhat happened
Exactinput int Fast = 20 ;an input carried over
Exactinput int Slow = 50 ;an input carried over
Exactinput double Lots = 0.10 ;an input carried over
Adaptedvoid OnTick ( )OnTick became the script body, which runs once per bar; add evaluate: tick to run on every tick
Exactdouble f = iMA ( NULL , 0 , Fast , 0 , MODE_EMAa variable carried over
Exactdouble s = iMA ( NULL , 0 , Slow , 0 , MODE_EMAa variable carried over
Adaptedf > s && OrdersTotal ( ) == 0OrdersTotal() became the number of open trades
Your callSymbol ( )Symbol() has no equivalent yet
AdaptedAskAsk became the close: a backtest here has one price per bar, and live trading uses the right side of the spread
AdaptedAsk - 250 * PointAsk became the close: a backtest here has one price per bar, and live trading uses the right side of the spread
AdaptedAsk + 500 * PointAsk became the close: a backtest here has one price per bar, and live trading uses the right side of the spread
ExactOrderSend ( Symbol ( ) , OP_BUY , Lots , Ask , 3 ,the order carried over with its stop and target
Adaptedif ( f > s && OrdersTotal ( ) == 0 ) OrderSend (a condition that places orders became a rule
Your callthe script headeran expert advisor runs on whatever chart it is attached to, so EURUSD on 1h was filled in: set the ones you want

How the ideas translate

In MQL4 and MQL5In AlgoBarsX
input int Fast = 20;input Fast = 20
input double Lots = 0.10;input Lots = 0.1 lots
iMA(NULL, 0, Fast, 0, MODE_EMA, PRICE_CLOSE, 0)ema(close, Fast)
OrdersTotal() == 0trades.open().len == 0
OrderSend(Symbol(), OP_BUY, Lots, Ask, 3, sl, tp)buy size: Lots, stop: …, target: …
Pointmarket.point_size
PERIOD_H1, PERIOD_D11h, 1d
void OnTick()the body of the script. Add evaluate: tick to the header if it must run inside the bar.
Tip. Stops written as Ask - 250 * Point carry over literally. They read better, and survive gaps better, as distances: stop: 250 points.

Names the importer translates for you

Their nameAlgoBarsX
mode_smasma
mode_emaema
mode_smmasmma
mode_lwmawma
price_closeclose
price_openopen
price_highhigh
price_lowlow
price_medianhl2
price_typicalhlc3
price_weightedohlc4
mathabsabs
mathmaxmax
mathminmin
mathroundround
mathfloorfloor
mathceilceil
mathsqrtsqrt
mathloglog
mathexpexp
mathpowpow
mathsignsign
_symbolmarket.symbol
symbolmarket.symbol
_pointmarket.point_size
pointmarket.point_size
barsbar.index
period_m11m
period_m55m
period_m1515m
period_m3030m
period_h11h
period_h44h
period_d11d
period_w11w
period_mn11M
Read every import before you run it. Compare the plain-English description with what your original did, settle each decision, and backtest before you deploy.

Open this page on its own · Markdown

Coming from NinjaScript

A real import, the ideas side by side, and the names that translate.
3 min

This is a real run of the importer on a small NinjaScript script. The result compiles. 26 lines were read: 5 carried over exactly, 1 were adapted and 4 came back as decisions for you.

What you paste · NinjaScript
namespace NinjaTrader.NinjaScript.Strategies
{
public class MacdMomentum : Strategy
{
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Name = "MACD Momentum";
}
}
protected override void OnBarUpdate()
{
if (CrossAbove(EMA(Close, 12), EMA(Close, 26), 1))
{
SetStopLoss(CalculationMode.Ticks, 40);
SetProfitTarget(CalculationMode.Ticks, 80);
EnterLong();
}
if (CrossBelow(EMA(Close, 12), EMA(Close, 26), 1))
{
ExitLong();
}
}
}
}
What you get back
1strategy "MACD Momentum"
2market: EURUSD
3bars: 1h
4
5input risk = 1%
6
7when crosses_above(ema(close, 12), ema(close, 26)):
8buy risk: risk, stop: 40 points, target: 80 points
9
10when crosses_below(ema(close, 12), ema(close, 26)):
11close_all side: long

Line by line

StatusYour lineWhat happened
ExactSetStopLoss ( CalculationMode.Ticks , 40 ) ;a stop in ticks became points
Your call; SetProfitTarget ( CalculationMode.Ticks , 80 )this line has no equivalent yet
ExactSetProfitTarget ( CalculationMode.Ticks , 80 ) ;a stop in ticks became points
Your call; EnterLong ( ) ; }this line has no equivalent yet
AdaptedEnterLong ( ) ; } ifNinjaTrader sizes an order by the strategy settings, so this one risks a set share of the balance
Your call; } if ( CrossBelow (this line has no equivalent yet
Exactif ( CrossAbove ( EMA ( Close ,a condition became a rule
ExactExitLong ( ) ; } }an exit carried over
Your call; } } }this line has no equivalent yet
Exactif ( CrossBelow ( EMA ( Close ,a condition became a rule

How the ideas translate

In NinjaScriptIn AlgoBarsX
OnBarUpdate()the body of the script
EMA(Close, 12)ema(close, 12)
CrossAbove(a, b, 1)crosses_above(a, b)
SetStopLoss(CalculationMode.Ticks, 40)stop: 40 points, on the order itself
SetProfitTarget(CalculationMode.Ticks, 80)target: 80 points
EnterLong()buy
ExitLong()close_all side: long
Instrument, TickSizemarket.symbol, market.point_size
Tip. Set a stop with SetStopLoss before the entry. The import sizes the trade by risk, and a risk-based order needs a stop to measure from. The C# around the strategy (namespaces, State handling) comes back as notes, not code.

Names the importer translates for you

Their nameAlgoBarsX
currentbarbar.index
instrumentmarket.symbol
ticksizemarket.point_size
nullna
Read every import before you run it. Compare the plain-English description with what your original did, settle each decision, and backtest before you deploy.

Open this page on its own · Markdown

Coming from EasyLanguage

A real import, the ideas side by side, and the names that translate.
3 min

This is a real run of the importer on a small EasyLanguage script. The result compiles. 6 lines were read: 3 carried over exactly, 3 were adapted and 1 came back as decisions for you.

What you paste · EasyLanguage
Inputs: FastLen(20), SlowLen(50);
Variables: FastAvg(0), SlowAvg(0);
FastAvg = XAverage(Close, FastLen);
SlowAvg = XAverage(Close, SlowLen);
If FastAvg crosses over SlowAvg then Buy next bar at market;
If FastAvg crosses under SlowAvg then Sell next bar at market;
What you get back
1strategy "Imported EasyLanguage strategy"
2market: EURUSD
3bars: 1h
4
5input FastLen = 20
6input SlowLen = 50
7
8state FastAvg = 0
9state SlowAvg = 0
10
11FastAvg = ema(close, FastLen)
12SlowAvg = ema(close, SlowLen)
13
14when crosses_above(FastAvg, SlowAvg):
15buy size: 1 lot
16
17when crosses_below(FastAvg, SlowAvg):
18close_all side: long

Line by line

StatusYour lineWhat happened
ExactFastAvg = XAverage ( Close , FastLen ) ;a calculation carried over
ExactSlowAvg = XAverage ( Close , SlowLen ) ;a calculation carried over
ExactBuy next bar at market ;an order at market carried over
AdaptedIf FastAvg crosses over SlowAvg then Buy next bar at market ;a condition that places orders became a rule
AdaptedSell next bar at market ;sell closed the open position, which became close_all on that side
AdaptedIf FastAvg crosses under SlowAvg then Sell next bar at market ;a condition that places orders became a rule
Your callthe script headerEasyLanguage carries no market or bar size, so EURUSD on 1h was filled in: set the ones you want

How the ideas translate

In EasyLanguageIn AlgoBarsX
Inputs: FastLen(20);input FastLen = 20
Variables: FastAvg(0);state FastAvg = 0
XAverage(Close, FastLen)ema(close, FastLen)
Average, WAveragesma, wma
If a crosses over b then …when crosses_above(a, b):
Buy next bar at market;buy. Market orders already fill at the next bar's open.
Sell next bar at market;close_all side: long
CurrentBarbar.index
Tip. EasyLanguage variables become state values. Where one is simply recalculated every bar, you can delete the state line and keep the assignment.

Names the importer translates for you

Their nameAlgoBarsX
averagesma
xaverageema
waveragewma
stddevstdev
standarddevstdev
truerangetrue_range
avgtruerangeatr
absvalueabs
maxlistmax
minlistmin
squarerootsqrt
expvalueexp
powerpow
ceilingceil
linearregvaluelinreg
cclose
oopen
hhigh
llow
vvolume
currentbarbar.index
barnumberbar.index
pi3.14159265
rangebar.range
avgpriceohlc4
medianpricehl2
typicalpricehlc3
Read every import before you run it. Compare the plain-English description with what your original did, settle each decision, and backtest before you deploy.

Open this page on its own · Markdown

Coming from thinkScript

A real import, the ideas side by side, and the names that translate.
3 min

This is a real run of the importer on a small thinkScript script. The result compiles. 8 lines were read: 7 carried over exactly, 1 were adapted and 0 came back as decisions for you.

What you paste · thinkScript
input fastLength = 20;
input slowLength = 50;
def fast = ExpAverage(close, fastLength);
def slow = ExpAverage(close, slowLength);
plot FastLine = fast;
plot SlowLine = slow;
AddOrder(OrderType.BUY_TO_OPEN, fast crosses above slow);
AddOrder(OrderType.SELL_TO_CLOSE, fast crosses below slow);
What you get back
1strategy "Imported study"
2market: EURUSD
3bars: 1h
4
5input risk = 1%
6input fastLength = 20
7input slowLength = 50
8
9fast = ema(close, fastLength)
10slow = ema(close, slowLength)
11
12when crosses_above(fast, slow):
13buy risk: risk, stop: atr(14) * 2, target: 2R
14
15when crosses_below(fast, slow):
16close_all side: long
17
18plot fast as FastLine
19plot slow as SlowLine

Line by line

StatusYour lineWhat happened
Exactinput fastLength = 20the input fastLength carried over
Exactinput slowLength = 50the input slowLength carried over
Exactdef fast = ExpAverage(close, fastLength)fast carried over
Exactdef slow = ExpAverage(close, slowLength)slow carried over
Exactplot FastLine = fastthe plot FastLine carried over
Exactplot SlowLine = slowthe plot SlowLine carried over
AdaptedAddOrder(OrderType.BUY_TO_OPEN, fast crosses above slow)thinkorswim sizes an order by the chart settings, so this one risks a set share of the balance with an ATR stop: set the size you want
ExactAddOrder(OrderType.SELL_TO_CLOSE, fast crosses below slow)a closing order carried over

How the ideas translate

In thinkScriptIn AlgoBarsX
input fastLength = 20;input fastLength = 20
def fast = ExpAverage(close, fastLength);fast = ema(close, fastLength)
plot FastLine = fast;plot fast as FastLine
fast crosses above slowcrosses_above(fast, slow)
AddOrder(OrderType.BUY_TO_OPEN, cond)when cond: with buy under it
AddOrder(OrderType.SELL_TO_CLOSE, cond)when cond: with close_all side: long under it
yes, notrue, false
BarNumber()bar.index
Tip. thinkScript orders carry no stop or size, so the import adds a risk input with a stop of two ATRs and a 2R target. Check those three numbers before anything else.

Names the importer translates for you

Their nameAlgoBarsX
yestrue
nofalse
doublenumber
barnumberbar.index
bar_numberbar.index
getsymbolmarket.symbol
Read every import before you run it. Compare the plain-English description with what your original did, settle each decision, and backtest before you deploy.

Open this page on its own · Markdown

Coming from Python

A real import, the ideas side by side, and the names that translate.
3 min

This is a real run of the importer on a small Python script. The result compiles. 5 lines were read: 4 carried over exactly, 1 were adapted and 0 came back as decisions for you.

What you paste · Python · pandas-ta
import pandas_ta as ta
df["fast"] = ta.ema(df["close"], length=20)
df["slow"] = ta.ema(df["close"], length=50)
df["rsi"] = ta.rsi(df["close"], length=14)
df["long"] = (df["fast"] > df["slow"]) & (df["rsi"] < 70)
What you get back
1indicator "Imported Python script"
2pane: price
3
4fast = ema(close, 20)
5slow = ema(close, 50)
6rsi_value = rsi(close, 14)
7long = fast > slow and rsi_value < 70

Line by line

StatusYour lineWhat happened
Exactdf["fast"] = ta.ema(df["close"], length=20)a calculation carried over
Exactdf["slow"] = ta.ema(df["close"], length=50)a calculation carried over
Adapteddf["rsi"] = ta.rsi(df["close"], length=14)rsi is the name of a built-in here, so it became rsi_value
Exactdf["rsi"] = ta.rsi(df["close"], length=14)a calculation carried over
Exactdf["long"] = (df["fast"] > df["slow"]) & (df["rsi"] < 70)a calculation carried over

How the ideas translate

In PythonIn AlgoBarsX
df["fast"] = ta.ema(df["close"], length=20)fast = ema(close, 20)
ta.rsi(df["close"], length=14)rsi(close, 14)
(a > b) & (c < 70)a > b and c < 70
a column named rsirenamed to rsi_value, so it does not hide the function
df["close"].shift(1)close[1]
df["high"].rolling(20).max()highest(high, 20). Rolling calculations come back as a decision, so you pick the function.
Tip. A data-frame script has no orders in it, so it comes back as an indicator. Add when rules to turn it into a strategy.

Names the importer translates for you

Their nameAlgoBarsX
mommomentum
natratr
willrwilliams_r
Read every import before you run it. Compare the plain-English description with what your original did, settle each decision, and backtest before you deploy.

Open this page on its own · Markdown

Language Basics

7 guides · Values and units, history, operators, inputs, state, control flow, functions and types

Values, units and types

Percent, pips, R and money are real types, not bare numbers.
4 min

Most mistakes in trading code are unit mistakes. AlgoBarsX makes the unit part of the value, and the compiler checks it.

AlgoBarsX
stop_distance = 20 pips
tick_buffer = 5 points
risk_now = 1%
cash_risk = $200
wait = 30m
opens_at = 08:00
level = high + 2 pips
two_percent = 2% of account.balance
You writeIt means
1%, 0.5%A percent. No space before the sign. Use 2% of account.balance to say what it is a percent of. Where the base is unclear the compiler asks: “1% of what?” (AS0305)
20 pips, 5 pointsA distance, converted with each market's own pip and point size.
2R, 1.5RA multiple of the trade's initial stop distance. Valid only where a trade has a stop.
$200Money in the account currency.
1 lot, 0.3 lotsPosition size.
10 barsA count of bars.
30s 15m 4h 1d 1w 1MA length of time. The same words are bar sizes.
08:00, 2026-01-15A time of day and a date.
#22c55e, green.fade(80)A colour. Named colours can fade and blend.
1_000_000A number. Underscores are allowed between digits.
naNo value. Test with is_na, replace with nz.

A stop written as a bare number is caught before anything runs: “stop 25 has no unit. Did you mean 25 pips?” (AS0302). A price level and a distance are different things, and the compiler knows which one an option expects.

Text with live values

Text in double quotes can include any expression in braces, with an optional format after a colon. Write {{ for a literal brace.

AlgoBarsX
on bar close:
log "RSI {rsi(close, 14):0.0} on {market.symbol}"

Units follow the value, not the text

The engine works a unit out from the code. It does not look for the word “pips” in what you typed.

  • A price with a distance taken off it is still a price. stop: lowest(low, 10) - 3 pips is a level on the chart.
  • One price taken from another is a distance.
  • A distance stays a distance when you scale it, as in atr(14) * 2.
  • A unit held in an input travels with it. After input risk = 1%, the order risk: risk risks one percent, exactly as if you had written 1%.

All eight units are listed under Units.

Open this page on its own · Markdown

Series and history

Every value has a past. Read it without looking ahead.
3 min

close is not one number. It is a series with a value on every bar. Square brackets read earlier bars: close[1] is the previous bar's close. A value at a bar never depends on a later bar, and the test suite proves it by rewriting the future and checking the past did not move.

AlgoBarsX
prev_close = close[1]
range_high = highest(high, 20)[1]
rising = close > close[1] and close[1] > close[2]
recent = was(rsi(close, 14) < 30, within: 5 bars)
steady = held(close > ema(close, 50), for: 3 bars)
since_cross = bars_since(crosses_above(close, ema(close, 50)))
safe = nz(close[500], close)
  • was is true if a condition was true at some point in recent bars. held is true if it has been true for consecutive bars.
  • crosses_above, crosses_below and crosses detect crossings. starts and ends are true on the bar a condition becomes true or stops being true.
  • bars_since counts bars since a condition was last true.
  • Reading further back than the data goes gives na. nz supplies a fallback.
  • Reading forward is an error, not a bug waiting to happen: “close[-1] would read a future bar. History counts back from the current bar: close[1] is the previous bar.” (AS0203)
  • Indicator calls update on every bar, even when their line sits in a branch that did not run, so a reading is never stale.

Built-in price series: open high low close volume time hl2 hlc3 ohlc4, plus facts about the bar such as bar.index, bar.confirmed and bar.range. See Bar variables.

Open this page on its own · Markdown

Operators and expressions

and, or, not, between, in, if-then-else.
2 min
AlgoBarsX
in_band = rsi(close, 14) between 40 and 60
morning = hour in 8..11
bias = if close > ema(close, 200) then 1 else -1
power = 2 ** 3
calm = not (atr(14) > atr(14)[10])
first_hour = time_of_day between 08:00 and 09:00
OperatorMeaning
+ - * / % **Arithmetic. ** is power and groups from the right, so 2 ** 3 ** 2 is 512.
== != < <= > >=Comparison.
and or notLogic, in words.
x between a and bTrue when x is inside the range.
x in 8..11True when x is in a range or a list.
if c then a else bChooses a value inside an expression.
2% of account.balanceTurns a percent into an amount.
+= -= *= /=Update a state value in place.

Time variables available everywhere: hour, minute, day_of_week and time_of_day.

Open this page on its own · Markdown

Inputs and constants

What the person running the script may change.
2 min

An input becomes a setting in the script's panel. Its type comes from its default value, so input risk = 1% is a percent and input higher_tf = 4h is a bar size. A const is fixed.

AlgoBarsX
input fast = 20, label: "Fast length", min: 2, max: 500, group: "Trend"
input source = close, label: "Source"
input higher_tf = 4h, label: "Higher timeframe"
input session = "london", options: ["london", "new_york", "asia"]
input risk = 1%, min: 0.1%, max: 5%, step: 0.1%
input show_zones = true, group: "Display"
input zone_color = blue.fade(70), group: "Display", visible_if: show_zones
const RISK_CAP = 2%
OptionWhat it does
labelThe name shown in the panel.
min, max, stepLimits and step size.
optionsA fixed list of choices.
groupGroups inputs under a heading.
visible_ifShows this input only when another one is on.

An input nobody reads is flagged as a hint (AS0601).

Open this page on its own · Markdown

Variables and state

Values recalculated each bar, and values that survive between bars.
2 min

A plain assignment such as trend_up = close > ema(close, 50) is worked out again on every bar. A state value is set once and keeps whatever you last put in it, which is how you count things or remember a price.

AlgoBarsX
state triggers = 0
state last_entry: price = na
when close > open:
triggers += 1
last_entry = close
on day change:
triggers = 0

You can annotate a type when the default does not say enough: state last_entry: price = na.

Open this page on its own · Markdown

Control flow

if, for, match, break and continue.
2 min
AlgoBarsX
if regime == Regime.trending:
risk_now = 1%
elif regime == Regime.volatile:
risk_now = 0.5%
else:
risk_now = 0.25%
for level in levels:
if close > level.price:
level.touched += 1
for i in 0..50:
if i > 10:
break
continue
match regime:
Regime.trending: log "trending"
Regime.ranging: log "ranging"
  • if / elif / else choose between blocks.
  • for x in list and for i in 0..50 loop. break and continue work as you expect.
  • match picks a branch by value, which reads well with an enum.

Open this page on its own · Markdown

Functions, types, enums and lists

Simple on top, a full language underneath.
4 min
AlgoBarsX
type Level:
price: price
touched: int = 0
formed_at: time
enum Regime: trending, ranging, volatile
fn swing_strength(len: int) -> number:
up = highest(high, len) - close
down = close - lowest(low, len)
return (down - up) / atr(14)
action fn enter_long(size_risk: percent = 1%) -> bool:
buy risk: size_risk, stop: 20 pips, target: 2R
return true
  • fn defines a pure function. It calculates and returns a value.
  • action fn may place orders, so it can only be called where orders are allowed. A plain fn that tries to trade is an error (AS0403).
  • type defines a record with named, typed fields and optional defaults. enum defines a fixed set of names.
  • Parameters can have types and defaults: fn f(source: series<number> = close, length: int = 20) -> number.

Lists and lambdas

AlgoBarsX
levels.push(Level(price: high, formed_at: time))
levels = levels.filter(l => l.touched == 0).keep_last(50)
ranked = levels.sort_by((a, b) => a.price - b.price)

Lists support push, pop, remove, filter, map, sort_by, keep_last, first, last, len and contains, plus the aggregates sum, mean, min and max. A lambda is written x => expression.

Open this page on its own · Markdown

Strategies

11 guides · Header settings, rules, confirmations, sequences, orders, sizing, management and guards

The header and its settings

Markets, bar size, limits and trading hours.
3 min
AlgoBarsX
strategy "Language Tour"
markets: EURUSD, GBPUSD
bars: 15m
evaluate: bar_close
max_open: 3
max_open_per_side: 2
direction: both
opposite: reverse
pyramiding: 3
min_distance: 20 pips
max_daily_loss: 3%
max_drawdown: 10%
trade_only: within sessions london, new_york

Every setting, with its type and default:

SettingTypeDefaultWhat it does
marketsymbolchart symbolSymbol the script runs on.
marketslist<symbol>Several symbols; alerts evaluate each independently.
barsbartypechart barsBar type: timeframe, range(n), xray(n), renko(n) or heikin_ashi(tf).
evaluatestringbar_closebar_close (default, never repaints) or tick.
panestringpriceprice, new or a named pane.
max_openint1Open trades allowed at once.
max_open_per_sideintOpen trades allowed per side.
directionstringbothboth, long or short.
oppositestringignoreOn an opposite signal: close, reverse, ignore or hedge (where the venue supports it).
warmupintBars required before rules run (computed by the compiler when omitted).
repeatstringonce per baronce, once per bar, once per bar close or every time.
cooldownduration | barsMinimum time or bars between notifications.
expiresdate | durationWhen the alert stops.
checkdurationevery 1mHow often account-only alerts are checked.
show_on_chartbooltrueDraw fire points, watched levels and live status on the chart.
max_daily_losspercent | moneyPause the deployment after this loss in a day.
max_drawdownpercent | moneyPause the deployment at this drawdown.
max_total_riskpercentRisk allowed across open trades.
pyramidingint1Entries allowed in the same direction.
min_distancedistanceSmallest distance between pyramided entries.
trade_onlysessionsSessions in which the strategy may open trades.

Limits are checked when an entry fills, not when it is placed (E19). With trade_only, entries are only created inside the listed sessions, while exits and management carry on outside them (E22). The named sessions are sydney, tokyo, asia, frankfurt, london and new_york.

Open this page on its own · Markdown

Rules: when something is true, do something

The when rule and its timing modifiers.
3 min

A rule is when <condition> [modifiers]: followed by what to do. Name a rule with as to read its counters later, such as long_entry.triggers.

AlgoBarsX
when long_setup.passed as long_entry every 4th:
buy risk: risk, stop: atr(14) * 1.5, target: 3R
when starts(long_setup.passed) skip first 3 max 2 per day cooldown 30m:
triggers += 1
if triggers % 4 == 0:
buy risk: 0.5%, stop: atr(14) * 1.5, target: 3R

Modifiers say when a rule may fire, on the rule itself, so there are no counters to build by hand:

ModifierWhat it does
every <ordinal> | every barAct on every Nth trigger, or count every bar the condition holds.
skip first <n>Ignore the first N triggers, then act on every trigger.
max <n> per <period>Cap actions per day, session, hour or week.
cooldown <duration | n bars>Ignore triggers for a while after acting.
once per barIn tick mode, act at most once per bar.
within sessions <name>, ...Only trigger inside the named sessions.
from <time> to <time> [zone]Only trigger inside a daily time window.

Open this page on its own · Markdown

Confirmations

Name each condition a setup needs.
2 min

A confirmations block lists named conditions and how many must agree: require: all or require: at least N. It gives you .passed to use in a rule.

AlgoBarsX
confirmations long_setup:
trend: trend_up
momentum: rsi(close, 14) > 55
volume: volume > sma(volume, 20) * 1.5
structure: break_of_structure(direction: up)
higher_tf_trend: h4.close > ema(h4.close, 50)
ribbon_up: ribbon.up
require: at least 5

The backtest report breaks trades down by which confirmations agreed, so you can see which ones earn their place.

Open this page on its own · Markdown

Sequences: setups that happen in steps

Sweep, reclaim, retest, inside a bar limit.
2 min

A sequence waits for its steps in order, within a number of bars. Later steps can refer to the bar where an earlier step happened, such as sweep.high. reset_if abandons the attempt. The sequence gives you .completed.

AlgoBarsX
sequence liquidity_grab within 30 bars:
step sweep: low < lowest(low, 20)[1]
step reclaim: close > sweep.high
step retest: low <= reclaim.close and close > reclaim.close
reset_if: close < sweep.low

Examples: Sweep and Reclaim, Renko Pullback, State Machine Momentum.

Open this page on its own · Markdown

Orders

Market, limit, stop, close, modify, cancel.
4 min
AlgoBarsX
when was(trend_up, within: 5 bars) and held(close > open, for: 3 bars) every bar:
buy limit: lowest(low, 5), size: 1 lot, expires: 10 bars
buy stop: high + 2 pips, risk: 0.5%, stop_loss: low - 2 pips, target: 2R, ghost: true
sell market: GBPUSD, size: 0.3 lots
when history.today.pnl < -(2% of account.balance) or account.margin_level < 150%: close_all
for trade in trades.open(tag: "breakout"):
if trade.r >= 3 and rsi(close, 14) > 75:
close trade, size: 50%
for trade in trades.open(side: long):
modify trade, stop: trade.entry_price
cancel orders.pending(tag: "grid")
  • buy and sell with no limit: or entry stop: are market orders. They fill at the next bar's open (E1).
  • buy limit: price places a pending limit order. buy stop: price places a pending stop order, and its protective stop is then stop_loss:.
  • expires: cancels a pending order after a number of bars or a length of time (E17).
  • ghost: true keeps the stop and target off the broker. AlgoBars enforces them instead.
  • tag: labels an order and its trade, so you can close, cancel or report on a group.
  • close, close_all, modify and cancel act on open trades and pending orders.

What happens when a signal arrives opposite an open trade is the header setting opposite: ignore (the default), close, reverse or hedge (E18).

Open this page on its own · Markdown

Sizing and risk

State what you are willing to lose. Size follows.
3 min

Give an order a risk: as a percent of the balance or as money, and a stop. The size is worked out for you:

size = risk amount ÷ (stop distance × contract size × quote-to-account rate)

It is rounded down to the lot step and held between the market's minimum and maximum lot. If the minimum lot would carry more than you asked for, the trade still opens at the minimum lot and is marked “above requested risk” with the risk it actually carries (E11).

  • Distances in pips, points or R are measured from the actual fill price, so a gap moves the stop and target with the entry (E9).
  • A risk-based order with no stop is an error: “Risk-based size needs a stop to measure risk from.” (AS0304)
  • size_for tells you the lot size an entry would use, without placing it.
  • You can also size directly with size: 1 lot.

Open this page on its own · Markdown

Trade management

Breakeven, partial closes, trailing stops and exits.
3 min

Management is written under the order it belongs to, as an indented block after the order line.

AlgoBarsX
when liquidity_grab.completed from 08:00 to 11:00 Europe/London:
buy risk: 1%, stop: liquidity_grab.sweep.low - 3 points, target: 2R + 5 pips, tag: "breakout":
breakeven at: 1R, offset: 2 pips
partial 30% at: 1.5R
partial 30% at: 2.5R
trail by: atr(14), after: 2R
exit after: 48 bars
exit when: crosses_below(close, ema(close, 20))
LineWhat it doesRule
breakevenMoves the stop to the entry price, plus an optional offset, once a level is reached.E13
partialCloses part of the original size at a level. Each partial fires once.E15
trailFollows the best price reached by a distance, after a level. It only ever tightens.E14
exitCloses after a number of bars, a length of time, or when a condition is true.E16

You can also manage trades from anywhere with a loop over trades.open(...), using close and modify. Example: Active Trade Manager.

Rules about a trade that is still open

An open trade knows how long it has been open and where it stands. trades.last() is the trade being held when there is one, bars_open counts its bars, and r is its result so far measured against its own risk.

AlgoBarsX
when close > open:
buy risk: 1%, stop: 50 pips, target: 4R
when trades.last().bars_open > 3:
close_all

Open this page on its own · Markdown

Loss guards and limits

What stops a strategy, and for how long.
2 min
  • max_daily_loss: at each bar close, the day's closed profit plus open profit is compared with the limit. When it is reached, all trades close and pending orders are cancelled at the next bar's open, and new entries are rejected until the next UTC day.
  • max_drawdown works the same way against the highest equity reached, and pauses the deployment until you resume it.
  • max_open, max_open_per_side, pyramiding, max_total_risk and min_distance reject an entry, with a reason, at the moment it would fill.

The rule is E20. You can also write your own guard as an ordinary rule:

AlgoBarsX
when history.today.pnl < -(2% of account.balance) or account.margin_level < 150%: close_all

Open this page on its own · Markdown

Events

Run code when something happens.
2 min
AlgoBarsX
on start:
log "starting on {market.symbol}"
on bar close:
log "bar {bar.index}"
on fill(order):
log "filled {order.size}"
on exit(trade):
log "{trade.tag} closed at {trade.r:0.00}R after {long_entry.triggers} triggers"
on session open "new_york":
log "New York is open"
on day change:
triggers = 0
EventWhen it runs
on start:Runs once before the first evaluated bar.
on bar close:Runs on every confirmed bar.
on tick:Runs on every price update (evaluate: tick).
on fill(order):Runs when an order fills.
on exit(trade):Runs when a trade closes, with trade.pnl, trade.r and trade.reason.
on session open "<name>":Runs when a session opens.
on day change:Runs at each calendar day boundary.
on render(canvas):Custom vector drawing for the visible range.

on tick needs a script that evaluates on ticks (AS0404). See Bar close or every tick.

Open this page on its own · Markdown

Bar close or every tick

One header line changes when the script runs.
2 min

By default a script runs after each bar closes. With evaluate: tick it runs at every point of the price path, and market orders fill at the price that triggered them.

AlgoBarsX
strategy "Tick Scalper"
market: XAUUSD
bars: 1m
evaluate: tick
max_open: 1
input max_stretch = 2.0
when crosses_above(close, vwap()) once per bar cooldown 2 bars:
buy risk: 0.5%, stop: 30 points, target: 1.5R, ghost: true
on tick:
if not bar.confirmed and close < vwap() - atr(14) * max_stretch:
close_all side: long
  • Inside a forming bar, prices are live and indicators are not. close, high and low move with the tick, while indicator values stay as they were at the last bar close. Nothing repaints.
  • bar.confirmed is false during a tick and true at the close.
  • In a backtest, the 1-minute bars inside each bar supply the price path. When a bar has no finer data stored, its own path is used and the run is labelled “approximate intrabar”, listing the bars affected.

Rules: E2 and E6.

Open this page on its own · Markdown

Other markets, bar sizes and bar types

Higher timeframes, other symbols, Renko, Heikin Ashi and X-Ray bars.
3 min
AlgoBarsX
h4 = bars(bars: higher_tf)
gold = bars(XAUUSD, bars: 15m)
gold_atr = atr(14, on: gold)
cov = data.coverage(EURUSD, bars: range(10))
spread_z = zscore(log(close_of(EURUSD) / close_of(GBPUSD)), 100)
first_hour = time_of_day between 08:00 and 09:00
recent_high = intrabar(1m).high.max()
  • bars reads another bar size, another symbol, or both. A higher bar's value appears only once its candle has closed, so a 5-minute rule cannot peek at a 4-hour bar early.
  • intrabar reads the finer bars inside the current one. close_of is a shortcut for another symbol's close.
  • Many functions take on: to calculate on another set of bars, such as atr(14, on: gold).
  • data.coverage tells a script how much data it actually has, and whether it is exact.
AlgoBarsX
coverage = data.coverage(EURUSD, bars: range(10))
enough_history = coverage.exact and coverage.bars >= 5000

Several markets in one strategy

AlgoBarsX
strategy "EURUSD and GBPUSD Mean Reversion"
markets: EURUSD, GBPUSD
bars: 1h
max_open: 2
input lookback = 200
input entry_z = 2.0
input exit_z = 0.5
eur = bars(EURUSD)
gbp = bars(GBPUSD)
hedge = beta(returns(eur.close), returns(gbp.close), lookback)

Full example: EURUSD and GBPUSD Mean Reversion. Orders take market: to say which symbol they are for.

Other bar types

The header's bars: accepts more than a time: renko, heikin_ashi, range and xray.

AlgoBarsX
strategy "Renko Pullback"
market: US500
bars: renko(5)
AlgoBarsX
indicator "X-Ray Flow Bands"
bars: xray(20)

Open this page on its own · Markdown

Testing and Going Live

3 guides · Reading the report, demo and live deployments, and generated strategies

Reading the backtest report

Every number, what it means and how it is worked out.
5 min

Everything in a report is derived from the trades the engine actually filled and the equity at each bar close, so any number can be traced back to a trade. Costs are never added or assumed: profit is the price difference (E12).

How it went

NumberWhat it means
TradesHow many trades completed. Trades still open when the test ends are closed at the last bar's close and marked “open at end” (E24).
Net profitGross profit minus gross loss.
Win rateWinning trades as a share of all trades.
Profit factorGross profit ÷ gross loss. What it made for every unit it lost.
ExpectancyThe average result per trade, in money and in R. In R it is the mean of every trade's R outcome.
PayoffAverage win ÷ average loss.

What it cost

NumberWhat it means
Max drawdownThe deepest fall from a high in equity, in money and percent, with how many bars it stayed below that high.
Recovery factorNet profit ÷ max drawdown.
SharpeMean return ÷ the deviation of returns, annualised.
SortinoThe same, counting only downside deviation.
SQN√(number of trades) × mean R ÷ deviation of R. How steady the R outcomes were.
Time in marketThe share of bars with a trade open.
CAGR, Calmar, Ulcer indexAlso calculated by the engine: compound annual growth, growth ÷ max drawdown percent, and the root mean square of drawdown percentages.

How the trades behaved

NumberWhat it means
Bars per tradeAverage length of a trade.
Average run-upThe best each trade saw while it was open (MFE).
Average drawdown in tradeThe worst each trade saw while it was open (MAE).
Streaks, largest win and lossThe longest run of wins and of losses, and the single biggest of each.
R distributionHow many trades ended in each band of R.

Breakdowns

By the rule that opened the trade, by how the trade ended, by the confirmations that agreed, by side, by tag and by month. Name your rules with as and tag your orders, and these tables become much more useful.

Labels worth noticing

  • Above requested risk: the minimum lot carried more risk than the order asked for (E11).
  • Approximate intrabar: a tick-evaluated run had no finer data for some bars, which are listed (E2).
  • Unfilled: a market order created on the last bar of the test (E1).
Read this before trusting any number. Backtests are hypothetical. They use historical data and contain no spread, commission, fees, swaps or slippage, so live results will differ. Past performance does not guarantee future results.

Open this page on its own · Markdown

Demo and live deployments

What changes when a script runs for real, and what does not.
3 min

Deploying a strategy runs the same script on a demo or live account. The runner evaluates each closed bar, hands out instructions, and waits to be told what actually happened.

  • The broker decides fills. A backtest may decide a fill itself. Live, a trade exists only once the broker has confirmed it, and an instruction is never sent twice.
  • Restarts are safe. Open trades and their management, rule counters, sequences part way through and pending orders live in a snapshot. After a restart the runner replays recent bars to warm the indicators back up and continues where it left off, so a restart cannot quietly abandon a stop.
  • Demo follows the written rules. Demo deployments fill under the same execution rules as a backtest: a market order fills at the next bar's open, and when a stop and target are both reached in one bar the stop fills first unless finer data says otherwise.
  • Live uses the side that can trade. A buy is triggered and filled on the ask and a sell on the bid. A long trade's stop and target trigger on the bid, a short trade's on the ask (E3, E4, E5). Backtests have no spread, so this is one reason live results differ.
  • Guards still apply. max_daily_loss stops new entries until the next UTC day, and max_drawdown pauses the deployment until you resume it (E20).
  • The deployment chooses where it runs. A script says what it was written for, and that comes filled in, but the market, the bar size, the trade size and the balance to trade belong to the deployment. A strategy written for EURUSD on the hour can be deployed on gold on five-minute bars by changing two fields.
  • Demo or live is said plainly. Demo fills against the AlgoBars engine and costs nothing. Live sends real orders to a real broker.
  • Live sizes the way the test did. The live runner places a stop where the backtest placed it and sizes a trade the same way, so what was tested is what trades.
  • Edits are explained first. Changing a script that is already running shows what the change would do once it is live, before you make it.

Chart replay uses the same runner and the same rules, so what appears in replay is what the script would have done.

You are responsible for a live deployment. AlgoBars is software and connects to your own broker account. It does not hold your funds and does not give financial advice. Trading involves significant risk of loss.

Open this page on its own · Markdown

Letting AlgoBarsX generate a strategy

Composed from the language, compiled and backtested before you see it.
2 min

Generated strategies are not written by a model. Entries, filters, exits and management are assembled from pieces of the language that are known to compile, and every candidate is then compiled and backtested. A strategy is only handed back once it has actually traded, so you never receive something that looks plausible and does nothing. The same seed and the same bars give the same strategy every time.

StrengthWhat you getAlgoBuilder tier
1A plain two-rule strategy.Simple, Basic
2More filters.Standard
3The default middle ground.Balanced
4More structure and management.Advanced
5Confirmations, sequences, higher bar sizes and full trade management.Complex, Extreme

What comes back is ordinary AlgoBarsX. Read its plain-English description, open it in the Terminal and change it.

A generated strategy is a draft to study, not a recommendation. Having traded in a backtest says nothing about how it will do next.

Open this page on its own · Markdown

Troubleshooting

12 guides · The questions people actually ask, answered from the written rules

Why did my order not fill?

Seven reasons, each with the rule behind it.
3 min
  • It was created on the last bar. A market order fills at the next bar's open. With no next bar it is reported as unfilled (E1).
  • Price never reached it. A buy limit fills when the low is at or below its price, a buy stop when the high is at or above it. Sells mirror that (E4).
  • It expired. expires: 10 bars cancels at the close of the tenth bar after it was placed (E17).
  • A limit rejected it. max_open, max_open_per_side, pyramiding, max_total_risk and min_distance are checked when the entry would fill. A rejected entry is recorded with its reason (E19).
  • It was outside trading hours. With trade_only, entries are only created inside the listed sessions (E22).
  • A loss guard had tripped. After max_daily_loss, new entries are rejected until the next UTC day (E20).
  • There was already a trade the other way. The default for opposite is ignore (E18).

Open this page on its own · Markdown

Why does live differ from my backtest?

Costs, the bid and ask, gaps and your broker.
2 min
  • Backtests have no costs. No spread, commission, fees, swaps or slippage. Profit is the price difference (E12).
  • Live trades on the bid and the ask. A buy fills on the ask, a sell on the bid, and stops and targets trigger on the side that can actually trade (E3, E5). A backtest has one price.
  • Gaps move fills. When a bar opens beyond a stop, the fill is the open, not the stop price (E8).
  • The broker decides live fills. A live trade exists only once your broker confirms it. Execution speed and liquidity are outside the script.
  • The data may be thinner. data.coverage tells a script how much history it has and whether it is exact.

Past performance does not guarantee future results.

Open this page on its own · Markdown

The bar reached my target. Why was I stopped out?

When one bar reaches both, the stop fills first.
1 min

When a bar reaches both the stop and the target, the engine walks the 1-minute bars inside it to see which came first (E6). If finer data cannot tell, the stop fills (E7). The engine never picks the flattering answer, so a backtest errs on the side of caution.

Open this page on its own · Markdown

Why is my stop not where I expected?

Distances follow the fill. Levels do not.
1 min
  • A stop written as a distance (25 pips, atr(14) * 2, 2R) is measured from the actual fill price. If the entry fills 8 pips higher after a gap, the stop is 8 pips higher too (E9).
  • A stop written as a level (low[1], 1.0850) stays exactly where you put it. If a gap makes it invalid, for example a long stop at or above the fill, the order is cancelled and recorded as “stop beyond entry” (E10).
  • breakeven and trail move stops during the trade, and a trailing stop only ever tightens (E13, E14).

Open this page on its own · Markdown

Why is my position smaller or bigger than I asked?

Lot steps, minimum lots and “above requested risk”.
1 min

Risk-based size is rounded down to the market's lot step, so it is usually a little under your risk. If it falls below the minimum lot, the trade opens at the minimum lot and is marked “above requested risk”, with the risk it actually carries (E11). Use size_for to see the size before you trade it.

Open this page on its own · Markdown

Why did my backtest stop early?

The test account ran out of money.
1 min

An account with nothing left cannot trade on. When equity is gone, the backtest stops at that bar, closes what was open and marks the run as liquidated, with the bar and the time. Everything after that point did not happen, so the engine does not pretend it did. The replay stops at the same place.

If this surprises you, check the trade size and the stop first. A large fixed lot size on a small starting balance is the usual cause.

Open this page on its own · Markdown

What size does buy trade when I give no size?

The usual amount, set where the script runs.
1 min

A script that says buy and nothing more is a reasonable script. It means “the usual amount”, and the usual amount belongs to wherever the script is run, not to the script. In the Terminal that is the Lot size in the backtest panel and the Trade size when you deploy. When nothing is set anywhere, it is the smallest lot the market deals in.

A script that names a size: or a risk: is never overruled.

Open this page on its own · Markdown

Why was my order for another market refused?

An order is only filled on the market it names.
1 min

An order that names a market the run is not trading is refused, with a reason. Filling it on the current market would be worse than not filling it: a pairs trade would quietly become two orders on one instrument. List every market the strategy trades under markets: in the header. The live runner refuses it too, and says so.

Open this page on its own · Markdown

Why is my indicator empty at the start?

Warm-up.
1 min

An average of 200 bars has nothing to say for the first 199. Each function's reference entry gives its warm-up, and rules do not run until the script's warm-up has passed. The compiler works the warm-up out for you. Set warmup: in the header to override it.

A higher bar size also shows nothing new until its candle closes, by design. A 5-minute rule never sees a 4-hour bar early.

Open this page on its own · Markdown

Why did my alert only fire once?

repeat, cooldown and expires.
1 min

An alert's own settings decide when it may speak again. The default repeat is once per bar. cooldown sets the shortest gap between messages, and expires switches the alert off. Testing an alert lists the messages it sent and the ones it held back, with the reason.

Open this page on its own · Markdown

What does “approximate intrabar” mean?

A tick-evaluated run that lacked finer data for some bars.
1 min

A script with evaluate: tick needs the price path inside each bar. When a bar has no 1-minute data stored, its own open, high, low and close are used instead, the run is labelled “approximate intrabar”, and the affected bars are listed (E2). Treat those stretches with more caution.

Open this page on its own · Markdown

The compiler rejected my script. Now what?

Read the message. It says what to change.
1 min

Every message names the problem, the line and the column, and says what to do. Many carry a one-click fix. Search this page for the code, such as AS0304, or browse Compiler Messages. The most common ones:

  • AS0201 a name the compiler does not know, usually a typo. It suggests the nearest name.
  • AS0302 a number with no unit where a distance is expected.
  • AS0303 and AS0304 an R target or a risk-based size with no stop to measure from.
  • AS0003 a tab used for indentation. Use spaces.
  • AS0401 something in the wrong kind of script, such as an order in an indicator.

Open this page on its own · Markdown

Indicators and Drawing

2 guides · Panes, plots, exported values, 26 drawing commands and the free-form canvas

Writing an indicator

Calculate, draw, and publish values.
3 min
AlgoBarsX
indicator "Trend Ribbon"
pane: price
input fast = 20
input slow = 50
fast_line = ema(close, fast)
slow_line = ema(close, slow)
export up = fast_line > slow_line
export strength = (fast_line - slow_line) / atr(14)
plot fast_line as fast, color: if up then green else red
plot slow_line as slow, color: gray
  • pane: price draws over the price chart. pane: new gives the indicator its own pane.
  • plot draws a series. as gives the plot a name. Colours can depend on a condition.
  • export publishes a value. Anything exported can be read by a strategy, an alert or another indicator that uses this one.

Using an indicator or a library from another script

AlgoBarsX
use indicator "Trend Ribbon" v3 as ribbon (fast: 10, slow: 30)
use library "Quant Toolkit" v2 as qt

You import by name and version, give it a short name with as, and set its inputs in brackets. After that, ribbon.up reads like any other value. A script names the version it uses, so an update to the indicator does not silently change a strategy that depends on it.

Open this page on its own · Markdown

Drawing on the chart

Plots, fills, boxes, Fibonacci, profiles, tables and dashboards.
3 min
AlgoBarsX
plot ema(close, fast) as fast_line, color: if trend_up then green else red, width: 2
plot (high + low) / 2, color: gray, style: step
fill ribbon.fast, ribbon.slow, color: green.fade(80)
hline 70, style: dashed, color: #22c55e
mark arrow_up, at: below, when: crosses_above(close, ema(close, fast)), color: green
label "Entry", at: (bar.index, high)
line from: (bar.index - 20, lowest(low, 20)), to: (bar.index, lowest(low, 20)), extend: right
box id: "range", from: (bar.index - 10, highest(high, 10)), to: (bar.index, lowest(low, 10)), color: blue.fade(85)
bar_color if close > open then green else red
background red.fade(90), when: regime == Regime.volatile
profile rows: 24, range: session, side: right
fib from: (bar.index - 50, lowest(low, 50)), to: (bar.index, highest(high, 50))
dashboard position: top_right, rows: [["Regime", "{regime}"], ["Triggers", "{triggers}"]]

There are 26 drawing commands. Each is documented under Drawing commands.

  • Give a drawing an id: to update the same object on later bars instead of adding a new one.
  • Positions are written as (bar, price) pairs, such as (bar.index - 20, lowest(low, 20)).
  • Colours: ten named colours, hex values, .fade(percent), and gradient, linear_gradient and radial_gradient.

The canvas

When no command fits, on render(canvas) gives you a vector canvas for the visible range: paths, lines, fills and text.

AlgoBarsX
on render(canvas):
for z in levels:
shape = canvas.path()
shape.move_to(z.formed_at, z.price)
shape.line_to(canvas.last_bar, z.price)
shape.stroke(zone_color, width: 1)
canvas.text("{z.touched}x", at: (canvas.last_bar, z.price), align: right)

Examples: Volatility Regime Canvas, Volume Heatmap, Multi-Timeframe Trend Table, Opening Range Dashboard.

Open this page on its own · Markdown

Alerts

1 guide · Alerts that carry their own check, repeat, cooldown and expiry rules

Writing an alert

The condition, the message, and when it may repeat.
3 min
AlgoBarsX
alert "RSI bullish divergence"
check: every 15m
repeat: once per bar
show_on_chart: true
input rsi_length = 14
input lookback = 30
momentum_now = rsi(close, rsi_length)
lower_low = low < lowest(low, lookback)[1]
higher_rsi = momentum_now > lowest(momentum_now, lookback)[1]
when lower_low and higher_rsi and was(momentum_now < 30, within: 5 bars):
notify "Bullish RSI divergence on {market.symbol}: RSI {momentum_now:0.0}"
SettingWhat it does
checkHow often the condition is checked, such as every 1m.
repeatonce, once per bar (the default), once per bar close or every time.
cooldownThe shortest gap between two messages.
expiresWhen the alert stops watching.
show_on_chartMarks the chart where it fired.

notify sends the message. In version 1 it is delivered in the app and in AI chat. Testing an alert shows you the messages it would have sent and the ones its own settings held back.

Alerts that watch the account, not the chart

AlgoBarsX
alert "Margin and exposure"
check: every 5m
repeat: once
expires: 30d
when account.free_margin < 20% of account.equity or positions.len >= 8:
notify "Free margin {account.free_margin:$0} with {positions.len} open positions"

More: Daily risk guard, Intrabar spike, Tokyo open gap, Distribution shift.

Open this page on its own · Markdown

Libraries

1 guide · Write a function once and import it everywhere, by version

Writing and using a library

Functions and constants you reuse.
2 min
AlgoBarsX
library "Quant Toolkit"
const TRADING_DAYS = 252
fn kelly_fraction(win_rate: number, payoff: number) -> number:
return win_rate - (1 - win_rate) / payoff
fn annualized_volatility(source: series<number> = close, length: int = 20) -> number:
return stdev(returns(source), length) * sqrt(TRADING_DAYS)
fn position_heat(risks: list<percent>) -> percent:
total = 0%
for r in risks:
total += r
return total

A library holds functions, constants and types. It cannot place orders or draw (AS0405). Import it with use library "Quant Toolkit" v2 as qt and call qt.kelly_fraction(0.55, 1.8).

Examples: Quant Toolkit, Risk Parity, Ranking Tools, and a strategy that uses one: Kelly Sized Breakout.

Open this page on its own · Markdown

Reference

297 entries · every function, command, setting, modifier, event, unit, variable and type

Moving averages

Functions: sma, ema, wma, rma, smma, hma…
13

sma ema wma rma smma hma vwma dema tema kama alma t3 zlema

sma(source = close, length = 20)→ like source#

Simple moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.

Formula Arithmetic mean of the last length values.

Warm-up length bars

Example
average = sma(close, 20)
strategyindicatoralertlibrarysince 1.0
ema(source = close, length = 20)→ like source#

Exponential moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.

Formula alpha = 2 / (length + 1), seeded with the SMA of the first length values.

Warm-up length bars

Example
fast = ema(close, 20)
strategyindicatoralertlibrarysince 1.0
wma(source = close, length = 20)→ like source#

Linearly weighted moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.

Formula Weights length, length - 1, ..., 1 from newest to oldest.

Warm-up length bars

Example
weighted = wma(close, 20)
strategyindicatoralertlibrarysince 1.0
rma(source = close, length = 14)→ like source#

Wilder's moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint141 to 5000Number of bars in the calculation.

Formula alpha = 1 / length, seeded with the SMA of the first length values.

Warm-up length bars

Example
smoothed = rma(close, 14)
strategyindicatoralertlibrarysince 1.0
smma(source = close, length = 14)→ like source#

Smoothed moving average (identical to rma).

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint141 to 5000Number of bars in the calculation.
Example
smoothed = smma(close, 14)
strategyindicatoralertlibrarysince 1.0
hma(source = close, length = 20)→ like source#

Hull moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.

Formula wma(2 * wma(source, length / 2) - wma(source, length), round(sqrt(length)))

Example
hull = hma(close, 20)
strategyindicatoralertlibrarysince 1.0
vwma(source = close, length = 20)→ like source#

Volume-weighted moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
by_volume = vwma(close, 20)
strategyindicatoralertlibrarysince 1.0
dema(source = close, length = 20)→ like source#

Double exponential moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.

Formula 2 * ema - ema(ema)

Example
double = dema(close, 20)
strategyindicatoralertlibrarysince 1.0
tema(source = close, length = 20)→ like source#

Triple exponential moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.

Formula 3 * ema - 3 * ema(ema) + ema(ema(ema))

Example
triple = tema(close, 20)
strategyindicatoralertlibrarysince 1.0
kama(source = close, length = 10, fast = 2, slow = 30)→ like source#

Kaufman's adaptive moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint101 to 5000Efficiency ratio length.
fastint21 to 500Fastest smoothing length.
slowint301 to 5000Slowest smoothing length.
Example
adaptive = kama(close, 10, fast: 2, slow: 30)
strategyindicatoralertlibrarysince 1.0
alma(source = close, length = 9, offset = 0.85, sigma = 6)→ like source#

Arnaud Legoux moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint91 to 5000Number of bars in the calculation.
offsetnumber0.850 to 1Gaussian offset from 0 to 1.
sigmanumber60.1 to 100Gaussian width.
Example
smooth = alma(close, 9, offset: 0.85, sigma: 6)
strategyindicatoralertlibrarysince 1.0
t3(source = close, length = 5, factor = 0.7)→ like source#

Tillson T3 moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint51 to 5000Number of bars in the calculation.
factornumber0.70 to 1Volume factor.
Example
t = t3(close, 5, factor: 0.7)
strategyindicatoralertlibrarysince 1.0
zlema(source = close, length = 20)→ like source#

Zero-lag exponential moving average.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
zero_lag = zlema(close, 20)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Momentum

Functions: rsi, stoch, stoch_rsi, macd, cci, williams_r…
15

rsi stoch stoch_rsi macd cci williams_r roc momentum tsi ultimate_osc awesome_osc ppo cmo trix mfi

rsi(source = close, length = 14)→ series<number>#

Relative strength index, from 0 to 100.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint141 to 5000Number of bars in the calculation.

Formula Wilder's smoothing (rma) of gains and losses.

Warm-up length + 1 bars

Example
r = rsi(close, 14)
strategyindicatoralertlibrarysince 1.0
stoch(k_length = 14, k_smoothing = 3, d_smoothing = 3, on = bars())→ Stoch#

Stochastic oscillator.

Parameters

NameTypeDefaultRangeWhat it is
k_lengthint141 to 5000%K lookback.
k_smoothingint31 to 500%K smoothing.
d_smoothingint31 to 500%D smoothing.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.

Outputs, read with a dot

NameTypeWhat it is
kseries<number>%K.
dseries<number>%D.
Example
s = stoch(14, 3, 3)
strategyindicatoralertlibrarysince 1.0
stoch_rsi(source = close, rsi_length = 14, stoch_length = 14, k = 3, d = 3)→ Stoch#

Stochastic RSI.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
rsi_lengthint141 to 5000RSI length.
stoch_lengthint141 to 5000Stochastic length.
kint31 to 500%K smoothing.
dint31 to 500%D smoothing.

Outputs, read with a dot

NameTypeWhat it is
kseries<number>%K.
dseries<number>%D.
Example
srsi = stoch_rsi(close, 14, 14, 3, 3)
strategyindicatoralertlibrarysince 1.0
macd(source = close, fast = 12, slow = 26, signal = 9)→ Macd#

Moving average convergence divergence.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
fastint121 to 5000Fast EMA length.
slowint261 to 5000Slow EMA length.
signalint91 to 5000Signal EMA length.

Outputs, read with a dot

NameTypeWhat it is
macdseries<number>MACD line.
signalseries<number>Signal line.
histogramseries<number>MACD minus signal.
Example
m = macd(close, 12, 26, 9)
Example
rising = macd(close).histogram > 0
strategyindicatoralertlibrarysince 1.0
cci(source = hlc3, length = 20)→ series<number>#

Commodity channel index.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>hlc3Series to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
c = cci(hlc3, 20)
strategyindicatoralertlibrarysince 1.0
williams_r(length = 14, on = bars())→ series<number>#

Williams %R.

Parameters

NameTypeDefaultRangeWhat it is
lengthint141 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
wr = williams_r(14)
strategyindicatoralertlibrarysince 1.0
roc(source = close, length = 9)→ series<number>#

Rate of change in percent.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint91 to 5000Number of bars in the calculation.
Example
change = roc(close, 9)
strategyindicatoralertlibrarysince 1.0
momentum(source = close, length = 10)→ distance of source#

Difference from the value length bars ago.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint101 to 5000Number of bars in the calculation.
Example
mom = momentum(close, 10)
strategyindicatoralertlibrarysince 1.0
tsi(source = close, long = 25, short = 13, signal = 13)→ Tsi#

True strength index.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
longint251 to 5000Long smoothing.
shortint131 to 5000Short smoothing.
signalint131 to 5000Signal length.

Outputs, read with a dot

NameTypeWhat it is
tsiseries<number>TSI line.
signalseries<number>Signal line.
Example
t = tsi(close, 25, 13, 13)
strategyindicatoralertlibrarysince 1.0
ultimate_osc(fast = 7, middle = 14, slow = 28, on = bars())→ series<number>#

Ultimate oscillator.

Parameters

NameTypeDefaultRangeWhat it is
fastint71 to 5000Fast length.
middleint141 to 5000Middle length.
slowint281 to 5000Slow length.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
uo = ultimate_osc(7, 14, 28)
strategyindicatoralertlibrarysince 1.0
awesome_osc(fast = 5, slow = 34, on = bars())→ series<number>#

Awesome oscillator.

Parameters

NameTypeDefaultRangeWhat it is
fastint51 to 5000Fast length.
slowint341 to 5000Slow length.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
ao = awesome_osc(5, 34)
strategyindicatoralertlibrarysince 1.0
ppo(source = close, fast = 12, slow = 26, signal = 9)→ Macd#

Percentage price oscillator.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
fastint121 to 5000Fast EMA length.
slowint261 to 5000Slow EMA length.
signalint91 to 5000Signal EMA length.

Outputs, read with a dot

NameTypeWhat it is
macdseries<number>PPO line.
signalseries<number>Signal line.
histogramseries<number>PPO minus signal.
Example
pp = ppo(close, 12, 26, 9)
strategyindicatoralertlibrarysince 1.0
cmo(source = close, length = 9)→ series<number>#

Chande momentum oscillator.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint91 to 5000Number of bars in the calculation.
Example
chande = cmo(close, 9)
strategyindicatoralertlibrarysince 1.0
trix(source = close, length = 18)→ series<number>#

Triple-smoothed EMA rate of change.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint181 to 5000Number of bars in the calculation.
Example
tx = trix(close, 18)
strategyindicatoralertlibrarysince 1.0
mfi(length = 14, on = bars())→ series<number>#

Money flow index.

Parameters

NameTypeDefaultRangeWhat it is
lengthint141 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
flow_index = mfi(14)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Trend

Functions: supertrend, psar, adx, dmi, ichimoku, aroon…
8

supertrend psar adx dmi ichimoku aroon vortex linreg

supertrend(length = 10, multiplier = 3.0, on = bars())→ Supertrend#

Supertrend line and direction.

Parameters

NameTypeDefaultRangeWhat it is
lengthint101 to 5000ATR length.
multipliernumber3.00.1 to 50ATR multiplier.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.

Outputs, read with a dot

NameTypeWhat it is
lineseries<price>Supertrend line.
directionseries<int>1 when up, -1 when down.
Example
st = supertrend(10, multiplier: 3.0)
strategyindicatoralertlibrarysince 1.0
psar(start = 0.02, increment = 0.02, maximum = 0.2, on = bars())→ series<price>#

Parabolic SAR.

Parameters

NameTypeDefaultRangeWhat it is
startnumber0.020.001 to 1Starting acceleration.
incrementnumber0.020.001 to 1Acceleration step.
maximumnumber0.20.001 to 1Maximum acceleration.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
sar = psar(start: 0.02, increment: 0.02, maximum: 0.2)
strategyindicatoralertlibrarysince 1.0
adx(length = 14, on = bars())→ series<number>#

Average directional index.

Parameters

NameTypeDefaultRangeWhat it is
lengthint141 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
strength = adx(14)
strategyindicatoralertlibrarysince 1.0
dmi(length = 14, on = bars())→ Dmi#

Directional movement index.

Parameters

NameTypeDefaultRangeWhat it is
lengthint141 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.

Outputs, read with a dot

NameTypeWhat it is
plusseries<number>+DI.
minusseries<number>-DI.
adxseries<number>ADX.
Example
movement = dmi(14)
strategyindicatoralertlibrarysince 1.0
ichimoku(conversion = 9, base = 26, span_b = 52, displacement = 26, on = bars())→ Ichimoku#

Ichimoku cloud.

Parameters

NameTypeDefaultRangeWhat it is
conversionint91 to 500Conversion line length.
baseint261 to 500Base line length.
span_bint521 to 1000Leading span B length.
displacementint261 to 500Cloud displacement.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.

Outputs, read with a dot

NameTypeWhat it is
conversionseries<price>Conversion line.
baseseries<price>Base line.
span_aseries<price>Leading span A.
span_bseries<price>Leading span B.
laggingseries<price>Lagging span.
Example
cloud = ichimoku(conversion: 9, base: 26, span_b: 52, displacement: 26)
strategyindicatoralertlibrarysince 1.0
aroon(length = 25, on = bars())→ Aroon#

Aroon up and down.

Parameters

NameTypeDefaultRangeWhat it is
lengthint251 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.

Outputs, read with a dot

NameTypeWhat it is
upseries<number>Aroon up.
downseries<number>Aroon down.
Example
ar = aroon(25)
strategyindicatoralertlibrarysince 1.0
vortex(length = 14, on = bars())→ Vortex#

Vortex indicator.

Parameters

NameTypeDefaultRangeWhat it is
lengthint141 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.

Outputs, read with a dot

NameTypeWhat it is
plusseries<number>VI+.
minusseries<number>VI-.
Example
vx = vortex(14)
strategyindicatoralertlibrarysince 1.0
linreg(source = close, length = 20, offset = 0)→ like source#

Linear regression value.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
offsetint00 to 500Bars back from the current bar.
Example
fit = linreg(close, 20)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Volatility

Functions: atr, true_range, bollinger, keltner, donchian, envelope…
8

atr true_range bollinger keltner donchian envelope hist_volatility choppiness

atr(length = 14, on = bars())→ series<distance>#

Average true range.

Parameters

NameTypeDefaultRangeWhat it is
lengthint141 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.

Formula Wilder's smoothing (rma) of the true range.

Warm-up length bars

Example
stop_distance = atr(14) * 1.5
strategyindicatoralertlibrarysince 1.0
true_range(on = bars())→ series<distance>#

True range of the current bar.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
tr = true_range()
strategyindicatoralertlibrarysince 1.0
bollinger(source = close, length = 20, multiplier = 2.0)→ Bands#

Bollinger Bands.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
multipliernumber2.00.1 to 10Standard deviations.

Outputs, read with a dot

NameTypeWhat it is
upperseries<price>Upper band.
middleseries<price>Middle band.
lowerseries<price>Lower band.
widthseries<number>Band width relative to the middle.
percent_bseries<number>Position inside the bands.
Example
bb = bollinger(close, 20, 2.0)
Example
squeeze = bollinger(close).width < 0.02
strategyindicatoralertlibrarysince 1.0
keltner(source = close, length = 20, multiplier = 2.0, atr_length = 10)→ Bands#

Keltner channels.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
multipliernumber2.00.1 to 10ATR multiplier.
atr_lengthint101 to 5000ATR length.

Outputs, read with a dot

NameTypeWhat it is
upperseries<price>Upper channel.
middleseries<price>Middle line.
lowerseries<price>Lower channel.
Example
kc = keltner(close, 20, 2.0, 10)
strategyindicatoralertlibrarysince 1.0
donchian(length = 20, on = bars())→ Bands#

Donchian channels.

Parameters

NameTypeDefaultRangeWhat it is
lengthint201 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.

Outputs, read with a dot

NameTypeWhat it is
upperseries<price>Highest high.
middleseries<price>Midpoint.
lowerseries<price>Lowest low.
Example
dc = donchian(20)
strategyindicatoralertlibrarysince 1.0
envelope(source = close, length = 20, percent = 2%)→ Bands#

Moving average envelope.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
percentpercent2%Distance from the average.

Outputs, read with a dot

NameTypeWhat it is
upperseries<price>Upper line.
middleseries<price>Average.
lowerseries<price>Lower line.
Example
env = envelope(close, 20, percent: 2%)
strategyindicatoralertlibrarysince 1.0
hist_volatility(source = close, length = 20, annualize = 252)→ series<number>#

Historical volatility.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
annualizeint2521 to 100000Periods per year.
Example
hv = hist_volatility(close, 20)
strategyindicatoralertlibrarysince 1.0
choppiness(length = 14, on = bars())→ series<number>#

Choppiness index.

Parameters

NameTypeDefaultRangeWhat it is
lengthint141 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
chop = choppiness(14)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Volume

Functions: vwap, obv, cmf, ad_line, pvt, volume_osc
6

vwap obv cmf ad_line pvt volume_osc

vwap(anchor = "session", on = bars())→ series<price>#

Volume-weighted average price, restarting at each session or period.

Parameters

NameTypeDefaultWhat it is
anchorstring"session"Where the average restarts.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
fair = vwap(anchor: "session")
strategyindicatoralertlibrarysince 1.0
obv(on = bars())→ series<number>#

On-balance volume.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
balance_volume = obv()
strategyindicatoralertlibrarysince 1.0
cmf(length = 20, on = bars())→ series<number>#

Chaikin money flow.

Parameters

NameTypeDefaultRangeWhat it is
lengthint201 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
money_flow = cmf(20)
strategyindicatoralertlibrarysince 1.0
ad_line(on = bars())→ series<number>#

Accumulation/distribution line.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
ad = ad_line()
strategyindicatoralertlibrarysince 1.0
pvt(on = bars())→ series<number>#

Price volume trend.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
trend_volume = pvt()
strategyindicatoralertlibrarysince 1.0
volume_osc(fast = 5, slow = 10, on = bars())→ series<number>#

Volume oscillator.

Parameters

NameTypeDefaultRangeWhat it is
fastint51 to 5000Fast length.
slowint101 to 5000Slow length.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
vo = volume_osc(5, 10)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Smart money concepts

Functions: order_blocks, fair_value_gaps, break_of_structure, change_of_character, liquidity_sweeps, premium_discount…
7

order_blocks fair_value_gaps break_of_structure change_of_character liquidity_sweeps premium_discount optimal_trade_entry

order_blocks(length = 50, new_only = false, on = bars())→ list<Zone>#

Order blocks as zones with price bounds, formation time and status.

Parameters

NameTypeDefaultRangeWhat it is
lengthint501 to 5000Bars to scan.
new_onlyboolfalseOnly blocks that formed on this bar.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
blocks = order_blocks(50, new_only: true)
strategyindicatoralertlibrarysince 1.0
fair_value_gaps(length = 50, min_size = 0, new_only = false, on = bars())→ list<Zone>#

Fair value gaps as zones.

Parameters

NameTypeDefaultRangeWhat it is
lengthint501 to 5000Bars to scan.
min_sizeprice0Smallest gap to include.
new_onlyboolfalseOnly gaps that formed on this bar.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
gaps = fair_value_gaps(50, min_size: 0)
strategyindicatoralertlibrarysince 1.0
break_of_structure(direction = both, swing_length = 5, on = bars())→ series<bool>#

True on the bar structure breaks.

Parameters

NameTypeDefaultRangeWhat it is
directionstringbothup, down or both.
swing_lengthint51 to 100Swing size in bars.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
bos = break_of_structure(direction: up)
strategyindicatoralertlibrarysince 1.0
change_of_character(direction = both, swing_length = 5, on = bars())→ series<bool>#

True on the bar character changes.

Parameters

NameTypeDefaultRangeWhat it is
directionstringbothup, down or both.
swing_lengthint51 to 100Swing size in bars.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
choch = change_of_character(direction: down)
strategyindicatoralertlibrarysince 1.0
liquidity_sweeps(length = 20, on = bars())→ series<bool>#

True on the bar a prior high or low is swept and rejected.

Parameters

NameTypeDefaultRangeWhat it is
lengthint201 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
swept = liquidity_sweeps(20)
strategyindicatoralertlibrarysince 1.0
premium_discount(length = 50, on = bars())→ PremiumDiscount#

Premium, equilibrium and discount zones of the recent range.

Parameters

NameTypeDefaultRangeWhat it is
lengthint501 to 5000Number of bars in the calculation.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.

Outputs, read with a dot

NameTypeWhat it is
premiumZoneTop of range.
equilibriumseries<price>Midpoint.
discountZoneBottom of range.
Example
pd = premium_discount(50)
strategyindicatoralertlibrarysince 1.0
optimal_trade_entry(swing_length = 5, low = 62%, high = 79%, on = bars())→ Zone#

Optimal trade entry zone of the latest swing.

Parameters

NameTypeDefaultRangeWhat it is
swing_lengthint51 to 100Swing size in bars.
lowpercent62%Shallow retracement.
highpercent79%Deep retracement.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
ote = optimal_trade_entry(swing_length: 5)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Market structure

Functions: highest, lowest, pivots, swing_high, swing_low, fractals…
8

highest lowest pivots swing_high swing_low fractals zigzag support_resistance

highest(source = high, length = 20)→ like source#

Highest value over the last bars.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>highSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
top = highest(high, 20)
strategyindicatoralertlibrarysince 1.0
lowest(source = low, length = 20)→ like source#

Lowest value over the last bars.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>lowSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
bottom = lowest(low, 20)
strategyindicatoralertlibrarysince 1.0
pivots(left = 5, right = 5, on = bars())→ Pivots#

Confirmed pivot highs and lows; each fires on its confirmation bar, never the pivot bar.

Parameters

NameTypeDefaultRangeWhat it is
leftint51 to 500Bars to the left.
rightint51 to 500Bars to the right.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.

Outputs, read with a dot

NameTypeWhat it is
highseries<price>Latest confirmed pivot high.
lowseries<price>Latest confirmed pivot low.
Example
pv = pivots(left: 5, right: 5)
strategyindicatoralertlibrarysince 1.0
swing_high(left = 5, right = 5, on = bars())→ series<price>#

Latest confirmed swing high.

Parameters

NameTypeDefaultRangeWhat it is
leftint51 to 500Bars to the left.
rightint51 to 500Bars to the right.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
last_swing_high = swing_high(left: 5, right: 5)
strategyindicatoralertlibrarysince 1.0
swing_low(left = 5, right = 5, on = bars())→ series<price>#

Latest confirmed swing low.

Parameters

NameTypeDefaultRangeWhat it is
leftint51 to 500Bars to the left.
rightint51 to 500Bars to the right.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
last_swing_low = swing_low(left: 5, right: 5)
strategyindicatoralertlibrarysince 1.0
fractals(periods = 2, on = bars())→ Fractals#

Williams fractals.

Parameters

NameTypeDefaultRangeWhat it is
periodsint21 to 50Bars on each side.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.

Outputs, read with a dot

NameTypeWhat it is
upseries<bool>Up fractal confirmed.
downseries<bool>Down fractal confirmed.
Example
fr = fractals(2)
strategyindicatoralertlibrarysince 1.0
zigzag(deviation = 5%, depth = 10, on = bars())→ list<Swing>#

Zigzag swing points.

Parameters

NameTypeDefaultRangeWhat it is
deviationpercent5%Smallest reversal.
depthint101 to 500Fewest bars between points.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
swings = zigzag(deviation: 5%, depth: 10)
strategyindicatoralertlibrarysince 1.0
support_resistance(length = 200, touches = 2, on = bars())→ list<Level>#

Support and resistance levels.

Parameters

NameTypeDefaultRangeWhat it is
lengthint2001 to 5000Bars to scan.
touchesint21 to 100Fewest touches for a level.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
key_levels = support_resistance(200, touches: 2)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Candle patterns

Functions: engulfing, hammer, shooting_star, doji, pin_bar, inside_bar…
11

engulfing hammer shooting_star doji pin_bar inside_bar outside_bar morning_star evening_star three_soldiers three_crows

engulfing(direction = both, on = bars())→ series<bool>#

Bullish or bearish engulfing candle.

Parameters

NameTypeDefaultWhat it is
directionstringbothup, down or both.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
signal = engulfing()
strategyindicatoralertlibrarysince 1.0
hammer(on = bars())→ series<bool>#

Hammer candle.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
signal = hammer()
strategyindicatoralertlibrarysince 1.0
shooting_star(on = bars())→ series<bool>#

Shooting star candle.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
signal = shooting_star()
strategyindicatoralertlibrarysince 1.0
doji(max_body = 10%, on = bars())→ series<bool>#

Doji candle.

Parameters

NameTypeDefaultWhat it is
max_bodypercent10%Largest body as a share of the range.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
signal = doji()
strategyindicatoralertlibrarysince 1.0
pin_bar(min_wick = 66%, on = bars())→ series<bool>#

Pin bar.

Parameters

NameTypeDefaultWhat it is
min_wickpercent66%Smallest wick as a share of the range.
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
signal = pin_bar()
strategyindicatoralertlibrarysince 1.0
inside_bar(on = bars())→ series<bool>#

Bar inside the previous bar.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
signal = inside_bar()
strategyindicatoralertlibrarysince 1.0
outside_bar(on = bars())→ series<bool>#

Bar engulfing the previous bar.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
signal = outside_bar()
strategyindicatoralertlibrarysince 1.0
morning_star(on = bars())→ series<bool>#

Morning star, three bars.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
signal = morning_star()
strategyindicatoralertlibrarysince 1.0
evening_star(on = bars())→ series<bool>#

Evening star, three bars.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
signal = evening_star()
strategyindicatoralertlibrarysince 1.0
three_soldiers(on = bars())→ series<bool>#

Three white soldiers.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
signal = three_soldiers()
strategyindicatoralertlibrarysince 1.0
three_crows(on = bars())→ series<bool>#

Three black crows.

Parameters

NameTypeDefaultWhat it is
onBarSetbars()Bars to calculate on; defaults to the script's own bars.
Example
signal = three_crows()
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Statistics

Functions: stdev, mean, median, variance, percentile, percent_rank…
16

stdev mean median variance percentile percent_rank zscore returns correlation covariance beta skew kurtosis rank autocorrelation hurst

stdev(source = close, length = 20)→ distance of source#

Standard deviation.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
dispersion = stdev(close, 20)
strategyindicatoralertlibrarysince 1.0
mean(source = close, length = 20)→ like source#

Mean value.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
avg = mean(close, 20)
strategyindicatoralertlibrarysince 1.0
median(source = close, length = 20)→ like source#

Median value.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
mid = median(close, 20)
strategyindicatoralertlibrarysince 1.0
variance(source = close, length = 20)→ series<number>#

Variance.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
var_now = variance(close, 20)
strategyindicatoralertlibrarysince 1.0
percentile(source = close, length = 100, percent = 50%)→ like source#

Value at a percentile of recent values.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint1001 to 5000Number of bars in the calculation.
percentpercent50%Percentile to return.
Example
p90 = percentile(close, 100, percent: 90%)
strategyindicatoralertlibrarysince 1.0
percent_rank(source = close, length = 100)→ series<number>#

How many of the recent values are below this one, as a percentage from 0 to 100.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint1001 to 5000Number of bars in the calculation.
Example
standing = percent_rank(close, 100)
strategyindicatoralertlibrarysince 1.0
zscore(source = close, length = 20)→ series<number>#

Standard score of the current value.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
z = zscore(close, 20)
strategyindicatoralertlibrarysince 1.0
returns(source = close, periods = 1)→ series<number>#

Fractional change between bars.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
periodsint11 to 5000Bars between the two values.
Example
r1 = returns(close)
strategyindicatoralertlibrarysince 1.0
correlation(a, b, length = 50)→ series<number>#

Pearson correlation.

Parameters

NameTypeDefaultRangeWhat it is
aseries<number>requiredFirst series.
bseries<number>requiredSecond series.
lengthint501 to 5000Number of bars in the calculation.
Example
corr = correlation(close_of(EURUSD), close_of(GBPUSD), 50)
strategyindicatoralertlibrarysince 1.0
covariance(a, b, length = 50)→ series<number>#

Covariance.

Parameters

NameTypeDefaultRangeWhat it is
aseries<number>requiredFirst series.
bseries<number>requiredSecond series.
lengthint501 to 5000Number of bars in the calculation.
Example
cov_now = covariance(returns(close_of(EURUSD)), returns(close_of(GBPUSD)), 50)
strategyindicatoralertlibrarysince 1.0
beta(asset, benchmark, length = 100)→ series<number>#

Beta of an asset against a benchmark.

Parameters

NameTypeDefaultRangeWhat it is
assetseries<number>requiredAsset returns.
benchmarkseries<number>requiredBenchmark returns.
lengthint1001 to 5000Number of bars in the calculation.
Example
b = beta(returns(close_of(EURUSD)), returns(close_of(GBPUSD)), 100)
strategyindicatoralertlibrarysince 1.0
skew(source = close, length = 50)→ series<number>#

Skewness.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint501 to 5000Number of bars in the calculation.
Example
asymmetry = skew(returns(close), 50)
strategyindicatoralertlibrarysince 1.0
kurtosis(source = close, length = 50)→ series<number>#

Excess kurtosis.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint501 to 5000Number of bars in the calculation.
Example
tails = kurtosis(returns(close), 50)
strategyindicatoralertlibrarysince 1.0
rank(source = close, length = 50)→ series<number>#

Rank of the current value among recent values.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint501 to 5000Number of bars in the calculation.
Example
position_rank = rank(close, 50)
strategyindicatoralertlibrarysince 1.0
autocorrelation(source = close, length = 50, lag = 1)→ series<number>#

Autocorrelation at a lag.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint501 to 5000Number of bars in the calculation.
lagint11 to 500Bars of lag.
Example
ac = autocorrelation(returns(close), 50, lag: 1)
strategyindicatoralertlibrarysince 1.0
hurst(source = close, length = 100)→ series<number>#

Hurst exponent, on returns rather than prices. Prices trend by construction, so hurst(close, n) reads high for a random walk, a trend and a mean-reverting market alike and cannot tell them apart; hurst(returns(close), n) can.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint1001 to 5000Number of bars in the calculation.
Example
persistence = hurst(returns(close), 100)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Regression

Functions: linreg_slope, linreg_intercept, r_squared, ols
4

linreg_slope linreg_intercept r_squared ols

linreg_slope(source = close, length = 20)→ series<number>#

Slope of the least-squares line.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
slope = linreg_slope(close, 20)
strategyindicatoralertlibrarysince 1.0
linreg_intercept(source = close, length = 20)→ series<number>#

Intercept of the least-squares line.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
intercept = linreg_intercept(close, 20)
strategyindicatoralertlibrarysince 1.0
r_squared(source = close, length = 20)→ series<number>#

Coefficient of determination of the least-squares line.

Parameters

NameTypeDefaultRangeWhat it is
sourceseries<number>closeSeries to calculate from.
lengthint201 to 5000Number of bars in the calculation.
Example
fit_quality = r_squared(close, 20)
strategyindicatoralertlibrarysince 1.0
ols(target, factors, length = 100)→ Regression#

Multi-factor least-squares regression.

Parameters

NameTypeDefaultRangeWhat it is
targetseries<number>requiredDependent series.
factorslist<series<number>>requiredExplanatory series.
lengthint1001 to 5000Number of bars in the calculation.

Outputs, read with a dot

NameTypeWhat it is
coefficientslist<number>One per factor.
interceptnumberIntercept.
r_squarednumberFit quality.
residualseries<number>Latest residual.
Example
model = ols(returns(close), [returns(close_of(EURUSD)), returns(close_of(XAUUSD))], 100)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Matrices

Functions: matrix, transpose, multiply, inverse, covariance_matrix
5

matrix transpose multiply inverse covariance_matrix

matrix(rows, columns, fill = 0)→ matrix#

A numeric matrix filled with a value.

Parameters

NameTypeDefaultWhat it is
rowsintrequiredRows.
columnsintrequiredColumns.
fillnumber0Initial value.
Example
grid = matrix(3, 3)
strategyindicatoralertlibrarysince 1.0
transpose(m)→ matrix#

Transpose a matrix.

Parameters

NameTypeDefaultWhat it is
mmatrixrequiredMatrix.
Example
flipped = transpose(grid)
strategyindicatoralertlibrarysince 1.0
multiply(a, b)→ matrix#

Matrix product.

Parameters

NameTypeDefaultWhat it is
amatrixrequiredLeft matrix.
bmatrixrequiredRight matrix.
Example
product = multiply(grid, transpose(grid))
strategyindicatoralertlibrarysince 1.0
inverse(m)→ matrix#

Matrix inverse; na when the matrix is singular.

Parameters

NameTypeDefaultWhat it is
mmatrixrequiredSquare matrix.
Example
inv = inverse(grid)
strategyindicatoralertlibrarysince 1.0
covariance_matrix(series, length = 100)→ matrix#

Covariance matrix of several series.

Parameters

NameTypeDefaultRangeWhat it is
serieslist<series<number>>requiredSeries to compare.
lengthint1001 to 5000Number of bars in the calculation.
Example
cov_m = covariance_matrix([returns(close_of(EURUSD)), returns(close_of(GBPUSD))], 100)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Conditions

Functions: crosses_above, crosses_below, crosses, starts, ends, bars_since…
8

crosses_above crosses_below crosses starts ends bars_since was held

crosses_above(a, b)→ series<bool>#

True on the bar where a crosses above b.

Parameters

NameTypeDefaultWhat it is
aseries<number>requiredSeries that crosses.
bseries<number>requiredSeries or level crossed.
Example
long_signal = crosses_above(close, ema(close, 20))
strategyindicatoralertlibrarysince 1.0
crosses_below(a, b)→ series<bool>#

True on the bar where a crosses below b.

Parameters

NameTypeDefaultWhat it is
aseries<number>requiredSeries that crosses.
bseries<number>requiredSeries or level crossed.
Example
short_signal = crosses_below(close, ema(close, 20))
strategyindicatoralertlibrarysince 1.0
crosses(a, b)→ series<bool>#

True on the bar where a crosses b in either direction.

Parameters

NameTypeDefaultWhat it is
aseries<number>requiredFirst series.
bseries<number>requiredSecond series.
Example
any_cross = crosses(ema(close, 20), ema(close, 50))
strategyindicatoralertlibrarysince 1.0
starts(condition)→ series<bool>#

True on the bar a condition becomes true.

Parameters

NameTypeDefaultWhat it is
conditionseries<bool>requiredCondition to watch.
Example
breakout = starts(close > highest(high, 20)[1])
strategyindicatoralertlibrarysince 1.0
ends(condition)→ series<bool>#

True on the bar a condition stops being true.

Parameters

NameTypeDefaultWhat it is
conditionseries<bool>requiredCondition to watch.
Example
trend_over = ends(ema(close, 20) > ema(close, 50))
strategyindicatoralertlibrarysince 1.0
bars_since(condition)→ series<int>#

Bars since a condition was last true.

Parameters

NameTypeDefaultWhat it is
conditionseries<bool>requiredCondition to watch.
Example
age = bars_since(crosses_above(close, ema(close, 20)))
strategyindicatoralertlibrarysince 1.0
was(condition, within = 5 bars)→ series<bool>#

True if a condition was true at some point in recent bars.

Parameters

NameTypeDefaultWhat it is
conditionseries<bool>requiredCondition to watch.
withinbars5 barsHow far back to look.
Example
recent = was(crosses_above(close, ema(close, 20)), within: 5 bars)
strategyindicatoralertlibrarysince 1.0
held(condition, for = 3 bars)→ series<bool>#

True if a condition has been true for consecutive bars.

Parameters

NameTypeDefaultWhat it is
conditionseries<bool>requiredCondition to watch.
forbars3 barsBars in a row.
Example
steady = held(close > open, for: 3 bars)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Data and bar types

Functions: bars, close_of, intrabar, data.coverage, range, xray…
8

bars close_of intrabar data.coverage range xray renko heikin_ashi

bars(symbol = market.symbol, bars = bar.type)→ BarSet#

Bars of another bar type or symbol. Higher-timeframe values change only when that bar confirms, so look-ahead is impossible.

Parameters

NameTypeDefaultWhat it is
symbolsymbolmarket.symbolMarket to read.
barsbartypebar.typeBar type to read.
Example
h4 = bars(bars: 4h)
Example
gold = bars(XAUUSD, bars: 15m)
strategyindicatoralertlibrarysince 1.0
close_of(symbol, bars = bar.type)→ series<price>#

Close series of another symbol, aligned by bar close time.

Parameters

NameTypeDefaultWhat it is
symbolsymbolrequiredMarket to read.
barsbartypebar.typeBar type to read.
Example
ratio = close_of(EURUSD) / close_of(GBPUSD)
strategyindicatoralertlibrarysince 1.0
intrabar(bars = 1m)→ list<Bar>#

Lower-timeframe bars inside the current bar, as a list.

Parameters

NameTypeDefaultWhat it is
barsbartype1mLower bar type.
Example
minute_bars = intrabar(1m)
strategyindicatoralertlibrarysince 1.0
data.coverage(symbol = market.symbol, bars = bar.type)→ Coverage#

The stored date range for a symbol and bar type, and whether results on it are exact.

Parameters

NameTypeDefaultWhat it is
symbolsymbolmarket.symbolMarket to check.
barsbartypebar.typeBar type to check.

Outputs, read with a dot

NameTypeWhat it is
fromtimeFirst available bar.
totimeLast available bar.
barsintNumber of bars.
sourcestring"stored" or "built".
exactboolfalse when rebuilt from coarser data.
Example
cov = data.coverage(EURUSD, bars: range(10))
strategyindicatoralertsince 1.0
range(size = 10)→ bartype#

Range bars of a fixed size; stored tick-built bars where they exist, otherwise built from candles.

Parameters

NameTypeDefaultWhat it is
sizenumber | distance10Bar size; a bare number follows the chart convention for the symbol.
Example
bars_r = bars(bars: range(10 pips))
strategyindicatoralertlibrarysince 1.0
xray(size = 10)→ bartype#

Range bars built with the chart's x-ray algorithm.

Parameters

NameTypeDefaultWhat it is
sizenumber | distance10Bar size.
Example
bars_x = bars(bars: xray(10))
strategyindicatoralertlibrarysince 1.0
renko(size = 10)→ bartype#

Renko bricks built with the chart's renko algorithm.

Parameters

NameTypeDefaultWhat it is
sizenumber | distance10Brick size.
Example
bars_k = bars(bars: renko(5 points))
strategyindicatoralertlibrarysince 1.0
heikin_ashi(timeframe = 1h)→ bartype#

Heikin-Ashi bars computed from time bars.

Parameters

NameTypeDefaultWhat it is
timeframeduration1hUnderlying timeframe.
Example
smooth_bars = bars(bars: heikin_ashi(1h))
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Sizing

Functions: size_for
1

size_for

size_for(symbol = market.symbol, risk, stop)→ lots#

The lot size an entry would use for a risk and stop, rounded down to the lot step.

Parameters

NameTypeDefaultWhat it is
symbolsymbolmarket.symbolMarket to size.
riskpercent | moneyrequiredRisk to take.
stopdistancerequiredStop distance.
Example
eur_size = size_for(EURUSD, risk: 0.5%, stop: 30 pips)
strategysince 1.0

Open this page on its own · Markdown

Math

Functions: abs, min, max, round, floor, ceil…
13

abs min max round floor ceil sqrt log exp pow clamp sign lerp

abs(value)→ like value#

Absolute value.

Parameters

NameTypeDefaultWhat it is
valuenumberrequiredValue.
Example
body_size = abs(close - open)
strategyindicatoralertlibrarysince 1.0
min(a, b)→ like a#

Smaller of two values.

Parameters

NameTypeDefaultWhat it is
anumberrequiredFirst value.
bnumberrequiredSecond value.
Example
body_low = min(open, close)
strategyindicatoralertlibrarysince 1.0
max(a, b)→ like a#

Larger of two values.

Parameters

NameTypeDefaultWhat it is
anumberrequiredFirst value.
bnumberrequiredSecond value.
Example
body_high = max(open, close)
strategyindicatoralertlibrarysince 1.0
round(value, decimals = 0)→ like value#

Round to a number of decimals.

Parameters

NameTypeDefaultRangeWhat it is
valuenumberrequiredValue.
decimalsint00 to 12Decimal places.
Example
shown = round(close, 2)
strategyindicatoralertlibrarysince 1.0
floor(value)→ like value#

Round down.

Parameters

NameTypeDefaultWhat it is
valuenumberrequiredValue.
Example
whole = floor(close)
strategyindicatoralertlibrarysince 1.0
ceil(value)→ like value#

Round up.

Parameters

NameTypeDefaultWhat it is
valuenumberrequiredValue.
Example
whole_up = ceil(close)
strategyindicatoralertlibrarysince 1.0
sqrt(value)→ number#

Square root, deterministic across devices.

Parameters

NameTypeDefaultWhat it is
valuenumberrequiredValue.
Example
root = sqrt(252)
strategyindicatoralertlibrarysince 1.0
log(value)→ number#

Natural logarithm, deterministic across devices.

Parameters

NameTypeDefaultWhat it is
valuenumberrequiredValue.
Example
log_price = log(close)
strategyindicatoralertlibrarysince 1.0
exp(value)→ number#

Exponential, deterministic across devices.

Parameters

NameTypeDefaultWhat it is
valuenumberrequiredValue.
Example
growth = exp(0.05)
strategyindicatoralertlibrarysince 1.0
pow(base, exponent)→ number#

Power, deterministic across devices.

Parameters

NameTypeDefaultWhat it is
basenumberrequiredBase.
exponentnumberrequiredExponent.
Example
squared = pow(close, 2)
strategyindicatoralertlibrarysince 1.0
clamp(value, low, high)→ like value#

Limit a value to a range.

Parameters

NameTypeDefaultWhat it is
valuenumberrequiredValue.
lownumberrequiredLowest allowed.
highnumberrequiredHighest allowed.
Example
bounded = clamp(rsi(close, 14), 20, 80)
strategyindicatoralertlibrarysince 1.0
sign(value)→ number#

-1, 0 or 1.

Parameters

NameTypeDefaultWhat it is
valuenumberrequiredValue.
Example
side_sign = sign(close - open)
strategyindicatoralertlibrarysince 1.0
lerp(a, b, t)→ like a#

Linear interpolation between two values.

Parameters

NameTypeDefaultWhat it is
anumberrequiredStart.
bnumberrequiredEnd.
tnumberrequiredFraction from 0 to 1.
Example
halfway = lerp(low, high, 0.5)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Missing values

Functions: nz, is_na
2

nz is_na

nz(value, fallback = 0)→ like value#

Replace a missing value.

Parameters

NameTypeDefaultWhat it is
valuenumberrequiredValue that may be na.
fallbacknumber0Replacement.
Example
safe = nz(close[1], close)
strategyindicatoralertlibrarysince 1.0
is_na(value)→ bool#

True when a value is missing.

Parameters

NameTypeDefaultWhat it is
valuenumberrequiredValue to test.
Example
warming_up = is_na(ema(close, 200))
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Colours

Functions: rgb, gradient, linear_gradient, radial_gradient
4

rgb gradient linear_gradient radial_gradient

rgb(red, green, blue, transparency = 0)→ color#

Color from red, green, blue and optional transparency.

Parameters

NameTypeDefaultRangeWhat it is
redintrequired0 to 255.
greenintrequired0 to 255.
blueintrequired0 to 255.
transparencynumber00 to 100Percent transparent, 0 to 100.
Example
brand = rgb(34, 197, 94)
strategyindicatoralertlibrarysince 1.0
gradient(value, low, high, from = 0, to = 100)→ color#

Color between two colors according to a value.

Parameters

NameTypeDefaultWhat it is
valuenumberrequiredValue to map.
lowcolorrequiredColor at the low end.
highcolorrequiredColor at the high end.
fromnumber0Value mapped to low.
tonumber100Value mapped to high.
Example
heat = gradient(rsi(close, 14), low: red, high: green)
strategyindicatoralertlibrarysince 1.0
linear_gradient(start, end)→ fill#

Linear gradient fill for shapes and channels.

Parameters

NameTypeDefaultWhat it is
startcolorrequiredStart color.
endcolorrequiredEnd color.
Example
shade = linear_gradient(green.fade(60), green.fade(95))
strategyindicatorsince 1.0
radial_gradient(inner, outer)→ fill#

Radial gradient fill for shapes.

Parameters

NameTypeDefaultWhat it is
innercolorrequiredCenter color.
outercolorrequiredEdge color.
Example
glow = radial_gradient(blue, blue.fade(100))
strategyindicatorsince 1.0

Open this page on its own · Markdown

Order commands

Commands: buy, sell, close, close_all, modify, cancel
6

buy sell close close_all modify cancel

buy [options]#

Open a long position or place a buy order.

Options

NameTypeDefaultWhat it is
sizelots | percent | money0.01 lotsPosition size in lots, or % / $ of balance as notional.
riskpercent | moneynoneRisk per trade; size is computed from the stop distance and rounded down to the lot step.
stopprice | distancenoneProtective stop. For a pending stop order, the entry price (its protective stop is then stop_loss).
targetprice | distancenoneTake-profit price or distance, such as 2R.
limitpricenoneEntry price of a pending limit order.
stop_lossprice | distancenoneProtective stop of a pending stop order.
ghostboolfalseKeep stop and target off the broker; AlgoBars enforces them.
expiresbars | durationnoneWhen a pending order expires.
marketsymbolmarket.symbolWhich symbol, in strategies with several markets.
tagstring""Label carried by the order and its trade.

Where it goes Inside a when rule, event or action fn of a strategy.

Block management

Example
buy risk: 1%, stop: 20 pips, target: 2R
strategysince 1.0
sell [options]#

Open a short position or place a sell order.

Options

NameTypeDefaultWhat it is
sizelots | percent | money0.01 lotsPosition size in lots, or % / $ of balance as notional.
riskpercent | moneynoneRisk per trade; size is computed from the stop distance and rounded down to the lot step.
stopprice | distancenoneProtective stop. For a pending stop order, the entry price (its protective stop is then stop_loss).
targetprice | distancenoneTake-profit price or distance, such as 2R.
limitpricenoneEntry price of a pending limit order.
stop_lossprice | distancenoneProtective stop of a pending stop order.
ghostboolfalseKeep stop and target off the broker; AlgoBars enforces them.
expiresbars | durationnoneWhen a pending order expires.
marketsymbolmarket.symbolWhich symbol, in strategies with several markets.
tagstring""Label carried by the order and its trade.

Where it goes Inside a when rule, event or action fn of a strategy.

Block management

Example
sell risk: $200, stop: highest(high, 10) + 2 pips, target: 2R
strategysince 1.0
close <trade> [options]#

Close a trade, fully or partly.

Arguments

NameTypeDefaultWhat it is
tradeTraderequiredTrade to close.

Options

NameTypeDefaultWhat it is
sizepercent | lots100%How much to close.

Where it goes Inside a when rule, event, loop or action fn of a strategy.

Example
close trades.last(), size: 50%
strategysince 1.0
close_all [options]#

Close all of the strategy's open trades, optionally filtered.

Options

NameTypeDefaultWhat it is
sidestringbothlong, short or both.
tagstring""Only trades with this tag.
marketsymbolmarket.symbolOnly this symbol.

Where it goes Inside a when rule, event or action fn of a strategy.

Example
close_all side: long
strategysince 1.0
modify <trade> [options]#

Change the stop or target of a trade.

Arguments

NameTypeDefaultWhat it is
tradeTraderequiredTrade to change.

Options

NameTypeDefaultWhat it is
stopprice | distanceunchangedNew stop.
targetprice | distanceunchangedNew target.

Where it goes Inside a when rule, event, loop or action fn of a strategy.

Example
modify trades.last(), stop: trades.last().entry_price
strategysince 1.0
cancel <orders>#

Cancel pending orders.

Arguments

NameTypeDefaultWhat it is
orderslist<Order>requiredOrders to cancel.

Where it goes Inside a when rule, event or action fn of a strategy.

Example
cancel orders.pending(tag: "grid")
strategysince 1.0

Open this page on its own · Markdown

Trade management commands

Commands: partial, breakeven, trail, exit
4

partial breakeven trail exit

partial <amount> [options]#

Close part of the trade at a level.

Arguments

NameTypeDefaultWhat it is
amountpercentrequiredShare of the trade to close.

Options

NameTypeDefaultWhat it is
atprice | distancerequiredLevel, such as 1.5R.

Where it goes Inside the management block of a buy or sell.

Example
partial 50% at: 2R
strategysince 1.0
breakeven [options]#

Move the stop to the entry price at a level.

Options

NameTypeDefaultWhat it is
atprice | distancerequiredLevel, such as 1R.
offsetdistance0 pipsDistance beyond entry.

Where it goes Inside the management block of a buy or sell.

Example
breakeven at: 1R, offset: 2 pips
strategysince 1.0
trail [options]#

Trail the stop behind price.

Options

NameTypeDefaultWhat it is
bydistancerequiredTrailing distance.
afterprice | distance0RStart trailing once this level is reached.

Where it goes Inside the management block of a buy or sell.

Example
trail by: atr(14), after: 2R
strategysince 1.0
exit [options]#

Close the trade after a time or when a condition becomes true.

Options

NameTypeDefaultWhat it is
afterbars | durationnoneClose after this long.
whenboolfalseClose when true.

Where it goes Inside the management block of a buy or sell.

Example
exit after: 48 bars
strategysince 1.0

Open this page on its own · Markdown

Drawing commands

Commands: plot, fill, hline, mark, label, line, box, table…
26

plot fill hline mark label line box table bar_color background pane polygon polyline curve channel profile heatmap cells candles fib pitchfork arrow icon image tooltip dashboard

plot <series> [options]#

Draw a series.

Arguments

NameTypeDefaultWhat it is
seriesseries<number>requiredValues to draw.

Options

NameTypeDefaultRangeWhat it is
stylestringlineline, step, area, histogram, columns, circles or cross.
colorcolorblueColor.
widthint11 to 10Line width in pixels.
panestringpriceprice, new or a named pane.

Where it goes At the top level of an indicator or strategy.

Example
plot ema(close, 20) as fast, color: green, width: 2
strategyindicatorsince 1.0
fill <a> <b> [options]#

Fill between two plots or levels.

Arguments

NameTypeDefaultWhat it is
aseries<number>requiredFirst edge.
bseries<number>requiredSecond edge.

Options

NameTypeDefaultWhat it is
colorcolorblueColor.

Where it goes At the top level of an indicator or strategy.

Example
fill ema(close, 20), ema(close, 50), color: green.fade(80)
strategyindicatorsince 1.0
hline <value> [options]#

Horizontal level.

Arguments

NameTypeDefaultWhat it is
valuepricerequiredLevel.

Options

NameTypeDefaultWhat it is
stylestringdashedsolid, dashed or dotted.
colorcolorgrayColor.

Where it goes At the top level of an indicator or strategy.

Example
hline 70, style: dashed, color: red
strategyindicatorsince 1.0
mark <shape> [options]#

Marker on bars where a condition is true.

Arguments

NameTypeDefaultWhat it is
shapestringrequiredBuilt-in shape, emoji or SVG path.

Options

NameTypeDefaultWhat it is
atstring | pricebelowabove, below or a price.
whenbooltrueWhere to draw.
colorcolorblueColor.
sizestringsmalltiny, small, normal or large.

Where it goes At the top level of an indicator or strategy.

Example
mark arrow_up, at: below, when: crosses_above(close, ema(close, 20))
strategyindicatorsince 1.0
label <text> [options]#

Text at a bar and price.

Arguments

NameTypeDefaultWhat it is
textstringrequiredText.

Options

NameTypeDefaultWhat it is
attuple<bar | time, price>requiredBar and price.
stylestringnormalLabel style.
colorcolorblueColor.

Where it goes Anywhere a drawing statement is allowed.

Example
label "Entry", at: (bar.index, high)
strategyindicatorsince 1.0
line [options]#

Trend line or ray.

Options

NameTypeDefaultRangeWhat it is
fromtuple<bar | time, price>requiredStart point.
totuple<bar | time, price>requiredEnd point.
extendstringnonenone, left, right or both.
colorcolorblueColor.
widthint11 to 10Line width in pixels.

Where it goes Anywhere a drawing statement is allowed.

Example
line from: (bar.index - 20, low), to: (bar.index, low), extend: right
strategyindicatorsince 1.0
box [options]#

Rectangle or zone.

Options

NameTypeDefaultWhat it is
idstringautomaticId for updating the same box later.
fromtuple<bar | time, price>requiredOne corner.
totuple<bar | time, price>requiredOpposite corner.
colorcolorblueColor.
bordercolornoneBorder color.

Where it goes Anywhere a drawing statement is allowed.

Example
box from: (bar.index - 10, high), to: (bar.index, low), color: blue.fade(85)
strategyindicatorsince 1.0
table [options]#

On-chart table.

Options

NameTypeDefaultWhat it is
positionstringtop_rightCorner or edge of the chart.
rowslist<list<string>>requiredCell text by row.

Where it goes At the top level of an indicator or strategy.

Example
table position: top_right, rows: [["RSI", "{rsi(close, 14):0}"]]
strategyindicatorsince 1.0
bar_color <color>#

Recolor price bars.

Arguments

NameTypeDefaultWhat it is
colorcolorrequiredBar color.

Where it goes At the top level of an indicator or strategy.

Example
bar_color if close > open then green else red
strategyindicatorsince 1.0
background <color> [options]#

Shade the background.

Arguments

NameTypeDefaultWhat it is
colorcolorrequiredBackground color.

Options

NameTypeDefaultWhat it is
whenbooltrueWhere to shade.

Where it goes At the top level of an indicator or strategy.

Example
background red.fade(90), when: rsi(close, 14) > 70
strategyindicatorsince 1.0
pane <name> [options]#

Declare a named pane shared by several plots.

Arguments

NameTypeDefaultWhat it is
namestringrequiredPane name.

Options

NameTypeDefaultWhat it is
heightpercent25%Share of the chart height.

Where it goes At the top level of an indicator.

Example
pane "Oscillators", height: 30%
strategyindicatorsince 1.0
polygon [options]#

Closed shape.

Options

NameTypeDefaultWhat it is
pointslist<tuple<bar | time, price>>requiredCorner points.
fillcolornoneFill color.
bordercolorblueBorder color.

Where it goes Anywhere a drawing statement is allowed.

Example
polygon points: [(bar.index - 5, high), (bar.index, low), (bar.index - 5, low)], fill: blue.fade(80)
strategyindicatorsince 1.0
polyline [options]#

Open multi-segment line.

Options

NameTypeDefaultRangeWhat it is
pointslist<tuple<bar | time, price>>requiredPoints in order.
colorcolorblueColor.
widthint11 to 10Line width in pixels.

Where it goes Anywhere a drawing statement is allowed.

Example
polyline points: [(bar.index - 10, low), (bar.index - 5, high), (bar.index, low)]
strategyindicatorsince 1.0
curve [options]#

Smoothed curve through points.

Options

NameTypeDefaultRangeWhat it is
pointslist<tuple<bar | time, price>>requiredPoints in order.
smoothnumber0.50 to 1Smoothing from 0 to 1.
colorcolorblueColor.

Where it goes Anywhere a drawing statement is allowed.

Example
curve points: [(bar.index - 10, low), (bar.index - 5, high), (bar.index, low)], smooth: 0.5
strategyindicatorsince 1.0
channel [options]#

Channel between two series with a fill.

Options

NameTypeDefaultWhat it is
upperseries<price>requiredUpper edge.
lowerseries<price>requiredLower edge.
fillfillblue.fade(85)Fill color or gradient.

Where it goes At the top level of an indicator or strategy.

Example
channel upper: bollinger(close).upper, lower: bollinger(close).lower, fill: blue.fade(85)
strategyindicatorsince 1.0
profile [options]#

Horizontal histogram on the price axis (volume profile, market profile).

Options

NameTypeDefaultRangeWhat it is
rowsint242 to 1000Price rows.
rangestringvisiblevisible, session or fixed.
sidestringrightleft or right.
value_areapercent70%Value area share.

Where it goes At the top level of an indicator.

Example
profile rows: 24, range: session, side: right
strategyindicatorsince 1.0
heatmap [options]#

Price-by-time heatmap.

Options

NameTypeDefaultWhat it is
cellslist<Cell>requiredCells with bar, price and value.
palettestring"thermal"Color palette.

Where it goes At the top level of an indicator.

Example
heatmap cells: liquidity_cells, palette: "thermal"
strategyindicatorsince 1.0
cells [options]#

Cell grid inside each bar (footprint style).

Options

NameTypeDefaultWhat it is
rowslist<list<string>>requiredCell text by row.
columnsint2Columns per bar.

Where it goes At the top level of an indicator.

Example
cells rows: footprint_rows, columns: 2
strategyindicatorsince 1.0
candles [options]#

Custom candles in any pane.

Options

NameTypeDefaultWhat it is
openseries<number>requiredOpen.
highseries<number>requiredHigh.
lowseries<number>requiredLow.
closeseries<number>requiredClose.
colorcolorblueColor.
panestringnewprice, new or a named pane.

Where it goes At the top level of an indicator.

Example
candles open: open - close_of(GBPUSD), high: high - close_of(GBPUSD), low: low - close_of(GBPUSD), close: close - close_of(GBPUSD)
strategyindicatorsince 1.0
fib [options]#

Fibonacci retracement or extension.

Options

NameTypeDefaultWhat it is
fromtuple<bar | time, price>requiredSwing start.
totuple<bar | time, price>requiredSwing end.
levelslist<number>[0.236, 0.382, 0.5, 0.618, 0.786]Levels to draw.

Where it goes Anywhere a drawing statement is allowed.

Example
fib from: (bar.index - 50, lowest(low, 50)), to: (bar.index, highest(high, 50))
strategyindicatorsince 1.0
pitchfork [options]#

Andrews pitchfork.

Options

NameTypeDefaultWhat it is
pointslist<tuple<bar | time, price>>requiredThree anchor points.

Where it goes Anywhere a drawing statement is allowed.

Example
pitchfork points: [(bar.index - 30, low), (bar.index - 20, high), (bar.index - 10, low)]
strategyindicatorsince 1.0
arrow [options]#

Arrow between two points.

Options

NameTypeDefaultWhat it is
fromtuple<bar | time, price>requiredTail.
totuple<bar | time, price>requiredHead.
colorcolorblueColor.

Where it goes Anywhere a drawing statement is allowed.

Example
arrow from: (bar.index - 5, high), to: (bar.index, close)
strategyindicatorsince 1.0
icon <name> [options]#

Icon glyph.

Arguments

NameTypeDefaultWhat it is
namestringrequiredIcon name.

Options

NameTypeDefaultWhat it is
attuple<bar | time, price>requiredBar and price.
colorcolorblueColor.

Where it goes Anywhere a drawing statement is allowed.

Example
icon "flag", at: (bar.index, high)
strategyindicatorsince 1.0
image <asset> [options]#

Small image uploaded with the script.

Arguments

NameTypeDefaultWhat it is
assetstringrequiredAsset name.

Options

NameTypeDefaultRangeWhat it is
attuple<bar | time, price>requiredBar and price.
widthint244 to 512Width in pixels.

Where it goes Anywhere a drawing statement is allowed.

Example
image "logo", at: (bar.index, high), width: 24
strategyindicatorsince 1.0
tooltip <text> [options]#

Hover tooltip.

Arguments

NameTypeDefaultWhat it is
textstringrequiredTooltip text.

Options

NameTypeDefaultWhat it is
attuple<bar | time, price>requiredBar and price.

Where it goes Anywhere a drawing statement is allowed.

Example
tooltip "Swing high", at: (bar.index, high)
strategyindicatorsince 1.0
dashboard [options]#

Panel pinned to the screen that stays put while the chart scrolls.

Options

NameTypeDefaultWhat it is
positionstringtop_rightCorner or edge of the screen.
rowslist<list<string>>requiredCell text by row.

Where it goes At the top level of an indicator or strategy.

Example
dashboard position: top_right, rows: [["Trend", "up"]]
strategyindicatorsince 1.0

Open this page on its own · Markdown

Alert commands

Commands: notify
1

notify

notify <message>#

Send a notification (in-app and AI chat in v1).

Arguments

NameTypeDefaultWhat it is
messagestringrequiredMessage text with {value} interpolation.

Where it goes Inside a when rule or event of an alert or strategy.

Example
notify "RSI is {rsi(close, 14):0.0}"
strategyalertsince 1.0

Open this page on its own · Markdown

Logging

Commands: log
1

log

log <message>#

Write a line to the Terminal console.

Arguments

NameTypeDefaultWhat it is
messagestringrequiredMessage text with {value} interpolation.

Where it goes Anywhere a statement is allowed.

Example
log "close {close}"
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Header settings

Every line you can write under the script header.
21

market markets bars evaluate pane max_open max_open_per_side direction opposite warmup repeat cooldown expires check show_on_chart max_daily_loss max_drawdown max_total_risk pyramiding min_distance trade_only

market: <symbol>#

Symbol the script runs on.

Default chart symbol

Example
market: EURUSD
strategyindicatoralertsince 1.0
markets: <list<symbol>>#

Several symbols; alerts evaluate each independently.

Example
markets: EURUSD, GBPUSD
strategyindicatoralertsince 1.0
bars: <bartype>#

Bar type: timeframe, range(n), xray(n), renko(n) or heikin_ashi(tf).

Default chart bars

Example
bars: 15m
strategyindicatoralertsince 1.0
evaluate: <string>#

bar_close (default, never repaints) or tick.

Choices bar_close tick

Default bar_close

Example
evaluate: bar_close
strategyalertsince 1.0
pane: <string>#

price, new or a named pane.

Default price

Example
pane: price
indicatorsince 1.0
max_open: <int>#

Open trades allowed at once.

Default 1

Example
max_open: 2
strategysince 1.0
max_open_per_side: <int>#

Open trades allowed per side.

Example
max_open_per_side: 1
strategysince 1.0
direction: <string>#

both, long or short.

Choices both long short

Default both

Example
direction: long
strategysince 1.0
opposite: <string>#

On an opposite signal: close, reverse, ignore or hedge (where the venue supports it).

Choices close reverse ignore hedge

Default ignore

Example
opposite: reverse
strategysince 1.0
warmup: <int>#

Bars required before rules run (computed by the compiler when omitted).

Example
warmup: 300
strategyindicatoralertsince 1.0
repeat: <string>#

once, once per bar, once per bar close or every time.

Default once per bar

Example
repeat: once per bar
alertsince 1.0
cooldown: <duration | bars>#

Minimum time or bars between notifications.

Example
cooldown: 30m
alertsince 1.0
expires: <date | duration>#

When the alert stops.

Example
expires: 2026-12-31
alertsince 1.0
check: <duration>#

How often account-only alerts are checked.

Default every 1m

Example
check: every 1m
alertsince 1.0
show_on_chart: <bool>#

Draw fire points, watched levels and live status on the chart.

Default true

Example
show_on_chart: true
alertsince 1.0
max_daily_loss: <percent | money>#

Pause the deployment after this loss in a day.

Example
max_daily_loss: 3%
strategysince 1.0
max_drawdown: <percent | money>#

Pause the deployment at this drawdown.

Example
max_drawdown: 10%
strategysince 1.0
max_total_risk: <percent>#

Risk allowed across open trades.

Example
max_total_risk: 4%
strategysince 1.0
pyramiding: <int>#

Entries allowed in the same direction.

Default 1

Example
pyramiding: 3
strategysince 1.0
min_distance: <distance>#

Smallest distance between pyramided entries.

Example
min_distance: 20 pips
strategysince 1.0
trade_only: <sessions>#

Sessions in which the strategy may open trades.

Example
trade_only: within sessions london, new_york
strategysince 1.0

Open this page on its own · Markdown

Rule modifiers

When a rule may fire.
7

every skip max cooldown once within from

every <ordinal> | every bar#

Act on every Nth trigger, or count every bar the condition holds.

Example
when crosses_above(close, ema(close, 20)) every 4th:
buy risk: 1%, stop: 20 pips, target: 2R
strategyalertsince 1.0
skip first <n>#

Ignore the first N triggers, then act on every trigger.

Example
when crosses_above(close, ema(close, 20)) skip first 3:
buy risk: 1%, stop: 20 pips, target: 2R
strategyalertsince 1.0
max <n> per <period>#

Cap actions per day, session, hour or week.

Example
when crosses_above(close, ema(close, 20)) max 2 per day:
buy risk: 1%, stop: 20 pips, target: 2R
strategyalertsince 1.0
cooldown <duration | n bars>#

Ignore triggers for a while after acting.

Example
when rsi(close, 14) < 30 cooldown 30m:
notify "Oversold"
strategyalertsince 1.0
once per bar#

In tick mode, act at most once per bar.

Example
when close > highest(high, 20)[1] once per bar:
notify "Breakout"
strategyalertsince 1.0
within sessions <name>, ...#

Only trigger inside the named sessions.

Example
when crosses_above(close, vwap()) within sessions london, new_york:
buy risk: 1%, stop: 20 pips, target: 2R
strategyalertsince 1.0
from <time> to <time> [zone]#

Only trigger inside a daily time window.

Example
when crosses_above(close, vwap()) from 08:00 to 11:00 Europe/London:
buy risk: 1%, stop: 20 pips, target: 2R
strategyalertsince 1.0

Open this page on its own · Markdown

Events

Blocks that run when something happens.
8

start bar close tick fill exit session open day change render

on start:#

Runs once before the first evaluated bar.

Example
on start:
log "Deployed"
strategyindicatoralertsince 1.0
on bar close:#

Runs on every confirmed bar.

Example
on bar close:
log "Bar {bar.index}"
strategyindicatoralertsince 1.0
on tick:#

Runs on every price update (evaluate: tick).

Example
on tick:
log "{close}"
strategyalertsince 1.0
on fill(order):#

Runs when an order fills.

Example
on fill(order):
log "Filled {order.size}"
strategysince 1.0
on exit(trade):#

Runs when a trade closes, with trade.pnl, trade.r and trade.reason.

Example
on exit(trade):
log "Closed at {trade.r:0.00}R"
strategysince 1.0
on session open "<name>":#

Runs when a session opens.

Example
on session open "london":
log "London open"
strategyindicatoralertsince 1.0
on day change:#

Runs at each calendar day boundary.

Example
on day change:
log "New day"
strategyindicatoralertsince 1.0
on render(canvas):#

Custom vector drawing for the visible range.

Example
on render(canvas):
canvas.text("Hello", at: (canvas.last_bar, close))
strategyindicatorsince 1.0

Open this page on its own · Markdown

Units

pips, points, percent, R, money, lots, bars, duration.
8

pips points percent R money lots bars duration

pips / pip→ distance#

Distance in pips, converted with each symbol's pip size.

Example
stop_distance = 20 pips
strategyindicatoralertlibrarysince 1.0
points / point→ distance#

Distance in points, converted with each symbol's point size.

Example
buffer = 150 points
strategyindicatoralertlibrarysince 1.0
%→ fraction#

A share of a base named by context, or by `of`.

Example
risk_share = 1%
strategyindicatoralertlibrarysince 1.0
R→ distance#

Multiple of the trade's initial stop distance; valid only where a trade has a stop.

Example
buy risk: 1%, stop: 20 pips, target: 2R
strategyindicatoralertlibrarysince 1.0
$→ money#

Amount in account currency.

Example
budget = $500
strategyindicatoralertlibrarysince 1.0
lots / lot→ size#

Position size, using the symbol's contract size and lot step.

Example
size_now = 0.5 lots
strategyindicatoralertlibrarysince 1.0
bars / bar→ count#

Count of bars of the script's bar type.

Example
window = 10 bars
strategyindicatoralertlibrarysince 1.0
s / m / h / d / w / M→ time#

Wall-clock time using UTC bar timestamps.

Example
wait = 4h
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Bar variables

Built-in values: open, high, low, close, volume, time…
17

open high low close volume time hl2 hlc3 ohlc4 bar.index bar.confirmed bar.is_first bar.is_last bar.range bar.body bar.direction bar.type

open→ series<price>#

Open of the bar.

Example
first_price = open
strategyindicatoralertlibrarysince 1.0
high→ series<price>#

High of the bar.

Example
top_price = high
strategyindicatoralertlibrarysince 1.0
low→ series<price>#

Low of the bar.

Example
bottom_price = low
strategyindicatoralertlibrarysince 1.0
close→ series<price>#

Close of the bar (final on confirmed bars).

Example
last_price = close
strategyindicatoralertlibrarysince 1.0
volume→ series<number>#

Volume, or tick count on range, x-ray and renko bars where recorded.

Example
activity = volume
strategyindicatoralertlibrarysince 1.0
time→ series<time>#

Bar time (completion time on range, x-ray and renko bars).

Example
stamp = time
strategyindicatoralertlibrarysince 1.0
hl2→ series<price>#

(high + low) / 2.

Example
midpoint = hl2
strategyindicatoralertlibrarysince 1.0
hlc3→ series<price>#

(high + low + close) / 3.

Example
typical = hlc3
strategyindicatoralertlibrarysince 1.0
ohlc4→ series<price>#

(open + high + low + close) / 4.

Example
average_price = ohlc4
strategyindicatoralertlibrarysince 1.0
bar.index→ int#

Index of the bar from the start of history.

Example
n = bar.index
strategyindicatoralertlibrarysince 1.0
bar.confirmed→ bool#

True once the bar has closed.

Example
closed = bar.confirmed
strategyindicatoralertlibrarysince 1.0
bar.is_first→ bool#

True on the first evaluated bar.

Example
starting = bar.is_first
strategyindicatoralertlibrarysince 1.0
bar.is_last→ bool#

True on the last historical bar.

Example
caught_up = bar.is_last
strategyindicatoralertlibrarysince 1.0
bar.range→ distance#

high - low.

Example
span = bar.range
strategyindicatoralertlibrarysince 1.0
bar.body→ distance#

Absolute distance between open and close.

Example
body_now = bar.body
strategyindicatoralertlibrarysince 1.0
bar.direction→ int#

1 up, -1 down, 0 flat.

Example
dir = bar.direction
strategyindicatoralertlibrarysince 1.0
bar.type→ bartype#

The script's bar type.

Example
current_bars = bar.type
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Time variables

Built-in values: hour, minute, day_of_week, time_of_day
4

hour minute day_of_week time_of_day

hour→ int#

Hour of the bar time, 0 to 23, in UTC or the configured time zone.

Example
morning = hour in 8..11
strategyindicatoralertlibrarysince 1.0
minute→ int#

Minute of the bar time.

Example
on_the_hour = minute == 0
strategyindicatoralertlibrarysince 1.0
day_of_week→ int#

1 Monday to 7 Sunday.

Example
friday = day_of_week == 5
strategyindicatoralertlibrarysince 1.0
time_of_day→ time#

Clock time of the bar, for windows such as time_of_day between 08:00 and 09:00.

Example
first_hour = time_of_day between 08:00 and 09:00
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Market variables

Built-in values: market.symbol, market.name, market.category, market.pip_size, market.point_size, market.contract_size…
16

market.symbol market.name market.category market.pip_size market.point_size market.contract_size market.lot_min market.lot_max market.lot_step market.leverage_tiers market.currency_base market.currency_quote market.session market.is_open market.next_open market.next_close

market.symbol→ symbol#

Symbol the script runs on.

Example
sym = market.symbol
strategyindicatoralertlibrarysince 1.0
market.name→ string#

Display name.

Example
title = market.name
strategyindicatoralertlibrarysince 1.0
market.category→ string#

forex, crypto, index, commodity or stock.

Example
asset_class = market.category
strategyindicatoralertlibrarysince 1.0
market.pip_size→ distance#

Price size of one pip.

Example
pip = market.pip_size
strategyindicatoralertlibrarysince 1.0
market.point_size→ distance#

Price size of one point.

Example
point = market.point_size
strategyindicatoralertlibrarysince 1.0
market.contract_size→ number#

Units per lot.

Example
units = market.contract_size
strategyindicatoralertlibrarysince 1.0
market.lot_min→ lots#

Smallest order size.

Example
smallest = market.lot_min
strategyindicatoralertlibrarysince 1.0
market.lot_max→ lots#

Largest order size.

Example
largest = market.lot_max
strategyindicatoralertlibrarysince 1.0
market.lot_step→ lots#

Size increment.

Example
increment = market.lot_step
strategyindicatoralertlibrarysince 1.0
market.leverage_tiers→ list<LeverageTier>#

Leverage by position size.

Example
tiers = market.leverage_tiers
strategyindicatoralertlibrarysince 1.0
market.currency_base→ string#

Base currency.

Example
base_ccy = market.currency_base
strategyindicatoralertlibrarysince 1.0
market.currency_quote→ string#

Quote currency.

Example
quote_ccy = market.currency_quote
strategyindicatoralertlibrarysince 1.0
market.session→ Session#

Trading session times and time zone.

Example
hours = market.session
strategyindicatoralertlibrarysince 1.0
market.is_open→ bool#

True while the market is open.

Example
trading_now = market.is_open
strategyindicatoralertlibrarysince 1.0
market.next_open→ time#

Next open time.

Example
reopens = market.next_open
strategyindicatoralertlibrarysince 1.0
market.next_close→ time#

Next close time.

Example
closes = market.next_close
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Account variables

Built-in values: account.balance, account.equity, account.margin, account.free_margin, account.margin_level, account.currency…
13

account.balance account.equity account.margin account.free_margin account.margin_level account.currency account.leverage account.mode account.venue positions orders trades history

account.balance→ money#

Account balance.

Example
bal = account.balance
strategyindicatoralertsince 1.0
account.equity→ money#

Balance plus open profit and loss.

Example
eq = account.equity
strategyindicatoralertsince 1.0
account.margin→ money#

Margin in use.

Example
used = account.margin
strategyindicatoralertsince 1.0
account.free_margin→ money#

Margin available.

Example
available = account.free_margin
strategyindicatoralertsince 1.0
account.margin_level→ percent#

Equity as a percentage of margin.

Example
level = account.margin_level
strategyindicatoralertsince 1.0
account.currency→ string#

Account currency.

Example
ccy = account.currency
strategyindicatoralertsince 1.0
account.leverage→ number#

Account leverage.

Example
lev = account.leverage
strategyindicatoralertsince 1.0
account.mode→ string#

demo or live.

Example
is_live = account.mode == "live"
strategyindicatoralertsince 1.0
account.venue→ string#

house, metatrader, ibkr or a broker name.

Example
where = account.venue
strategyindicatoralertsince 1.0
positions→ list<Trade>#

Open positions on the account, filterable by symbol, side and source.

Example
open_count = positions.len
strategyindicatoralertsince 1.0
orders→ Orders#

Pending orders on the account.

Example
waiting = orders.pending(tag: "grid")
strategyindicatoralertsince 1.0
trades→ Trades#

The strategy's own trades: open(), closed(), last().

Example
mine = trades.open()
strategysince 1.0
history→ History#

Closed trades with aggregates such as pnl, win_rate and profit_factor.

Example
today_pnl = history.today.pnl
strategyindicatoralertsince 1.0

Open this page on its own · Markdown

Named colours

Built-in values: green, red, blue, gray, white, black…
10

green red blue gray white black orange yellow purple teal

green→ color#

The green color; use .fade(percent) for transparency.

Example
tint = green.fade(50)
strategyindicatoralertlibrarysince 1.0
red→ color#

The red color; use .fade(percent) for transparency.

Example
tint = red.fade(50)
strategyindicatoralertlibrarysince 1.0
blue→ color#

The blue color; use .fade(percent) for transparency.

Example
tint = blue.fade(50)
strategyindicatoralertlibrarysince 1.0
gray→ color#

The gray color; use .fade(percent) for transparency.

Example
tint = gray.fade(50)
strategyindicatoralertlibrarysince 1.0
white→ color#

The white color; use .fade(percent) for transparency.

Example
tint = white.fade(50)
strategyindicatoralertlibrarysince 1.0
black→ color#

The black color; use .fade(percent) for transparency.

Example
tint = black.fade(50)
strategyindicatoralertlibrarysince 1.0
orange→ color#

The orange color; use .fade(percent) for transparency.

Example
tint = orange.fade(50)
strategyindicatoralertlibrarysince 1.0
yellow→ color#

The yellow color; use .fade(percent) for transparency.

Example
tint = yellow.fade(50)
strategyindicatoralertlibrarysince 1.0
purple→ color#

The purple color; use .fade(percent) for transparency.

Example
tint = purple.fade(50)
strategyindicatoralertlibrarysince 1.0
teal→ color#

The teal color; use .fade(percent) for transparency.

Example
tint = teal.fade(50)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Types

Records the language hands you: Trade, Order, Bar, Zone, Canvas and more.
18

Bar BarState BarSet Zone Level Swing Cell Trade Order Trades Orders HistoryPeriod History Session LeverageTier Canvas Path color

Bar#

One bar.

Fields

NameTypeWhat it is
openpriceOpen.
highpriceHigh.
lowpriceLow.
closepriceClose.
volumenumberVolume, or tick count on range, x-ray and renko bars.
timetimeBar time.
indexintBar index.
Example
first_high = intrabar(1m).first().high
strategyindicatoralertlibrarysince 1.0
BarState#

Status of a bar set.

Fields

NameTypeWhat it is
freshboolfalse when this symbol had no bar in the latest interval.
indexintBar index.
confirmedbooltrue once the bar has closed.
Example
gold_fresh = bars(XAUUSD).bar.fresh
strategyindicatoralertlibrarysince 1.0
BarSet#

Bars of a symbol and bar type, aligned to the script.

Fields

NameTypeWhat it is
openpriceOpen.
highpriceHigh.
lowpriceLow.
closepriceClose.
volumenumberVolume, or tick count on range, x-ray and renko bars.
timetimeBar time.
barBarStateBar status.
Example
h4_close = bars(bars: 4h).close
strategyindicatoralertlibrarysince 1.0
Zone#

A price zone, such as an order block or fair value gap.

Fields

NameTypeWhat it is
idstringStable id.
toppriceUpper bound.
bottompriceLower bound.
midpriceMidpoint.
bullishbooltrue for bullish zones.
mitigatedbooltrue once price has traded back into it.
formed_barintBar index where it formed.
formed_timetimeWhen it formed.
touchesintTimes price has returned to it.
statusstringactive, mitigated or broken.
Example
fresh_blocks = order_blocks().filter(z => not z.mitigated)
strategyindicatoralertlibrarysince 1.0
Level#

A support or resistance level.

Fields

NameTypeWhat it is
pricepriceLevel price.
touchesintTouches.
formed_barintBar index where it formed.
strengthnumberRelative strength from 0 to 1.
Example
strong_levels = support_resistance().filter(l => l.touches >= 3)
strategyindicatoralertlibrarysince 1.0
Swing#

A swing point.

Fields

NameTypeWhat it is
pricepriceSwing price.
barintBar index.
timetimeTime.
directionint1 for a swing high, -1 for a swing low.
Example
last_turn = zigzag().last().price
strategyindicatoralertlibrarysince 1.0
Cell#

One heatmap or footprint cell.

Fields

NameTypeWhat it is
barintBar index.
pricepricePrice.
valuenumberValue shown.
Example
hot_cells = liquidity_cells.filter(c => c.value > 0)
strategyindicatoralertlibrarysince 1.0
Trade#

An open or closed trade.

Fields

NameTypeWhat it is
idstringTrade id.
symbolsymbolSymbol.
sidestringlong or short.
sizelotsSize.
entry_pricepriceEntry price.
entry_timetimeEntry time.
exit_pricepriceExit price, once closed.
stoppriceCurrent stop.
targetpriceCurrent target.
rnumberCurrent R multiple.
pnlmoneyProfit or loss.
pnl_pctpercentProfit or loss as a share of balance.
maemoneyMaximum adverse excursion.
mfemoneyMaximum favorable excursion.
bars_openintBars since entry.
tagstringTag.
reasonstringWhy it closed: target, stop, rule, manual or management.
Example
best_r = trades.closed().map(t => t.r).max()
strategyindicatoralertlibrarysince 1.0
Order#

A pending or filled order.

Fields

NameTypeWhat it is
idstringOrder id.
typestringmarket, limit, stop or stop_limit.
sidestringbuy or sell.
symbolsymbolSymbol.
pricepriceOrder price.
sizelotsSize.
expirestimeExpiry time.
tagstringTag.
Example
grid_count = orders.pending(tag: "grid").len
strategyindicatoralertlibrarysince 1.0
Trades#

The strategy's own trades.

Methods

MethodReturnsWhat it does
open(tag, side, market)list<Trade>Open trades.
closed(tag, side, market)list<Trade>Closed trades.
last(tag, side, market)TradeThe most recent trade.
Example
open_longs = trades.open(side: long).len
strategysince 1.0
Orders#

Pending orders on the account.

Methods

MethodReturnsWhat it does
pending(tag, side, market)list<Order>Pending orders.
Example
waiting_count = orders.pending().len
strategyindicatoralertlibrarysince 1.0
HistoryPeriod#

Aggregates of closed trades for a period.

Fields

NameTypeWhat it is
countintClosed trades.
pnlmoneyNet profit or loss.
win_ratepercentShare of winning trades.
profit_factornumberGross profit divided by gross loss.
expectancymoneyAverage result per trade.
max_drawdownmoneyLargest peak-to-trough decline.
avg_rnumberAverage R multiple.
Example
week_pnl = history.this_week.pnl
strategyindicatoralertlibrarysince 1.0
History#

Closed trades on the account.

Fields

NameTypeWhat it is
todayHistoryPeriodToday.
this_weekHistoryPeriodThis week.
this_monthHistoryPeriodThis month.
countintClosed trades.
pnlmoneyNet profit or loss.
win_ratepercentShare of winning trades.
profit_factornumberGross profit divided by gross loss.
expectancymoneyAverage result per trade.
max_drawdownmoneyLargest peak-to-trough decline.
avg_rnumberAverage R multiple.

Methods

MethodReturnsWhat it does
last(period)HistoryPeriodA trailing period.
Example
month_win_rate = history.last(30d).win_rate
strategyindicatoralertlibrarysince 1.0
Session#

A trading session.

Fields

NameTypeWhat it is
namestringSession name.
opentimeOpen time.
closetimeClose time.
timezonestringTime zone.
Example
opens_at = market.session.open
strategyindicatoralertlibrarysince 1.0
LeverageTier#

Leverage for a band of position sizes.

Fields

NameTypeWhat it is
max_sizelotsLargest size in the band.
leveragenumberLeverage.
Example
tier_count = market.leverage_tiers.len
strategyindicatoralertlibrarysince 1.0
Canvas#

The vector canvas passed to on render.

Fields

NameTypeWhat it is
last_barintIndex of the last bar.
visible_fromintFirst visible bar.
visible_tointLast visible bar.
price_minpriceLowest visible price.
price_maxpriceHighest visible price.
widthnumberWidth in pixels.
heightnumberHeight in pixels.

Methods

MethodReturnsWhat it does
path()PathStart a new shape.
text(text, at, align, color, size)voidDraw text.
rect(from, to, fill, border)voidDraw a rectangle.
line(from, to, color, width)voidDraw a line.
Example
on render(canvas):
canvas.text("Hi", at: (canvas.last_bar, close))
strategyindicatorsince 1.0
Path#

A vector shape being drawn.

Methods

MethodReturnsWhat it does
move_to(bar, price)PathMove without drawing.
line_to(bar, price)PathDraw a straight segment.
curve_to(bar, price, control_bar, control_price)PathDraw a curved segment.
close()PathClose the shape.
fill(style)PathFill the shape.
stroke(color, width)PathOutline the shape.
Example
on render(canvas):
shape = canvas.path()
strategyindicatorsince 1.0
color#

Functions available on every color.

Methods

MethodReturnsWhat it does
fade(amount)colorThe same color with transparency.
Example
soft_green = green.fade(80)
strategyindicatoralertlibrarysince 1.0

Open this page on its own · Markdown

Execution Rules

24 rules · how every order fills, in writing

These rules say exactly how orders fill and how trades are managed. Every rule has test cases, and the backtester, the demo engine and live trade management must all pass them. Rule IDs are stable: a change in behaviour gets a new rule ID. Nothing in these rules adds costs.

Timing

E1 Bar-close evaluation, E2 Tick evaluation
2
E1Bar-close evaluation#

Scripts with evaluate: bar_close (the default) run after each bar closes. Orders created at that close take effect from the next bar: market orders fill at the next bar's open, and pending orders can first fill during the next bar. A market order created at the last bar of a test never fills and is reported as unfilled.

E2Tick evaluation#

Scripts with evaluate: tick run at every point of the price path (E6), and market orders fill at the price of the point that triggered them, without waiting for the bar to close. Live, that is the next tick after the condition becomes true; in a backtest it is the next stored price. When a bar has no finer stored data, its own path is used and the run is labelled "approximate intrabar", listing the bars affected.

Inside a forming bar, prices are live and indicators are not: close, high, low and everything derived from them move with the tick, while indicator values stay as they were at the last bar close, because a bar that has not finished cannot have changed them yet. bar.confirmed is false during a tick and true at the close. Pending orders placed by a tick still wait for the next bar, as in E1.

Open this page on its own · Markdown

Fills

E3 Limit orders, E4 Stop orders, E5 Stops and targets, E6 Price path inside a bar, E7 Stop before target, E8 Same-bar exits
6
E3Limit orders#

A buy limit at price L fills at the bar's open when the open is at or below L; otherwise it fills at L when the price path reaches L. A sell limit mirrors this above the market. Touching the price is enough; queue position is not modelled.

Backtests have no spread, so one price per bar triggers and fills every order. Live and demo trading use the side that can actually trade: a buy is triggered and filled on the ask, a sell on the bid. A script never chooses a side; the deployment does.

E4Stop orders#

A buy stop at price S fills at the bar's open when the open is at or above S; otherwise it fills at S when the price path reaches S. A sell stop mirrors this below the market. Live, a buy stop triggers on the ask and a sell stop on the bid, as in E3.

E5Stops and targets#

A trade's stop and target are closing orders: a long trade's stop is a sell stop and its target a sell limit, and a short trade's are the mirror. They fill under E3 and E4, including at the open when a bar gaps past them. Live, a long trade's stop and target are triggered on the bid and a short trade's on the ask, because that is the side that closes them.

E6Price path inside a bar#

When events inside a bar need an order, the 1-minute bars inside it are used, because 1m is the stored base resolution; sub-minute history is not kept beyond the most recent bars, and tick data arrives later. A 1-minute bar, or any bar with no finer data stored, follows the path open → nearer extreme → farther extreme → close, where the nearer extreme is whichever of the high and low is closer to the open. When both are equally close, a bar that closes at or above its open goes to the low first, and a bar that closes below its open goes to the high first. Every price between two path points is passed through in order. Reports name the resolution each run used.

E7Stop before target#

When a trade's stop and target are both reached within one bar after the trade exists, and finer data cannot tell which came first, the stop fills. This applies even when the path of E6 would reach the target first.

E8Same-bar exits#

A trade's stop, target and management are active from the moment it fills, so a trade can close in the bar where it opened, following E6 and E7.

Open this page on its own · Markdown

Prices, distances and size

E9 Distances and R, E10 Price rounding, E11 Risk-based size, E12 No costs
4
E9Distances and R#

Distances given in pips, points or price are measured from the actual fill price, so a gap moves the stop and target with the entry. Price levels are used as given. R is the distance between the actual fill price and the initial stop, fixed when the trade opens; for a pending stop order the initial stop is its stop_loss.

E10Price rounding#

Every order, stop and target price is rounded to the symbol's tick size when it is set, with halves rounded away from zero, using decimal arithmetic.

E11Risk-based size#

Size = risk amount ÷ (stop distance × contract size × quote-to-account rate), rounded down to the lot step, then held between the symbol's minimum and maximum lot. Percent risk uses the balance, and the stop distance is measured from the actual fill price, both at the moment of the fill. A size that rounds below the minimum lot trades at the minimum lot, and the trade is marked "above requested risk" with the risk it actually carries, so reports and the Terminal can show it.

E12No costs#

Fills carry no spread, commission, fees, swaps or slippage. Profit is (exit price − entry price) × size × contract size × quote-to-account rate at the exit, negated for short trades. Gap fills at the open (E3–E5) are prices that traded, not slippage.

Open this page on its own · Markdown

Trade management

E13 Breakeven, E14 Trailing stops, E15 Partial closes, E16 Time and condition exits, E17 Pending order expiry
5
E13Breakeven#

When the price path reaches the at level, the stop moves to the entry price plus offset for a long trade (minus for a short trade) if that tightens it. The new stop applies to the rest of the path.

E14Trailing stops#

Once the price path reaches the after level, the stop follows the most favourable price reached since then, less by for a long trade (plus for a short trade), and only ever tightens. It updates at every point of the path. Distances that come from indicators use their value at the last closed bar.

E15Partial closes#

partial P at: X closes P of the trade's original size when the price path reaches X (at X, or at the open when the bar gaps past it), rounded down to the lot step. A partial that rounds to zero is skipped. If the size left would fall below the minimum lot, the whole trade closes. Each partial fires once.

E16Time and condition exits#

exit after: N bars closes a trade at the open of the bar after the Nth bar close following its entry bar. exit after: with a duration closes it at the open after the first bar close at or beyond that time since the fill. exit when: closes it at the open after the bar close where the condition is true.

E17Pending order expiry#

expires: N bars keeps an order active for the N bars after the bar that created it; expires: with a duration keeps it active until the first bar close at or beyond that time. An order that has not filled by then is cancelled at that close. Pending orders still open when a test ends are cancelled.

Open this page on its own · Markdown

Strategy controls

E18 Opposite signals, E19 Limits checked at the fill, E20 Loss guards, E21 Order of work at a bar close, E22 Trading hours
5
E18Opposite signals#

With opposite: ignore (the default), entries opposite an open trade are rejected. With close, the opposite entry closes open trades at its fill price and opens nothing. With reverse, it closes open trades and opens the new trade at the same price. With hedge, it opens alongside open trades where the venue supports hedging, and behaves as ignore elsewhere.

E19Limits checked at the fill#

When an entry fills, it is rejected with a reason if it would exceed max_open, max_open_per_side, one plus pyramiding trades in the same direction, or max_total_risk, or if it would be closer than min_distance to the entry price of an open trade in the same direction. Pending orders are checked when they fill, not when they are placed.

E20Loss guards#

At each bar close, the day's closed profit plus the open profit at that close is compared with max_daily_loss. When the limit is reached, all trades close and pending orders are cancelled at the next bar's open, and new entries are rejected until the next UTC day. max_drawdown works the same way against the highest equity reached, and pauses the deployment until it is resumed.

E21Order of work at a bar close#

At each bar close the runtime (1) completes the fills and management inside the bar in path order, (2) runs on fill and on exit for them in the order they happened, (3) runs calculations, (4) updates confirmations and sequences, (5) runs rules and on bar close in script order, (6) records exports and drawing, so outputs always see this bar's final values, and (7) queues the orders the rules created for the next bar. Queued closes run before queued entries. Indicator calls update on every bar, even when their line sits in a branch that did not run.

E22Trading hours#

With trade_only, entries are only created at the close of bars that open inside the listed sessions; other entries are skipped with a reason. Exits, management and pending orders already placed continue outside the sessions.

Open this page on its own · Markdown

Results

E23 Reproducibility, E24 End of test
2
E23Reproducibility#

The same script version, inputs, symbols, bar types, dates, dataset version and runtime version always produce the same fills, to the last digit.

E24End of test#

Trades still open when a test ends are closed at the last bar's close and marked "open at end", so results include them.

Open this page on its own · Markdown

Compiler Messages

50 codes · what each one means

The compiler checks a script before a single bar is touched. Every message says what is wrong and what to do, and many carry a one-click fix. There are 50 codes, and a code is never reused for a different meaning. Where a message is shown below, it is the compiler's real output for a small mistake.

Text and layout

AS0001, AS0002, AS0003, AS0004, AS0005, AS0006
6
AS0001unexpected_char#
AS0002unterminated_stringerror#

This text is missing its closing quote (").

AS0003tab_indenterror#

Use spaces, not tabs, to indent.

AS0004bad_dedent#
AS0005number_suffix#
AS0006unterminated_interpolation#

Open this page on its own · Markdown

Syntax

AS0010, AS0011, AS0012, AS0013, AS0014, AS0015, AS0016…
9
AS0010expected#
AS0011missing_colonerror#

Missing ":" after the rule condition.

Quick fix Insert ":"

AS0012missing_headererror#

A script starts with its type and a name, such as strategy "My Strategy" or indicator "My Indicator".

AS0013no_effect#
AS0014bad_version#
AS0015unknown_modifier#
AS0016expected_blockerror#

Put what the rule does on indented lines below.

AS0017bad_target#
AS0018stray_indent#

Open this page on its own · Markdown

Names and types

AS0201, AS0202, AS0203, AS0204, AS0205, AS0206, AS0207…
20
AS0201unknown_nameerror#

crosses_abve isn't a function. Did you mean crosses_above?

Quick fix Change to crosses_above

AS0202duplicate#
AS0203future_valueerror#

close[-1] would read a future bar. History counts back from the current bar: close[1] is the previous bar.

AS0204type_mismatcherror#

+ needs numbers, but this combines a price and text.

AS0205not_callable#
AS0206bad_argumenterror#

length must be at least 1.

AS0207missing_argumenterror#

crosses_above needs b (series or level crossed).

AS0208unknown_membererror#

top isn't a field of Bands.

AS0209read_only#
AS0210used_before#
AS0211unknown_type#
AS0212bad_return#
AS0213bad_loop_control#
AS0214unknown_settingerror#

max_opn isn't a strategy setting. Did you mean max_open?

Quick fix Change to max_open

AS0215bad_setting#
AS0216unresolved_import#
AS0217not_iterable#
AS0218unknown_eventerror#

on candle isn't an event. Events are start, bar close, tick, fill(order), exit(trade), session open, day change and render(canvas).

AS0219input_not_fixed#
AS0220nested_declaration#

Open this page on its own · Markdown

Units and risk

AS0301, AS0302, AS0303, AS0304, AS0305, AS0306
6
AS0301r_outside_trade#
AS0302bare_numberwarning#

stop 25 has no unit. Did you mean 25 pips?

Quick fix Use 25 pips · Use 25 points

AS0303r_without_stoperror#

2R needs a stop to measure from. Add a stop to this trade, such as stop: 20 pips.

AS0304risk_without_stoperror#

Risk-based size needs a stop to measure risk from. Add a stop, such as stop: 20 pips.

AS0305percent_baseerror#

1% of what? A percentage needs a base here, such as 1% of 20 pips.

Quick fix Use 1% of 20 pips

AS0306incompatible_units#

Open this page on its own · Markdown

Where things may go

AS0401, AS0402, AS0403, AS0404, AS0405
5
AS0401wrong_scripterror#

buy places or manages trades, which only strategies do. Use this indicator in a strategy instead.

AS0402management_placementerror#

breakeven only works inside the management block of a buy or sell. Indent it under the entry.

AS0403pure_functionerror#

Only action functions can place or change orders; write action fn f.

AS0404needs_tickerror#

on tick needs evaluate: tick in the header.

Quick fix Add evaluate: tick to the header

AS0405library_contenterror#

A library holds functions, types, enums and constants. Move this into a strategy, indicator or alert.

Open this page on its own · Markdown

Data

AS0501, AS0502, AS0503
3
AS0501brick_pattern#
AS0502unknown_symbol#
AS0503unknown_sessionerror#

mars isn't a session. Sessions are sydney, tokyo, asia, london, frankfurt and new_york.

Open this page on its own · Markdown

Hints

AS0601
1
AS0601unused_inputwarning#

Input unused is never used.

Quick fix Remove input unused

Open this page on its own · Markdown

Examples

61 scripts · filter by what they demonstrate

61 complete scripts covering every part of the language. Each one compiles, and each is shown with the compiler's own plain-English description. Copy one into the Terminal and change it. They are teaching examples, not recommendations, and none of them is a forecast of results.

EMA Cross

EMA Cross is a strategy that trades EURUSD on 15-minute bars.
strategy

core language

ema-cross.abx
1strategy "EMA Cross"
2market: EURUSD
3bars: 15m
4
5input fast = 20
6input slow = 50
7
8when crosses_above(ema(close, fast), ema(close, slow)):
9buy risk: 1%, stop: 25 pips, target: 2R
10
11when crosses_below(ema(close, fast), ema(close, slow)):
12close_all
What this script says

EMA Cross is a strategy that trades EURUSD on 15-minute bars.

You can change 2 inputs: fast (default 20) and slow (default 50).

When the EMA of the close over fast bars crosses above the EMA of the close over slow bars, it buys at market, risking 1% of the balance, with a stop 25 pips from the entry and with a target 2R from the entry.

When the EMA of the close over fast bars crosses below the EMA of the close over slow bars, it closes all trades.

Open this page on its own · Markdown

Six-Confirmation Momentum

Six-Confirmation Momentum is a strategy that trades XAUUSD on 5-minute bars. It holds at most 1 open trade and stops for the day after losing 3%.
strategy

confirmationstrade managementother bar sizesuses a library or indicatorsmart moneysessions and time

six-confirmation-momentum.abx
1strategy "Six-Confirmation Momentum"
2market: XAUUSD
3bars: 5m
4max_open: 1
5max_daily_loss: 3%
6
7use indicator "Trend Ribbon" v3 as ribbon (fast: 10, slow: 30)
8
9input risk = 0.5%
10
11confirmations long_setup:
12trend: ema(close, 50) > ema(close, 200)
13higher_tf: bars(bars: 1h).close > ema(bars(bars: 1h).close, 50)
14momentum: rsi(close, 14) between 55 and 70
15volume: volume > sma(volume, 20) * 1.5
16structure: break_of_structure(direction: up)
17ribbon: ribbon.up and ribbon.strength > 0.5
18require: all
19
20when long_setup.passed as long_entry every 4th within sessions london, new_york:
21buy risk: risk, stop: lowest(low, 10) - 5 points, target: 3R, tag: "momentum":
22breakeven at: 1R
23partial 50% at: 2R
24trail by: atr(14) * 1.5, after: 2R
25exit after: 60 bars
26
27on exit(trade):
28log "{trade.tag} closed at {trade.r:0.00}R after {long_entry.triggers} triggers"
What this script says

Six-Confirmation Momentum is a strategy that trades XAUUSD on 5-minute bars. It holds at most 1 open trade and stops for the day after losing 3%.

It uses the indicator "Trend Ribbon" (version 3) as ribbon, with fast set to 10 and slow set to 30.

You can change one input: risk (default 0.5%).

long_setup passes when all of these 6 conditions are true: trend (the 50-bar EMA of the close is above the 200-bar EMA of the close); higher_tf (the close of 1-hour bars is above the 50-bar EMA of the close of 1-hour bars); momentum (the 14-bar RSI is between 55 and 70); volume (volume is above 1.5 × the 20-bar SMA of volume); structure (a bullish break of structure); ribbon (ribbon.up and ribbon.strength is above 0.5).

When long_setup passes (on every 4th time and during the London and New York sessions), it buys at market, risking risk of the balance, with a stop at the lowest low of the last 10 bars minus 5 points, with a target 3R from the entry and tagged "momentum"; once open, it moves the stop to breakeven at 1R, closes 50% at 2R, trails the stop by 1.5 × the 14-bar ATR once the trade reaches 2R and exits after 60 bars.

When a trade closes, it logs "{trade.tag} closed at {trade.r:0.00}R after {long_entry.triggers} triggers".

This description may be incomplete because the script has errors.

Open this page on its own · Markdown

Ribbon Multi-Timeframe

Ribbon Multi-Timeframe is a strategy that trades GBPUSD on 15-minute bars.
strategy

uses a library or indicator

ribbon-multi-timeframe.abx
1strategy "Ribbon Multi-Timeframe"
2market: GBPUSD
3bars: 15m
4
5use indicator "Trend Ribbon" v3 as ribbon (fast: 10, slow: 30)
6
7ribbon_4h = ribbon.on(bars: 4h)
8
9when ribbon_4h.up and crosses_above(close, ribbon.fast) and ribbon.strength > 0.5:
10buy risk: 1%, stop: atr(14) * 1.5, target: 2R
11
12when ends(ribbon.up):
13close_all side: long
What this script says

Ribbon Multi-Timeframe is a strategy that trades GBPUSD on 15-minute bars.

It uses the indicator "Trend Ribbon" (version 3) as ribbon, with fast set to 10 and slow set to 30.

It calculates ribbon_4h as ribbon.on(bars: 4h).

When ribbon_4h.up and the close crosses above ribbon.fast and ribbon.strength is above 0.5, it buys at market, risking 1% of the balance, with a stop 1.5 × the 14-bar ATR from the entry and with a target 2R from the entry.

When ribbon.up stops being true, it closes all long trades.

This description may be incomplete because the script has errors.

Open this page on its own · Markdown

Sweep and Reclaim

Sweep and Reclaim is a strategy that trades XAUUSD on 20-tick range bars.
strategy

sequencerenko, heikin ashi, x-ray

sweep-and-reclaim.abx
1strategy "Sweep and Reclaim"
2market: XAUUSD
3bars: range(20)
4
5sequence grab within 25 bars:
6step sweep: low < lowest(low, 30)[1]
7step reclaim: close > sweep.high
8step retest: low <= reclaim.close and close > reclaim.close
9reset_if: close < sweep.low
10
11when grab.completed:
12buy risk: 1%, stop: grab.sweep.low - 3 points, target: 2.5R
What this script says

Sweep and Reclaim is a strategy that trades XAUUSD on 20-tick range bars.

grab completes when these steps happen in order within 25 bars: sweep, when the low is below the previous bar's lowest low of the last 30 bars; then reclaim, when the close is above sweep.high; then retest, when the low is at or below reclaim.close and the close is above reclaim.close. It starts over if the close is below sweep.low.

When grab completes, it buys at market, risking 1% of the balance, with a stop at the low of the sweep step minus 3 points and with a target 2.5R from the entry.

Open this page on its own · Markdown

EURUSD and GBPUSD Mean Reversion

EURUSD and GBPUSD Mean Reversion is a strategy that trades EURUSD and GBPUSD on 1-hour bars. It holds at most 2 open trades.
strategy

several marketsstatistics and matrices

eurusd-and-gbpusd-mean-reversion.abx
1strategy "EURUSD and GBPUSD Mean Reversion"
2markets: EURUSD, GBPUSD
3bars: 1h
4max_open: 2
5
6input lookback = 200
7input entry_z = 2.0
8input exit_z = 0.5
9
10eur = bars(EURUSD)
11gbp = bars(GBPUSD)
12hedge = beta(returns(eur.close), returns(gbp.close), lookback)
13z = zscore(log(eur.close / gbp.close), lookback)
14
15when z > entry_z and trades.open(tag: "pair").len == 0:
16eur_size = size_for(EURUSD, risk: 0.5%, stop: atr(14, on: eur) * 3)
17sell market: EURUSD, size: eur_size, tag: "pair"
18buy market: GBPUSD, size: eur_size * hedge, tag: "pair"
19
20when abs(z) < exit_z:
21close_all tag: "pair"
What this script says

EURUSD and GBPUSD Mean Reversion is a strategy that trades EURUSD and GBPUSD on 1-hour bars. It holds at most 2 open trades.

You can change 3 inputs: lookback (default 200), entry_z (default 2.0) and exit_z (default 0.5).

It calculates eur as EURUSD bars, gbp as GBPUSD bars, hedge as the beta of the returns of eur.close against the returns of gbp.close over lookback bars and z as the z-score of the logarithm of eur.close divided by gbp.close over lookback bars.

When z is above entry_z and the number of open trades tagged "pair" is 0, it sets eur_size to the size of EURUSD that risks 0.5% with a stop 3 × the 14-bar ATR of eur away; it also sells EURUSD at market, with a size of eur_size and tagged "pair"; it also buys GBPUSD at market, with a size of eur_size × hedge and tagged "pair".

When the absolute value of z is below exit_z, it closes all trades tagged "pair".

Open this page on its own · Markdown

Language Tour

Language Tour is a strategy that trades EURUSD and GBPUSD on 15-minute bars. It holds at most 3 open trades (2 per side), reverses on an opposite sign
strategy

confirmationssequencetrade managementother bar sizesseveral marketsinside the barrenko, heikin ashi, x-rayuses a library or indicatorcanvastables and dashboardsaccount and historystatefunctions and typessmart moneystatistics and matricessessions and timepending orders

language-tour.abx
1algobarsx 1
2# Exercises every construct in spec sections 3-16.
3strategy "Language Tour"
4markets: EURUSD, GBPUSD
5bars: 15m
6evaluate: bar_close
7max_open: 3
8max_open_per_side: 2
9direction: both
10opposite: reverse
11pyramiding: 3
12min_distance: 20 pips
13max_daily_loss: 3%
14max_drawdown: 10%
15trade_only: within sessions london, new_york
16
17use indicator "Trend Ribbon" v3 as ribbon (fast: 10, slow: 30)
18use library "Quant Toolkit" v2 as qt
19
20input fast = 20, label: "Fast length", min: 2, max: 500, group: "Trend"
21input source = close, label: "Source"
22input higher_tf = 4h, label: "Higher timeframe"
23input session = "london", options: ["london", "new_york", "asia"]
24input risk = 1%, min: 0.1%, max: 5%, step: 0.1%
25input show_zones = true, group: "Display"
26input zone_color = blue.fade(70), group: "Display", visible_if: show_zones
27
28const RISK_CAP = 2%
29
30type Level:
31price: price
32touched: int = 0
33formed_at: time
34
35enum Regime: trending, ranging, volatile
36
37fn swing_strength(len: int) -> number:
38up = highest(high, len) - close
39down = close - lowest(low, len)
40return (down - up) / atr(14)
41
42action fn enter_long(size_risk: percent = 1%) -> bool:
43buy risk: size_risk, stop: 20 pips, target: 2R
44return true
45
46state triggers = 0
47state last_entry: price = na
48state regime = Regime.ranging
49state levels: list<Level> = []
50
51trend_up = ema(close, 50) > ema(close, 200)
52distance = (source - ema(source, fast)) / atr(14)
53threshold: number = 1.5
54h4 = bars(bars: higher_tf)
55gold = bars(XAUUSD, bars: 15m)
56gold_atr = atr(14, on: gold)
57cov = data.coverage(EURUSD, bars: range(10))
58spread_z = zscore(log(close_of(EURUSD) / close_of(GBPUSD)), 100)
59first_hour = time_of_day between 08:00 and 09:00
60recent_high = intrabar(1m).high.max()
61kelly = qt.kelly_fraction(0.55, 1.8)
62power = 2 ** 3 ** 2
63in_window = hour in 8..11
64
65if regime == Regime.trending:
66risk_now = 1%
67elif regime == Regime.volatile:
68risk_now = 0.5%
69else:
70risk_now = 0.25%
71
72for level in levels:
73if close > level.price:
74level.touched += 1
75
76for i in 0..50:
77if i > 10:
78break
79continue
80
81match regime:
82Regime.trending: log "trending"
83Regime.ranging: log "ranging"
84
85levels.push(Level(price: high, formed_at: time))
86levels = levels.filter(l => l.touched == 0).keep_last(50)
87ranked = levels.sort_by((a, b) => a.price - b.price)
88
89confirmations long_setup:
90trend: trend_up
91momentum: rsi(close, 14) > 55
92volume: volume > sma(volume, 20) * 1.5
93structure: break_of_structure(direction: up)
94higher_tf_trend: h4.close > ema(h4.close, 50)
95ribbon_up: ribbon.up
96require: at least 5
97
98sequence liquidity_grab within 30 bars:
99step sweep: low < lowest(low, 20)[1]
100step reclaim: close > sweep.high
101step retest: low <= reclaim.close and close > reclaim.close
102reset_if: close < sweep.low
103
104when long_setup.passed as long_entry every 4th:
105buy risk: risk, stop: atr(14) * 1.5, target: 3R
106
107when starts(long_setup.passed) skip first 3 max 2 per day cooldown 30m:
108triggers += 1
109if triggers % 4 == 0:
110buy risk: 0.5%, stop: atr(14) * 1.5, target: 3R
111
112when liquidity_grab.completed from 08:00 to 11:00 Europe/London:
113buy risk: 1%, stop: liquidity_grab.sweep.low - 3 points, target: 2R + 5 pips, tag: "breakout":
114breakeven at: 1R, offset: 2 pips
115partial 30% at: 1.5R
116partial 30% at: 2.5R
117trail by: atr(14), after: 2R
118exit after: 48 bars
119exit when: crosses_below(close, ema(close, 20))
120
121when crosses_below(close, ema(close, 50)) cooldown 5 bars:
122sell risk: $200, stop: highest(high, 10) + 2 pips, target: lowest(low, 50)
123
124when was(trend_up, within: 5 bars) and held(close > open, for: 3 bars) every bar:
125buy limit: lowest(low, 5), size: 1 lot, expires: 10 bars
126buy stop: high + 2 pips, risk: 0.5%, stop_loss: low - 2 pips, target: 2R, ghost: true
127sell market: GBPUSD, size: 0.3 lots
128
129when history.today.pnl < -(2% of account.balance) or account.margin_level < 150%: close_all
130
131for trade in trades.open(tag: "breakout"):
132if trade.r >= 3 and rsi(close, 14) > 75:
133close trade, size: 50%
134
135for trade in trades.open(side: long):
136modify trade, stop: trade.entry_price
137
138cancel orders.pending(tag: "grid")
139
140on start:
141log "starting on {market.symbol}"
142
143on bar close:
144log "bar {bar.index}"
145
146on fill(order):
147log "filled {order.size}"
148
149on exit(trade):
150log "{trade.tag} closed at {trade.r:0.00}R after {long_entry.triggers} triggers"
151
152on session open "new_york":
153log "New York is open"
154
155on day change:
156triggers = 0
157
158on render(canvas):
159for z in levels:
160shape = canvas.path()
161shape.move_to(z.formed_at, z.price)
162shape.line_to(canvas.last_bar, z.price)
163shape.stroke(zone_color, width: 1)
164canvas.text("{z.touched}x", at: (canvas.last_bar, z.price), align: right)
165
166plot ema(close, fast) as fast_line, color: if trend_up then green else red, width: 2
167plot (high + low) / 2, color: gray, style: step
168fill ribbon.fast, ribbon.slow, color: green.fade(80)
169hline 70, style: dashed, color: #22c55e
170mark arrow_up, at: below, when: crosses_above(close, ema(close, fast)), color: green
171label "Entry", at: (bar.index, high)
172line from: (bar.index - 20, lowest(low, 20)), to: (bar.index, lowest(low, 20)), extend: right
173box id: "range", from: (bar.index - 10, highest(high, 10)), to: (bar.index, lowest(low, 10)), color: blue.fade(85)
174bar_color if close > open then green else red
175background red.fade(90), when: regime == Regime.volatile
176profile rows: 24, range: session, side: right
177fib from: (bar.index - 50, lowest(low, 50)), to: (bar.index, highest(high, 50))
178dashboard position: top_right, rows: [["Regime", "{regime}"], ["Triggers", "{triggers}"]]
What this script says

Language Tour is a strategy that trades EURUSD and GBPUSD on 15-minute bars. It holds at most 3 open trades (2 per side), reverses on an opposite signal, adds up to 3 entries in the same direction, keeps at least 20 pips between entries, stops for the day after losing 3%, stops trading after a 10% drawdown and trades only during the London and New York sessions.

It uses the indicator "Trend Ribbon" (version 3) as ribbon, with fast set to 10 and slow set to 30.

It uses the library "Quant Toolkit" (version 2) as qt.

You can change 7 inputs: fast (default 20, shown as "Fast length"), source (default close, shown as "Source"), higher_tf (default 4h, shown as "Higher timeframe"), session (default "london"), risk (default 1%), show_zones (default true) and zone_color (default blue.fade(70)).

It defines the constant RISK_CAP as 2%.

It defines swing_strength(len), which returns a number and the action enter_long(size_risk), which returns true or false.

It remembers triggers, last_entry, regime and levels from one bar to the next.

It calculates trend_up as whether the 50-bar EMA of the close is above the 200-bar EMA of the close, distance as (source minus the EMA of source over fast bars) divided by the 14-bar ATR, threshold as 1.5, h4 as higher_tf bars, gold as XAUUSD 15-minute bars, gold_atr as the 14-bar ATR of gold, cov as the data.coverage (symbol EURUSD, bars the range (size 10)), spread_z as the 100-bar z-score of the logarithm of the close of EURUSD divided by the close of GBPUSD, first_hour as whether the time of day is between 08:00 and 09:00, recent_high as intrabar(1m).high.max(), kelly as qt.kelly_fraction(0.55, 1.8), power as 2 to the power of 3 to the power of 2 and 3 more values.

long_setup passes when at least 5 of these 6 conditions are true: trend (trend_up); momentum (the 14-bar RSI is above 55); volume (volume is above 1.5 × the 20-bar SMA of volume); structure (a bullish break of structure); higher_tf_trend (h4.close is above the 50-bar EMA of h4.close); ribbon_up (ribbon.up).

liquidity_grab completes when these steps happen in order within 30 bars: sweep, when the low is below the previous bar's lowest low of the last 20 bars; then reclaim, when the close is above sweep.high; then retest, when the low is at or below reclaim.close and the close is above reclaim.close. It starts over if the close is below sweep.low.

When long_setup passes (on every 4th time), it buys at market, risking risk of the balance, with a stop 1.5 × the 14-bar ATR from the entry and with a target 3R from the entry.

When long_setup passes becomes true (ignoring the first 3 times, at most 2 times per day and waiting at least 30 minutes between actions), it adds 1 to triggers; it also checks whether triggers modulo 4 is 0 and, if so, buys at market, risking 0.5% of the balance, with a stop 1.5 × the 14-bar ATR from the entry and with a target 3R from the entry.

When liquidity_grab completes (between 08:00 and 11:00 Europe/London time), it buys at market, risking 1% of the balance, with a stop at the low of the sweep step minus 3 points, with a target 2R plus 5 pips from the entry and tagged "breakout"; once open, it moves the stop to breakeven at 1R plus 2 pips, closes 30% at 1.5R, closes 30% at 2.5R, trails the stop by the 14-bar ATR once the trade reaches 2R, exits after 48 bars and exits when the close crosses below the 20-bar EMA of the close.

When the close crosses below the 50-bar EMA of the close (waiting at least 5 bars between actions), it sells at market, risking $200, with a stop at the highest high of the last 10 bars plus 2 pips and with a target at the lowest low of the last 50 bars.

When trend_up at some point within the last 5 bars and the close is above the open for 3 bars in a row (on every bar while it holds), it buys with a limit order at the lowest low of the last 5 bars, with a size of 1 lot and expiring after 10 bars; it also buys with a stop order at the high plus 2 pips, risking 0.5% of the balance, with a stop-loss at the low minus 2 pips, with a target 2R from the entry and kept hidden from the broker until it triggers; it also sells GBPUSD at market, with a size of 0.3 lots.

When today's closed profit or loss is below minus 2% of the account balance or the margin level is below 150%, it closes all trades.

When the script starts, it logs "starting on {market.symbol}".

At every bar close, it logs "bar {bar.index}".

When an order fills, it logs "filled {order.size}".

When a trade closes, it logs "{trade.tag} closed at {trade.r:0.00}R after {long_entry.triggers} triggers".

When the New York session opens, it logs "New York is open".

When a new day begins, it sets triggers to 0.

Whenever the chart is drawn, it goes through each z in levels and sets shape to canvas.path(), moves to a point, draws a line segment, outlines the shape and writes "{z.touched}x" on the chart.

On each bar, it checks whether regime is trending and, if so, sets risk_now to 1%; otherwise, if regime is volatile, sets risk_now to 0.5%; otherwise sets risk_now to 0.25%.

On each bar, it goes through each level in levels and checks whether the close is above level.price and, if so, adds 1 to level.touched.

On each bar, it goes through each i in 0 to 50 and checks whether i is above 10 and, if so, stops the loop; it also moves on to the next item.

On each bar, it checks regime: for trending it logs "trending"; for ranging it logs "ranging".

On each bar, it goes through each trade in open trades tagged "breakout" and checks whether trade.r is at or above 3 and the 14-bar RSI is above 75 and, if so, closes trade (50% of it).

On each bar, it goes through each trade in open trades on the long side and moves the stop to trade.entry_price for trade.

On each bar, it cancels pending orders tagged "grid".

On the chart, it plots the EMA of the close over fast bars as fast_line, plots (the high plus the low) divided by 2, shades between ribbon.fast and ribbon.slow, draws a horizontal line at 70, marks arrow up below the bar when the close crosses above the EMA of the close over fast bars, labels "Entry", draws a line, draws a box, colors the bars, shades the background when regime is volatile, draws a volume profile, draws Fibonacci levels and shows a dashboard.

This description may be incomplete because the script has errors.

Open this page on its own · Markdown

Tick Scalper

Tick Scalper is a strategy that trades XAUUSD on 1-minute bars, checking its rules on every price change. It holds at most 1 open trade.
strategy

inside the bar

tick-scalper.abx
1strategy "Tick Scalper"
2market: XAUUSD
3bars: 1m
4evaluate: tick
5max_open: 1
6
7input max_stretch = 2.0
8
9when crosses_above(close, vwap()) once per bar cooldown 2 bars:
10buy risk: 0.5%, stop: 30 points, target: 1.5R, ghost: true
11
12on tick:
13if not bar.confirmed and close < vwap() - atr(14) * max_stretch:
14close_all side: long
What this script says

Tick Scalper is a strategy that trades XAUUSD on 1-minute bars, checking its rules on every price change. It holds at most 1 open trade.

You can change one input: max_stretch (default 2.0).

When the close crosses above VWAP (at most once per bar and waiting at least 2 bars between actions), it buys at market, risking 0.5% of the balance, with a stop 30 points from the entry, with a target 1.5R from the entry and kept hidden from the broker until it triggers.

On every price change, it checks whether not the bar has closed and the close is below VWAP minus the 14-bar ATR × max_stretch and, if so, closes all long trades.

Open this page on its own · Markdown

Bollinger Mean Reversion

Bollinger Mean Reversion is a strategy that trades EURUSD on 1-hour bars. It holds at most 1 open trade and closes its trade on an opposite signal.
strategy

pending orders

bollinger-mean-reversion.abx
1strategy "Bollinger Mean Reversion"
2market: EURUSD
3bars: 1h
4max_open: 1
5opposite: close
6
7input length = 20
8input width = 2.0
9
10bands = bollinger(close, length, multiplier: width)
11
12when crosses_below(close, bands.lower) and rsi(close, 14) < 30:
13buy limit: bands.lower, risk: 1%, stop: bands.lower - atr(14), target: bands.middle, expires: 5 bars
14
15when crosses_above(close, bands.upper) and rsi(close, 14) > 70:
16sell limit: bands.upper, risk: 1%, stop: bands.upper + atr(14), target: bands.middle, expires: 5 bars
17
18plot bands.upper, color: gray
19plot bands.middle, color: blue
20plot bands.lower, color: gray
What this script says

Bollinger Mean Reversion is a strategy that trades EURUSD on 1-hour bars. It holds at most 1 open trade and closes its trade on an opposite signal.

You can change 2 inputs: length (default 20) and width (default 2.0).

It calculates bands as the Bollinger Bands (source the close, length length, multiplier width).

When the close crosses below bands.lower and the 14-bar RSI is below 30, it buys with a limit order at bands.lower, risking 1% of the balance, with a stop at bands.lower minus the 14-bar ATR, with a target at bands.middle and expiring after 5 bars.

When the close crosses above bands.upper and the 14-bar RSI is above 70, it sells with a limit order at bands.upper, risking 1% of the balance, with a stop at bands.upper plus the 14-bar ATR, with a target at bands.middle and expiring after 5 bars.

On the chart, it plots bands.upper, bands.middle and bands.lower.

Open this page on its own · Markdown

London Open Breakout

London Open Breakout is a strategy that trades GBPUSD on 5-minute bars. It holds at most 1 open trade and trades only during the London session.
strategy

sessions and timepending orders

london-open-breakout.abx
1strategy "London Open Breakout"
2market: GBPUSD
3bars: 5m
4max_open: 1
5trade_only: within sessions london
6
7input range_bars = 12
8input buffer = 2 pips
9
10range_high = highest(high, range_bars)
11range_low = lowest(low, range_bars)
12
13when time_of_day == 08:00 max 1 per day:
14buy stop: range_high + buffer, risk: 0.5%, stop_loss: range_low - buffer, target: 2R, expires: 24 bars, tag: "breakout"
15sell stop: range_low - buffer, risk: 0.5%, stop_loss: range_high + buffer, target: 2R, expires: 24 bars, tag: "breakout"
16
17when time_of_day >= 16:00:
18close_all tag: "breakout"
19cancel orders.pending(tag: "breakout")
20
21plot range_high, color: green, style: step
22plot range_low, color: red, style: step
What this script says

London Open Breakout is a strategy that trades GBPUSD on 5-minute bars. It holds at most 1 open trade and trades only during the London session.

You can change 2 inputs: range_bars (default 12) and buffer (default 2 pips).

It calculates range_high as the highest high of the last range_bars bars and range_low as the lowest low of the last range_bars bars.

When the time of day is 08:00 (at most 1 time per day), it buys with a stop order at range_high plus buffer, risking 0.5% of the balance, with a stop-loss at range_low minus buffer, with a target 2R from the entry, expiring after 24 bars and tagged "breakout"; it also sells with a stop order at range_low minus buffer, risking 0.5% of the balance, with a stop-loss at range_high plus buffer, with a target 2R from the entry, expiring after 24 bars and tagged "breakout".

When the time of day is at or above 16:00, it closes all trades tagged "breakout" and cancels pending orders tagged "breakout".

On the chart, it plots range_high and range_low.

Open this page on its own · Markdown

Supertrend Trend Rider

Supertrend Trend Rider is a strategy that trades XAUUSD on 1-hour bars. It takes long trades only, adds up to 2 entries in the same direction and keep
strategy

trade management

supertrend-trend-rider.abx
1strategy "Supertrend Trend Rider"
2market: XAUUSD
3bars: 1h
4direction: long
5pyramiding: 2
6min_distance: 300 points
7
8input atr_length = 10
9input factor = 3.0
10
11trend = supertrend(atr_length, factor)
12
13when trend.direction == 1 and crosses_above(close, ema(close, 21)):
14buy risk: 0.75%, stop: trend.line, target: 4R, tag: "rider":
15breakeven at: 1R, offset: 50 points
16partial 25% at: 2R
17trail by: atr(14) * 2, after: 2R
18exit when: trend.direction == -1
19
20plot trend.line, color: if trend.direction == 1 then green else red, width: 2
What this script says

Supertrend Trend Rider is a strategy that trades XAUUSD on 1-hour bars. It takes long trades only, adds up to 2 entries in the same direction and keeps at least 300 points between entries.

You can change 2 inputs: atr_length (default 10) and factor (default 3.0).

It calculates trend as the Supertrend (length atr_length, multiplier factor).

When trend.direction is 1 and the close crosses above the 21-bar EMA of the close, it buys at market, risking 0.75% of the balance, with a stop at trend.line, with a target 4R from the entry and tagged "rider"; once open, it moves the stop to breakeven at 1R plus 50 points, closes 25% at 2R, trails the stop by 2 × the 14-bar ATR once the trade reaches 2R and exits when trend.direction is -1.

On the chart, it plots trend.line.

Open this page on its own · Markdown

Grid Accumulator

Grid Accumulator is a strategy that trades EURUSD on 15-minute bars. It holds at most 5 open trades, takes long trades only and adds up to 5 entries i
strategy

statepending orders

grid-accumulator.abx
1strategy "Grid Accumulator"
2market: EURUSD
3bars: 15m
4direction: long
5pyramiding: 5
6max_open: 5
7
8input levels = 5
9input spacing = 15 pips
10input grid_size = 0.1 lots
11
12state anchor: price = na
13
14when trades.open(tag: "grid").len == 0 and orders.pending(tag: "grid").len == 0 and close > ema(close, 200):
15anchor = close
16for step in 1..levels:
17buy limit: close - spacing * step, size: grid_size, stop: close - spacing * (levels + 2), target: close + spacing, tag: "grid"
18
19when close < anchor - spacing * (levels + 2):
20close_all tag: "grid"
21cancel orders.pending(tag: "grid")
What this script says

Grid Accumulator is a strategy that trades EURUSD on 15-minute bars. It holds at most 5 open trades, takes long trades only and adds up to 5 entries in the same direction.

You can change 3 inputs: levels (default 5), spacing (default 15 pips) and grid_size (default 0.1 lots).

It remembers anchor from one bar to the next.

When the number of open trades tagged "grid" is 0 and the number of pending orders tagged "grid" is 0 and the close is above the 200-bar EMA of the close, it sets anchor to the close; it also goes through each step in 1 to levels and buys with a limit order at the close minus spacing × step, with a size of grid_size, with a stop at the close minus spacing × (levels plus 2), with a target at the close plus spacing and tagged "grid".

When the close is below anchor minus spacing × (levels plus 2), it closes all trades tagged "grid" and cancels pending orders tagged "grid".

Open this page on its own · Markdown

Quiet Hours Trend

Quiet Hours Trend is a strategy that trades USDJPY on 15-minute bars. It holds at most 2 open trades (1 per side) and never risks more than 2% across
strategy

sessions and time

quiet-hours-trend.abx
1strategy "Quiet Hours Trend"
2market: USDJPY
3bars: 15m
4max_open: 2
5max_open_per_side: 1
6max_total_risk: 2%
7
8input risk = 0.5%
9
10fast_line = ema(close, 9)
11slow_line = ema(close, 34)
12
13when crosses_above(fast_line, slow_line) from 01:00 to 11:00 UTC skip first 1 max 3 per session cooldown 30m:
14buy risk: risk, stop: 20 pips, target: 1.8R
15
16when crosses_below(fast_line, slow_line) from 01:00 to 11:00 UTC skip first 1 max 3 per session cooldown 30m:
17sell risk: risk, stop: 20 pips, target: 1.8R
18
19when hour >= 20:
20close_all
What this script says

Quiet Hours Trend is a strategy that trades USDJPY on 15-minute bars. It holds at most 2 open trades (1 per side) and never risks more than 2% across open trades.

You can change one input: risk (default 0.5%).

It calculates fast_line as the 9-bar EMA of the close and slow_line as the 34-bar EMA of the close.

When fast_line crosses above slow_line (between 01:00 and 11:00 UTC, ignoring the first time, at most 3 times per session and waiting at least 30 minutes between actions), it buys at market, risking risk of the balance, with a stop 20 pips from the entry and with a target 1.8R from the entry.

When fast_line crosses below slow_line (between 01:00 and 11:00 UTC, ignoring the first time, at most 3 times per session and waiting at least 30 minutes between actions), it sells at market, risking risk of the balance, with a stop 20 pips from the entry and with a target 1.8R from the entry.

When the hour is at or above 20, it closes all trades.

Open this page on its own · Markdown

Heikin-Ashi Trend

Heikin-Ashi Trend is a strategy that trades BTCUSD on 1-hour Heikin-Ashi bars. It takes long trades only.
strategy

renko, heikin ashi, x-ray

heikin-ashi-trend.abx
1strategy "Heikin-Ashi Trend"
2market: BTCUSD
3bars: heikin_ashi(1h)
4direction: long
5
6input slow = 50
7
8when close > open and close[1] > open[1] and close > ema(close, slow):
9buy risk: 1%, stop: lowest(low, 5), target: 3R
10
11when close < open and close[1] < open[1]:
12close_all
What this script says

Heikin-Ashi Trend is a strategy that trades BTCUSD on 1-hour Heikin-Ashi bars. It takes long trades only.

You can change one input: slow (default 50).

When the close is above the open and the previous bar's close is above the previous bar's open and the close is above the EMA of the close over slow bars, it buys at market, risking 1% of the balance, with a stop at the lowest low of the last 5 bars and with a target 3R from the entry.

When the close is below the open and the previous bar's close is below the previous bar's open, it closes all trades.

Open this page on its own · Markdown

Renko Pullback

Renko Pullback is a strategy that trades US500 on 5-point renko bars. It holds at most 1 open trade.
strategy

sequencerenko, heikin ashi, x-ray

renko-pullback.abx
1strategy "Renko Pullback"
2market: US500
3bars: renko(5)
4max_open: 1
5
6sequence pullback within 12 bars:
7step impulse: close > open and close[1] > open[1] and close[2] > open[2]
8step dip: close < open
9step resume: close > open and close > dip.high
10reset_if: close < impulse.low
11
12when pullback.completed:
13buy risk: 1%, stop: pullback.dip.low - 2 points, target: 2R
What this script says

Renko Pullback is a strategy that trades US500 on 5-point renko bars. It holds at most 1 open trade.

pullback completes when these steps happen in order within 12 bars: impulse, when the close is above the open and the previous bar's close is above the previous bar's open and the close 2 bars ago is above the open 2 bars ago; then dip, when the close is below the open; then resume, when the close is above the open and the close is above dip.high. It starts over if the close is below impulse.low.

When pullback completes, it buys at market, risking 1% of the balance, with a stop at the low of the dip step minus 2 points and with a target 2R from the entry.

Open this page on its own · Markdown

Momentum Rotation

Momentum Rotation is a strategy that trades EURUSD, GBPUSD, USDJPY and AUDUSD on 4-hour bars. It holds at most 1 open trade.
strategy

several markets

momentum-rotation.abx
1strategy "Momentum Rotation"
2markets: EURUSD, GBPUSD, USDJPY, AUDUSD
3bars: 4h
4max_open: 1
5
6input lookback = 30
7input threshold = 2%
8
9when bar.confirmed and trades.open(tag: "rotation").len == 0:
10for s in [EURUSD, GBPUSD, USDJPY, AUDUSD]:
11if roc(close_of(s), lookback) > threshold:
12buy market: s, risk: 0.5%, stop: 30 pips, target: 2R, tag: "rotation"
13break
14
15when trades.open(tag: "rotation").len > 0 and roc(close, lookback) < 0:
16close_all tag: "rotation"
What this script says

Momentum Rotation is a strategy that trades EURUSD, GBPUSD, USDJPY and AUDUSD on 4-hour bars. It holds at most 1 open trade.

You can change 2 inputs: lookback (default 30) and threshold (default 2%).

When the bar has closed and the number of open trades tagged "rotation" is 0, it goes through each s in EURUSD, GBPUSD, USDJPY and AUDUSD and checks whether the rate of change of the close of s over lookback bars is above threshold and, if so, buys s at market, risking 0.5% of the balance, with a stop 30 pips from the entry, with a target 2R from the entry and tagged "rotation"; it also stops the loop.

When the number of open trades tagged "rotation" is above 0 and the rate of change over lookback bars is below 0, it closes all trades tagged "rotation".

Open this page on its own · Markdown

Kelly Sized Breakout

Kelly Sized Breakout is a strategy that trades XAUUSD on 30-minute bars. It holds at most 1 open trade.
strategy

uses a library or indicatoraccount and history

kelly-sized-breakout.abx
1strategy "Kelly Sized Breakout"
2market: XAUUSD
3bars: 30m
4max_open: 1
5
6use library "Quant Toolkit" v2 as qt
7
8input max_risk = 2%
9
10stats = history.last(90d)
11edge = qt.kelly_fraction(stats.win_rate / 100%, 2.0)
12risk_now = clamp(edge * 50%, 0.25%, max_risk)
13breakout = crosses_above(close, highest(high, 20)[1])
14
15when breakout and stats.count >= 20:
16buy risk: risk_now, stop: atr(14) * 1.5, target: 2R
17
18when breakout and stats.count < 20:
19buy risk: 0.25%, stop: atr(14) * 1.5, target: 2R
What this script says

Kelly Sized Breakout is a strategy that trades XAUUSD on 30-minute bars. It holds at most 1 open trade.

It uses the library "Quant Toolkit" (version 2) as qt.

You can change one input: max_risk (default 2%).

It calculates stats as closed-trade results over the last 90 days, edge as qt.kelly_fraction(stats.win_rate / 100%, 2.0), risk_now as edge × 50% kept between 0.25% and max_risk and breakout as whether the close crosses above the previous bar's highest high of the last 20 bars.

When breakout and stats.count is at or above 20, it buys at market, risking risk_now of the balance, with a stop 1.5 × the 14-bar ATR from the entry and with a target 2R from the entry.

When breakout and stats.count is below 20, it buys at market, risking 0.25% of the balance, with a stop 1.5 × the 14-bar ATR from the entry and with a target 2R from the entry.

This description may be incomplete because the script has errors.

Open this page on its own · Markdown

Candle Reversal

Candle Reversal is a strategy that trades EURUSD on 1-hour bars. It holds at most 1 open trade.
strategy

confirmations

candle-reversal.abx
1strategy "Candle Reversal"
2market: EURUSD
3bars: 1h
4max_open: 1
5
6confirmations reversal_long:
7pattern: hammer() or engulfing(direction: up) or pin_bar()
8oversold: rsi(close, 14) < 35
9support: low <= lowest(low, 50)[1] + atr(14) * 0.5
10require: at least 2
11
12when reversal_long.passed:
13buy risk: 1%, stop: low - atr(14) * 0.5, target: 2.5R
What this script says

Candle Reversal is a strategy that trades EURUSD on 1-hour bars. It holds at most 1 open trade.

reversal_long passes when at least 2 of these 3 conditions are true: pattern (a hammer pattern or a bullish engulfing pattern or a pin bar pattern); oversold (the 14-bar RSI is below 35); support (the low is at or below the previous bar's lowest low of the last 50 bars plus 0.5 × the 14-bar ATR).

When reversal_long passes, it buys at market, risking 1% of the balance, with a stop at the low minus 0.5 × the 14-bar ATR and with a target 2.5R from the entry.

Open this page on its own · Markdown

Squeeze Breakout

Squeeze Breakout is a strategy that trades NAS100 on 15-minute bars. It holds at most 1 open trade and waits 200 bars before trading.
strategy

trade management

squeeze-breakout.abx
1strategy "Squeeze Breakout"
2market: NAS100
3bars: 15m
4max_open: 1
5warmup: 200
6
7bb = bollinger(close, 20, multiplier: 2.0)
8kc = keltner(close, 20, multiplier: 1.5)
9squeeze_on = bb.upper < kc.upper and bb.lower > kc.lower
10released = ends(squeeze_on)
11momentum_up = linreg_slope(close, 20) > 0
12
13when released and momentum_up and close > kc.upper:
14buy risk: 1%, stop: kc.middle, target: 2R:
15trail by: atr(14) * 2, after: 1R
16
17when released and not momentum_up and close < kc.lower:
18sell risk: 1%, stop: kc.middle, target: 2R:
19trail by: atr(14) * 2, after: 1R
20
21background orange.fade(90), when: squeeze_on
What this script says

Squeeze Breakout is a strategy that trades NAS100 on 15-minute bars. It holds at most 1 open trade and waits 200 bars before trading.

It calculates bb as the Bollinger Bands (source the close, length 20, multiplier 2.0), kc as the Keltner Channels (source the close, length 20, multiplier 1.5), squeeze_on as whether bb.upper is below kc.upper and bb.lower is above kc.lower, released as whether squeeze_on stops being true and momentum_up as whether the linreg slope (source the close, length 20) is above 0.

When released and momentum_up and the close is above kc.upper, it buys at market, risking 1% of the balance, with a stop at kc.middle and with a target 2R from the entry; once open, it trails the stop by 2 × the 14-bar ATR once the trade reaches 1R.

When released and not momentum_up and the close is below kc.lower, it sells at market, risking 1% of the balance, with a stop at kc.middle and with a target 2R from the entry; once open, it trails the stop by 2 × the 14-bar ATR once the trade reaches 1R.

On the chart, it shades the background when squeeze_on.

Open this page on its own · Markdown

DMI Trend Filter

DMI Trend Filter is a strategy that trades EURJPY on 1-hour bars. It holds at most 1 open trade and reverses on an opposite signal.
strategy

core language

dmi-trend-filter.abx
1strategy "DMI Trend Filter"
2market: EURJPY
3bars: 1h
4max_open: 1
5opposite: reverse
6
7input adx_floor = 25
8
9d = dmi(14)
10trending = d.adx > adx_floor
11
12when trending and crosses_above(d.plus, d.minus):
13buy risk: 1%, stop: psar(), target: 3R
14
15when trending and crosses_above(d.minus, d.plus):
16sell risk: 1%, stop: psar(), target: 3R
17
18plot psar(), style: circles, color: yellow
What this script says

DMI Trend Filter is a strategy that trades EURJPY on 1-hour bars. It holds at most 1 open trade and reverses on an opposite signal.

You can change one input: adx_floor (default 25).

It calculates d as the directional movement (length 14) and trending as whether d.adx is above adx_floor.

When trending and d.plus crosses above d.minus, it buys at market, risking 1% of the balance, with a stop at the parabolic SAR and with a target 3R from the entry.

When trending and d.minus crosses above d.plus, it sells at market, risking 1% of the balance, with a stop at the parabolic SAR and with a target 3R from the entry.

On the chart, it plots the parabolic SAR.

Open this page on its own · Markdown

Turtle Channels

Turtle Channels is a strategy that trades XAUUSD on daily bars. It adds up to 4 entries in the same direction, keeps at least 500 points between entri
strategy

core language

turtle-channels.abx
1strategy "Turtle Channels"
2market: XAUUSD
3bars: 1d
4pyramiding: 4
5min_distance: 500 points
6max_drawdown: 20%
7
8input entry_length = 20
9input exit_length = 10
10input unit_risk = 0.5%
11
12entry_channel = donchian(entry_length)
13exit_channel = donchian(exit_length)
14
15when crosses_above(close, entry_channel.upper[1]):
16buy risk: unit_risk, stop: atr(20) * 2, tag: "turtle"
17
18when crosses_below(close, exit_channel.lower[1]):
19close_all side: long, tag: "turtle"
20
21plot entry_channel.upper, color: green
22plot exit_channel.lower, color: red
What this script says

Turtle Channels is a strategy that trades XAUUSD on daily bars. It adds up to 4 entries in the same direction, keeps at least 500 points between entries and stops trading after a 20% drawdown.

You can change 3 inputs: entry_length (default 20), exit_length (default 10) and unit_risk (default 0.5%).

It calculates entry_channel as the Donchian Channels (length entry_length) and exit_channel as the Donchian Channels (length exit_length).

When the close crosses above the previous bar's entry_channel.upper, it buys at market, risking unit_risk of the balance, with a stop 2 × the 20-bar ATR from the entry and tagged "turtle".

When the close crosses below the previous bar's exit_channel.lower, it closes all long trades tagged "turtle".

On the chart, it plots entry_channel.upper and exit_channel.lower.

Open this page on its own · Markdown

Smart Money Pullback

Smart Money Pullback is a strategy that trades GBPJPY on 15-minute bars. It holds at most 1 open trade and trades only during the London and New York
strategy

confirmationstrade managementsmart moneysessions and time

smart-money-pullback.abx
1strategy "Smart Money Pullback"
2market: GBPJPY
3bars: 15m
4max_open: 1
5trade_only: within sessions london, new_york
6
7pd = premium_discount(80)
8entry_zone = optimal_trade_entry(swing_length: 5)
9
10confirmations smc_long:
11choch: was(change_of_character(direction: up), within: 20 bars)
12swept: was(liquidity_sweeps(30), within: 10 bars)
13in_discount: close < pd.equilibrium
14at_entry_zone: low <= entry_zone.top and close >= entry_zone.bottom
15require: all
16
17when smc_long.passed cooldown 10 bars:
18buy risk: 0.75%, stop: entry_zone.bottom - atr(14) * 0.25, target: pd.premium.bottom:
19breakeven at: 1.5R
20
21box id: "premium", from: (bar.index - 80, pd.premium.top), to: (bar.index, pd.premium.bottom), color: red.fade(90)
22box id: "discount", from: (bar.index - 80, pd.discount.top), to: (bar.index, pd.discount.bottom), color: green.fade(90)
What this script says

Smart Money Pullback is a strategy that trades GBPJPY on 15-minute bars. It holds at most 1 open trade and trades only during the London and New York sessions.

It calculates pd as the premium and discount zones (length 80) and entry_zone as the optimal trade entry zone (swing length 5).

smc_long passes when all of these 4 conditions are true: choch (the change of character (direction up) at some point within the last 20 bars); swept (the liquidity sweeps (length 30) at some point within the last 10 bars); in_discount (the close is below pd.equilibrium); at_entry_zone (the low is at or below entry_zone.top and the close is at or above entry_zone.bottom).

When smc_long passes (waiting at least 10 bars between actions), it buys at market, risking 0.75% of the balance, with a stop at entry_zone.bottom minus 0.25 × the 14-bar ATR and with a target at pd.premium.bottom; once open, it moves the stop to breakeven at 1.5R.

On the chart, it draws a box and draws a box.

Open this page on its own · Markdown

Regression Spread

Regression Spread is a strategy that trades AUDUSD and NZDUSD on 1-hour bars. It holds at most 2 open trades.
strategy

several marketsstatistics and matrices

regression-spread.abx
1strategy "Regression Spread"
2markets: AUDUSD, NZDUSD
3bars: 1h
4max_open: 2
5
6input lookback = 250
7input entry_z = 2.2
8
9aud = bars(AUDUSD)
10nzd = bars(NZDUSD)
11model = ols(aud.close, [nzd.close], lookback)
12z = zscore(model.residual, lookback)
13fit_ok = model.r_squared > 0.6
14flat = trades.open(tag: "spread").len == 0
15
16when fit_ok and z > entry_z and flat:
17sell market: AUDUSD, risk: 0.5%, stop: atr(14, on: aud) * 3, tag: "spread"
18buy market: NZDUSD, risk: 0.5%, stop: atr(14, on: nzd) * 3, tag: "spread"
19
20when fit_ok and z < -entry_z and flat:
21buy market: AUDUSD, risk: 0.5%, stop: atr(14, on: aud) * 3, tag: "spread"
22sell market: NZDUSD, risk: 0.5%, stop: atr(14, on: nzd) * 3, tag: "spread"
23
24when abs(z) < 0.25 or not fit_ok:
25close_all tag: "spread"
What this script says

Regression Spread is a strategy that trades AUDUSD and NZDUSD on 1-hour bars. It holds at most 2 open trades.

You can change 2 inputs: lookback (default 250) and entry_z (default 2.2).

It calculates aud as AUDUSD bars, nzd as NZDUSD bars, model as the ols (target aud.close, factors nzd.close, length lookback), z as the z-score of model.residual over lookback bars, fit_ok as whether model.r_squared is above 0.6 and flat as whether the number of open trades tagged "spread" is 0.

When fit_ok and z is above entry_z and flat, it sells AUDUSD at market, risking 0.5% of the balance, with a stop 3 × the 14-bar ATR of aud from the entry and tagged "spread"; it also buys NZDUSD at market, risking 0.5% of the balance, with a stop 3 × the 14-bar ATR of nzd from the entry and tagged "spread".

When fit_ok and z is below -entry_z and flat, it buys AUDUSD at market, risking 0.5% of the balance, with a stop 3 × the 14-bar ATR of aud from the entry and tagged "spread"; it also sells NZDUSD at market, risking 0.5% of the balance, with a stop 3 × the 14-bar ATR of nzd from the entry and tagged "spread".

When the absolute value of z is below 0.25 or not fit_ok, it closes all trades tagged "spread".

Open this page on its own · Markdown

Coverage-Aware Scalper

Coverage-Aware Scalper is a strategy that trades EURUSD on 10-tick range bars. It holds at most 1 open trade.
strategy

renko, heikin ashi, x-ray

coverage-aware-scalper.abx
1strategy "Coverage-Aware Scalper"
2market: EURUSD
3bars: range(10)
4max_open: 1
5
6coverage = data.coverage(EURUSD, bars: range(10))
7enough_history = coverage.exact and coverage.bars >= 5000
8
9when enough_history and crosses_above(close, ema(close, 34)):
10buy risk: 0.5%, stop: 8 pips, target: 1.5R
11
12when enough_history and crosses_below(close, ema(close, 34)):
13sell risk: 0.5%, stop: 8 pips, target: 1.5R
14
15on start:
16log "Data from {coverage.from} to {coverage.to}, {coverage.bars} bars from {coverage.source}"
What this script says

Coverage-Aware Scalper is a strategy that trades EURUSD on 10-tick range bars. It holds at most 1 open trade.

It calculates coverage as the data.coverage (symbol EURUSD, bars the range (size 10)) and enough_history as whether coverage.exact and coverage.bars is at or above 5000.

When enough_history and the close crosses above the 34-bar EMA of the close, it buys at market, risking 0.5% of the balance, with a stop 8 pips from the entry and with a target 1.5R from the entry.

When enough_history and the close crosses below the 34-bar EMA of the close, it sells at market, risking 0.5% of the balance, with a stop 8 pips from the entry and with a target 1.5R from the entry.

When the script starts, it logs "Data from {coverage.from} to {coverage.to}, {coverage.bars} bars from {coverage.source}".

Open this page on its own · Markdown

Performance Throttle

Performance Throttle is a strategy that trades EURUSD on 30-minute bars. It holds at most 1 open trade and stops for the day after losing $500.
strategy

account and history

performance-throttle.abx
1strategy "Performance Throttle"
2market: EURUSD
3bars: 30m
4max_open: 1
5max_daily_loss: $500
6
7input base_risk = 1%
8
9week = history.this_week
10recent_r = trades.closed(tag: "trend").keep_last(10).map(t => t.r).sum()
11risk_scale = if week.profit_factor < 1 or recent_r < -3 then 0.5 else 1.0
12
13when crosses_above(ema(close, 20), ema(close, 50)):
14buy risk: base_risk * risk_scale, stop: 25 pips, target: 2R, tag: "trend"
15
16on exit(trade):
17if trade.reason == "stop" and trade.r <= -1:
18log "Stopped out; recent R total is {recent_r:0.0}"
What this script says

Performance Throttle is a strategy that trades EURUSD on 30-minute bars. It holds at most 1 open trade and stops for the day after losing $500.

You can change one input: base_risk (default 1%).

It calculates week as history.this_week, recent_r as trades.closed(tag: "trend").keep_last(10).map(t => t.r).sum() and risk_scale as 0.5 when week.profit_factor is below 1 or recent_r is below -3, otherwise 1.0.

When the 20-bar EMA of the close crosses above the 50-bar EMA of the close, it buys at market, risking base_risk × risk_scale of the balance, with a stop 25 pips from the entry, with a target 2R from the entry and tagged "trend".

When a trade closes, it checks whether trade.reason is "stop" and trade.r is at or below -1 and, if so, logs "Stopped out; recent R total is {recent_r:0.0}".

Open this page on its own · Markdown

Hedged Breakout

Hedged Breakout is a strategy that trades EURUSD on 1-hour bars. It holds at most 2 open trades (1 per side) and hedges on an opposite signal.
strategy

core language

hedged-breakout.abx
1strategy "Hedged Breakout"
2market: EURUSD
3bars: 1h
4opposite: hedge
5max_open: 2
6max_open_per_side: 1
7
8when crosses_above(close, highest(high, 24)[1]):
9buy risk: 0.5%, stop: 40 pips, target: 80 pips, tag: "up"
10
11when crosses_below(close, lowest(low, 24)[1]):
12sell risk: 0.5%, stop: 40 pips, target: 80 pips, tag: "down"
13
14for trade in trades.open():
15if trade.bars_open >= 48:
16close trade
What this script says

Hedged Breakout is a strategy that trades EURUSD on 1-hour bars. It holds at most 2 open trades (1 per side) and hedges on an opposite signal.

When the close crosses above the previous bar's highest high of the last 24 bars, it buys at market, risking 0.5% of the balance, with a stop 40 pips from the entry, with a target 80 pips from the entry and tagged "up".

When the close crosses below the previous bar's lowest low of the last 24 bars, it sells at market, risking 0.5% of the balance, with a stop 40 pips from the entry, with a target 80 pips from the entry and tagged "down".

On each bar, it goes through each trade in open trades and checks whether trade.bars_open is at or above 48 and, if so, closes trade.

Open this page on its own · Markdown

Active Trade Manager

Active Trade Manager is a strategy that trades XAUUSD on 5-minute bars. It holds at most 1 open trade.
strategy

core language

active-trade-manager.abx
1strategy "Active Trade Manager"
2market: XAUUSD
3bars: 5m
4max_open: 1
5
6when crosses_above(close, vwap()) and rsi(close, 7) > 55:
7buy risk: 1%, stop: 2 * atr(14), target: 3R, tag: "managed"
8
9for trade in trades.open(tag: "managed"):
10if trade.r >= 1 and trade.stop < trade.entry_price:
11modify trade, stop: trade.entry_price
12elif trade.r >= 2:
13close trade, size: 50%
14modify trade, target: trade.entry_price + atr(14) * 6
What this script says

Active Trade Manager is a strategy that trades XAUUSD on 5-minute bars. It holds at most 1 open trade.

When the close crosses above VWAP and the 7-bar RSI is above 55, it buys at market, risking 1% of the balance, with a stop 2 × the 14-bar ATR from the entry, with a target 3R from the entry and tagged "managed".

On each bar, it goes through each trade in open trades tagged "managed" and checks whether trade.r is at or above 1 and trade.stop is below trade.entry_price and, if so, moves the stop to trade.entry_price for trade; otherwise, if trade.r is at or above 2, closes trade (50% of it) and moves the target to trade.entry_price plus 6 × the 14-bar ATR for trade.

Open this page on its own · Markdown

Pyramid Momentum

Pyramid Momentum is a strategy that trades NAS100 on 1-hour bars. It takes long trades only, adds up to 3 entries in the same direction, keeps at leas
strategy

state

pyramid-momentum.abx
1strategy "Pyramid Momentum"
2market: NAS100
3bars: 1h
4direction: long
5pyramiding: 3
6min_distance: 100 points
7max_total_risk: 3%
8
9state adds = 0
10
11when crosses_above(close, ema(close, 50)) and trades.open().len == 0:
12buy risk: 1%, stop: 3 * atr(14), tag: "core"
13adds = 0
14
15when trades.open().len > 0 and adds < 2 and close > trades.last().entry_price + 2 * atr(14):
16buy risk: 0.5%, stop: 3 * atr(14), tag: "add"
17adds += 1
18
19when crosses_below(close, ema(close, 50)):
20close_all
What this script says

Pyramid Momentum is a strategy that trades NAS100 on 1-hour bars. It takes long trades only, adds up to 3 entries in the same direction, keeps at least 100 points between entries and never risks more than 3% across open trades.

It remembers adds from one bar to the next.

When the close crosses above the 50-bar EMA of the close and the number of open trades is 0, it buys at market, risking 1% of the balance, with a stop 3 × the 14-bar ATR from the entry and tagged "core"; it also sets adds to 0.

When the number of open trades is above 0 and adds is below 2 and the close is above trades.last().entry_price plus 2 × the 14-bar ATR, it buys at market, risking 0.5% of the balance, with a stop 3 × the 14-bar ATR from the entry and tagged "add"; it also adds 1 to adds.

When the close crosses below the 50-bar EMA of the close, it closes all trades.

Open this page on its own · Markdown

Hurst Regime Switch

Hurst Regime Switch is a strategy that trades EURUSD on 4-hour bars. It holds at most 1 open trade.
strategy

statistics and matrices

hurst-regime-switch.abx
1strategy "Hurst Regime Switch"
2market: EURUSD
3bars: 4h
4max_open: 1
5
6input window = 200
7
8h = hurst(close, window)
9trending = h > 0.55
10mean_reverting = h < 0.45
11z = zscore(close, 50)
12
13when trending and crosses_above(close, kama(close, 20)):
14buy risk: 1%, stop: 2 * atr(14), target: 3R, tag: "trend"
15
16when mean_reverting and z < -2:
17buy risk: 0.5%, stop: 1.5 * atr(14), target: mean(close, 50), tag: "revert"
18
19when mean_reverting and z > 2:
20sell risk: 0.5%, stop: 1.5 * atr(14), target: mean(close, 50), tag: "revert"
What this script says

Hurst Regime Switch is a strategy that trades EURUSD on 4-hour bars. It holds at most 1 open trade.

You can change one input: window (default 200).

It calculates h as the hurst (source the close, length window), trending as whether h is above 0.55, mean_reverting as whether h is below 0.45 and z as the 50-bar z-score of the close.

When trending and the close crosses above the 20-bar KAMA of the close, it buys at market, risking 1% of the balance, with a stop 2 × the 14-bar ATR from the entry, with a target 3R from the entry and tagged "trend".

When mean_reverting and z is below -2, it buys at market, risking 0.5% of the balance, with a stop 1.5 × the 14-bar ATR from the entry, with a target at the 50-bar average of the close and tagged "revert".

When mean_reverting and z is above 2, it sells at market, risking 0.5% of the balance, with a stop 1.5 × the 14-bar ATR from the entry, with a target at the 50-bar average of the close and tagged "revert".

Open this page on its own · Markdown

Aroon Vortex Confirmation

Aroon Vortex Confirmation is a strategy that trades GBPUSD on 30-minute bars. It holds at most 1 open trade.
strategy

confirmations

aroon-vortex-confirmation.abx
1strategy "Aroon Vortex Confirmation"
2market: GBPUSD
3bars: 30m
4max_open: 1
5
6confirmations bull:
7aroon_up: aroon(25).up > 70
8vortex_up: vortex(14).plus > vortex(14).minus
9cmf_positive: cmf(20) > 0
10choppiness_low: choppiness(14) < 50
11require: at least 3
12
13when bull.passed and not bull.passed[1]:
14buy risk: 1%, stop: swing_low(5, 5), target: 2R
What this script says

Aroon Vortex Confirmation is a strategy that trades GBPUSD on 30-minute bars. It holds at most 1 open trade.

bull passes when at least 3 of these 4 conditions are true: aroon_up (the up of the Aroon (length 25) is above 70); vortex_up (the plus of the Vortex (length 14) is above the minus of the Vortex (length 14)); cmf_positive (the Chaikin money flow (length 20) is above 0); choppiness_low (the choppiness index (length 14) is below 50).

When bull passes and not the previous bar's bull passes, it buys at market, risking 1% of the balance, with a stop at the last swing low (left 5, right 5) and with a target 2R from the entry.

Open this page on its own · Markdown

ALMA Envelope Reversion

ALMA Envelope Reversion is a strategy that trades USDCAD on 15-minute bars. It holds at most 1 open trade.
strategy

pending orders

alma-envelope-reversion.abx
1strategy "ALMA Envelope Reversion"
2market: USDCAD
3bars: 15m
4max_open: 1
5
6input envelope_width = 0.4%
7
8env = envelope(alma(close, 21), 21, percent: envelope_width)
9
10when crosses_below(close, env.lower) and cci(hlc3, 20) < -150:
11buy limit: env.lower, risk: 0.5%, stop: env.lower - 1.5 * atr(14), target: env.middle, expires: 4 bars
12
13when crosses_above(close, env.upper) and cci(hlc3, 20) > 150:
14sell limit: env.upper, risk: 0.5%, stop: env.upper + 1.5 * atr(14), target: env.middle, expires: 4 bars
15
16channel upper: env.upper, lower: env.lower
What this script says

ALMA Envelope Reversion is a strategy that trades USDCAD on 15-minute bars. It holds at most 1 open trade.

You can change one input: envelope_width (default 0.4%).

It calculates env as the moving average envelope (source the 21-bar ALMA of the close, length 21, percent envelope_width).

When the close crosses below env.lower and the 20-bar CCI of the typical price is below -150, it buys with a limit order at env.lower, risking 0.5% of the balance, with a stop at env.lower minus 1.5 × the 14-bar ATR, with a target at env.middle and expiring after 4 bars.

When the close crosses above env.upper and the 20-bar CCI of the typical price is above 150, it sells with a limit order at env.upper, risking 0.5% of the balance, with a stop at env.upper plus 1.5 × the 14-bar ATR, with a target at env.middle and expiring after 4 bars.

On the chart, it draws a channel.

Open this page on its own · Markdown

Awesome Oscillator Saucer

Awesome Oscillator Saucer is a strategy that trades EURGBP on 1-hour bars. It holds at most 1 open trade.
strategy

sequence

awesome-oscillator-saucer.abx
1strategy "Awesome Oscillator Saucer"
2market: EURGBP
3bars: 1h
4max_open: 1
5
6ao = awesome_osc()
7
8sequence saucer within 5 bars:
9step first_red: ao > 0 and ao < ao[1]
10step second_red: ao > 0 and ao < ao[1]
11step green_bar: ao > 0 and ao > ao[1]
12reset_if: ao < 0
13
14when saucer.completed:
15buy risk: 0.75%, stop: saucer.first_red.low, target: 2R
What this script says

Awesome Oscillator Saucer is a strategy that trades EURGBP on 1-hour bars. It holds at most 1 open trade.

It calculates ao as the awesome oscillator.

saucer completes when these steps happen in order within 5 bars: first_red, when ao is above 0 and ao is below the previous bar's ao; then second_red, when ao is above 0 and ao is below the previous bar's ao; then green_bar, when ao is above 0 and ao is above the previous bar's ao. It starts over if ao is below 0.

When saucer completes, it buys at market, risking 0.75% of the balance, with a stop at the low of the first_red step and with a target 2R from the entry.

Open this page on its own · Markdown

State Machine Momentum

State Machine Momentum is a strategy that trades EURUSD on 15-minute bars. It holds at most 1 open trade and stops for the day after losing 2%.
strategy

tables and dashboardsstatefunctions and types

state-machine-momentum.abx
1strategy "State Machine Momentum"
2market: EURUSD
3bars: 15m
4max_open: 1
5max_daily_loss: 2%
6
7enum Phase: waiting, armed, in_trade, cooling
8
9state phase = Phase.waiting
10state armed_at = 0
11state entries = 0
12state exit_prices: map<string, price> = []
13
14action fn enter(reason: string) -> bool:
15buy risk: 0.5%, stop: 1.5 * atr(14), target: 2R, tag: reason
16return true
17
18match phase:
19Phase.waiting:
20if rsi(close, 14) < 35:
21phase = Phase.armed
22armed_at = bar.index
23Phase.armed:
24if crosses_above(rsi(close, 14), 40):
25phase = Phase.in_trade
26elif bar.index - armed_at > 20:
27phase = Phase.waiting
28Phase.in_trade:
29if trades.open().len == 0 and bar.index - armed_at > 1:
30phase = Phase.cooling
31armed_at = bar.index
32Phase.cooling:
33if bar.index - armed_at > 10:
34phase = Phase.waiting
35
36when starts(phase == Phase.in_trade):
37enter("state machine")
38entries += 1
39
40on exit(trade):
41exit_prices.set(trade.tag, trade.exit_price)
42
43dashboard position: top_left, rows: [["Phase", "{phase}"], ["Entries", "{entries}"]]
What this script says

State Machine Momentum is a strategy that trades EURUSD on 15-minute bars. It holds at most 1 open trade and stops for the day after losing 2%.

It defines the action enter(reason), which returns true or false.

It remembers phase, armed_at, entries and exit_prices from one bar to the next.

When phase is in trade becomes true, it runs enter and adds 1 to entries.

When a trade closes, it works out exit_prices.set(trade.tag, trade.exit_price).

On each bar, it checks phase: for waiting it checks whether the 14-bar RSI is below 35 and, if so, sets phase to armed and sets armed_at to the bar number; for armed it checks whether the 14-bar RSI crosses above 40 and, if so, sets phase to in trade; otherwise, if the bar number minus armed_at is above 20, sets phase to waiting; for in trade it checks whether the number of open trades is 0 and the bar number minus armed_at is above 1 and, if so, sets phase to cooling and sets armed_at to the bar number; for cooling it checks whether the bar number minus armed_at is above 10 and, if so, sets phase to waiting.

On the chart, it shows a dashboard.

Open this page on its own · Markdown

Trend Ribbon

Trend Ribbon is an indicator drawn over the price chart.
indicator

core language

trend-ribbon.abx
1indicator "Trend Ribbon"
2pane: price
3
4input fast = 20
5input slow = 50
6
7fast_line = ema(close, fast)
8slow_line = ema(close, slow)
9
10export up = fast_line > slow_line
11export strength = (fast_line - slow_line) / atr(14)
12
13plot fast_line as fast, color: if up then green else red
14plot slow_line as slow, color: gray
What this script says

Trend Ribbon is an indicator drawn over the price chart.

You can change 2 inputs: fast (default 20) and slow (default 50).

It calculates fast_line as the EMA of the close over fast bars, slow_line as the EMA of the close over slow bars, up as whether fast_line is above slow_line and strength as (fast_line minus slow_line) divided by the 14-bar ATR. It shares up and strength with scripts that use it.

On the chart, it plots fast_line as fast and plots slow_line as slow.

Open this page on its own · Markdown

Live Order Blocks

Live Order Blocks is an indicator drawn over the price chart.
indicator

statesmart money

live-order-blocks.abx
1indicator "Live Order Blocks"
2pane: price
3
4input keep = 10
5
6state zones: list<Zone> = []
7
8for ob in order_blocks(new_only: true):
9zones.push(ob)
10zones = zones.filter(z => not z.mitigated).keep_last(keep)
11
12for z in zones:
13box id: z.id, from: (z.formed_bar, z.top), to: (bar.index, z.bottom), color: if z.bullish then green.fade(80) else red.fade(80)
What this script says

Live Order Blocks is an indicator drawn over the price chart.

You can change one input: keep (default 10).

It remembers zones from one bar to the next.

It calculates zones as zones.filter(z => not z.mitigated).keep_last(keep).

On each bar, it goes through each ob in the order blocks and adds ob to zones.

On each bar, it goes through each z in zones and draws a box.

Open this page on its own · Markdown

MACD Histogram

MACD Histogram is an indicator drawn in its own pane.
indicator

core language

macd-histogram.abx
1indicator "MACD Histogram"
2pane: new
3
4input fast = 12
5input slow = 26
6input signal_length = 9
7
8m = macd(close, fast, slow, signal_length)
9
10plot m.histogram, style: histogram, color: if m.histogram >= 0 then green.fade(30) else red.fade(30)
11plot m.macd, color: blue
12plot m.signal, color: orange
13hline 0, style: dotted, color: gray
14mark circle, at: below, when: crosses_above(m.macd, m.signal), color: green
What this script says

MACD Histogram is an indicator drawn in its own pane.

You can change 3 inputs: fast (default 12), slow (default 26) and signal_length (default 9).

It calculates m as the MACD (source the close, fast fast, slow slow, signal signal_length).

On the chart, it plots m.histogram, m.macd and m.signal; it also draws a horizontal line at 0; it also marks circle below the bar when m.macd crosses above m.signal.

Open this page on its own · Markdown

Session VWAP and Profile

Session VWAP and Profile is an indicator drawn over the price chart.
indicator

tables and dashboards

session-vwap-and-profile.abx
1indicator "Session VWAP and Profile"
2pane: price
3
4input rows = 24
5input value_area = 70%
6
7session_vwap = vwap(anchor: "session")
8upper_band = session_vwap + stdev(close, 20)
9lower_band = session_vwap - stdev(close, 20)
10
11plot session_vwap as vwap_line, color: purple, width: 2
12plot upper_band, color: purple.fade(60), style: step
13plot lower_band, color: purple.fade(60), style: step
14fill upper_band, lower_band, color: purple.fade(92)
15profile rows: rows, range: session, side: right, value_area: value_area
What this script says

Session VWAP and Profile is an indicator drawn over the price chart.

You can change 2 inputs: rows (default 24) and value_area (default 70%).

It calculates session_vwap as VWAP, upper_band as session_vwap plus the 20-bar standard deviation of the close and lower_band as session_vwap minus the 20-bar standard deviation of the close.

On the chart, it plots session_vwap as vwap_line, plots upper_band and lower_band, shades between upper_band and lower_band and draws a volume profile.

Open this page on its own · Markdown

Fair Value Gaps

Fair Value Gaps is an indicator drawn over the price chart.
indicator

statesmart money

fair-value-gaps.abx
1indicator "Fair Value Gaps"
2pane: price
3
4input keep = 15
5input min_gap = 0.5
6
7state gaps: list<Zone> = []
8
9for gap in fair_value_gaps(min_size: min_gap, new_only: true):
10gaps.push(gap)
11gaps = gaps.filter(g => not g.mitigated).keep_last(keep)
12
13for g in gaps:
14box id: g.id, from: (g.formed_bar, g.top), to: (bar.index, g.bottom), color: if g.bullish then teal.fade(75) else orange.fade(75)
15label if g.bullish then "FVG +" else "FVG -", at: (g.formed_bar, g.mid), color: gray
What this script says

Fair Value Gaps is an indicator drawn over the price chart.

You can change 2 inputs: keep (default 15) and min_gap (default 0.5).

It remembers gaps from one bar to the next.

It calculates gaps as gaps.filter(g => not g.mitigated).keep_last(keep).

On each bar, it goes through each gap in the fair value gaps and adds gap to gaps.

On each bar, it goes through each g in gaps and draws a box and labels if g.bullish then "FVG +" else "FVG -".

Open this page on its own · Markdown

Ichimoku Cloud

Ichimoku Cloud is an indicator drawn over the price chart.
indicator

core language

ichimoku-cloud.abx
1indicator "Ichimoku Cloud"
2pane: price
3
4cloud = ichimoku()
5
6plot cloud.conversion, color: blue
7plot cloud.base, color: red
8plot cloud.span_a, color: green.fade(40)
9plot cloud.span_b, color: red.fade(40)
10fill cloud.span_a, cloud.span_b, color: if cloud.span_a > cloud.span_b then green.fade(85) else red.fade(85)
11plot cloud.lagging, color: gray
What this script says

Ichimoku Cloud is an indicator drawn over the price chart.

It calculates cloud as the Ichimoku cloud.

On the chart, it plots cloud.conversion, cloud.base, cloud.span_a and cloud.span_b; it also shades between cloud.span_a and cloud.span_b; it also plots cloud.lagging.

Open this page on its own · Markdown

Opening Range Dashboard

Opening Range Dashboard is an indicator drawn over the price chart.
indicator

tables and dashboardsstate

opening-range-dashboard.abx
1indicator "Opening Range Dashboard"
2pane: price
3
4input range_start = 09:30
5input range_end = 10:00
6
7state or_high: price = na
8state or_low: price = na
9
10in_range = time_of_day between range_start and range_end
11
12if time_of_day == range_start:
13or_high = high
14or_low = low
15elif in_range:
16or_high = max(or_high, high)
17or_low = min(or_low, low)
18
19background blue.fade(92), when: in_range
20hline or_high, style: dashed, color: green
21hline or_low, style: dashed, color: red
22dashboard position: top_right, rows: [["Range high", "{or_high:0.00}"], ["Range low", "{or_low:0.00}"], ["Width", "{or_high - or_low:0.00}"]]
What this script says

Opening Range Dashboard is an indicator drawn over the price chart.

You can change 2 inputs: range_start (default 09:30) and range_end (default 10:00).

It remembers or_high and or_low from one bar to the next.

It calculates in_range as whether the time of day is between range_start and range_end.

On each bar, it checks whether the time of day is range_start and, if so, sets or_high to the high and sets or_low to the low; otherwise, if in_range, sets or_high to the max (a or_high, b the high); it also sets or_low to the min (a or_low, b the low).

On the chart, it shades the background when in_range, draws a horizontal line at or_high, draws a horizontal line at or_low and shows a dashboard.

Open this page on its own · Markdown

Volatility Regime Canvas

Volatility Regime Canvas is an indicator drawn in its own pane.
indicator

canvasstatefunctions and types

volatility-regime-canvas.abx
1indicator "Volatility Regime Canvas"
2pane: new
3
4enum Regime: calm, normal, stormy
5
6input fast_vol = 20
7input slow_vol = 100
8
9state regime = Regime.normal
10
11ratio = stdev(returns(close), fast_vol) / stdev(returns(close), slow_vol)
12
13if ratio < 0.8:
14regime = Regime.calm
15elif ratio > 1.3:
16regime = Regime.stormy
17else:
18regime = Regime.normal
19
20plot ratio as vol_ratio, color: white
21hline 1, style: dotted, color: gray
22
23on render(canvas):
24tint = if regime == Regime.stormy then red.fade(80) else if regime == Regime.calm then green.fade(80) else gray.fade(90)
25canvas.rect(from: (canvas.visible_from, canvas.price_max), to: (canvas.last_bar, canvas.price_min), fill: tint)
26match regime:
27Regime.calm: canvas.text("calm", at: (canvas.last_bar, canvas.price_max), align: right, color: green)
28Regime.normal: canvas.text("normal", at: (canvas.last_bar, canvas.price_max), align: right)
29Regime.stormy: canvas.text("stormy", at: (canvas.last_bar, canvas.price_max), align: right, color: red)
What this script says

Volatility Regime Canvas is an indicator drawn in its own pane.

You can change 2 inputs: fast_vol (default 20) and slow_vol (default 100).

It remembers regime from one bar to the next.

It calculates ratio as the standard deviation of the returns of the close over fast_vol bars divided by the standard deviation of the returns of the close over slow_vol bars.

Whenever the chart is drawn, it sets tint to red at 80% transparency when regime is stormy, otherwise green at 80% transparency when regime is calm, otherwise gray at 90% transparency; it also draws a rectangle; it also checks regime: for calm it writes "calm" on the chart; for normal it writes "normal" on the chart; for stormy it writes "stormy" on the chart.

On each bar, it checks whether ratio is below 0.8 and, if so, sets regime to calm; otherwise, if ratio is above 1.3, sets regime to stormy; otherwise sets regime to normal.

On the chart, it plots ratio as vol_ratio and draws a horizontal line at 1.

Open this page on its own · Markdown

Support and Resistance

Support and Resistance is an indicator drawn over the price chart.
indicator

core language

support-and-resistance.abx
1indicator "Support and Resistance"
2pane: price
3
4input lookback = 300
5input min_touches = 3
6
7found = support_resistance(lookback, touches: min_touches).filter(l => l.touches >= min_touches)
8strongest = found.sort_by(l => -l.strength)
9
10for level in strongest.keep_last(6):
11line from: (bar.index - 50, level.price), to: (bar.index, level.price), extend: right, color: if level.price > close then red.fade(40) else green.fade(40), width: 2
12label "{level.touches} touches", at: (bar.index, level.price), color: gray
What this script says

Support and Resistance is an indicator drawn over the price chart.

You can change 2 inputs: lookback (default 300) and min_touches (default 3).

It calculates found as support_resistance(lookback, touches: min_touches).filter(l => l.touches >= min_touches) and strongest as found.sort_by(l => -l.strength).

On each bar, it goes through each level in strongest.keep_last(6) and draws a line and labels "{level.touches} touches".

Open this page on its own · Markdown

ZigZag Fibonacci

ZigZag Fibonacci is an indicator drawn over the price chart.
indicator

core language

zigzag-fibonacci.abx
1indicator "ZigZag Fibonacci"
2pane: price
3
4input deviation = 3%
5
6swings = zigzag(deviation: deviation, depth: 12)
7
8if swings.len >= 2:
9last_swing = swings.last()
10previous_swing = swings.get(swings.len - 2)
11fib from: (previous_swing.bar, previous_swing.price), to: (last_swing.bar, last_swing.price), levels: [0.382, 0.5, 0.618, 0.786]
12polyline points: swings.map(s => (s.bar, s.price)), color: gray, width: 1
What this script says

ZigZag Fibonacci is an indicator drawn over the price chart.

You can change one input: deviation (default 3%).

It calculates swings as the zigzag swings (deviation deviation, depth 12).

On each bar, it checks whether the number of swings is at or above 2 and, if so, sets last_swing to swings.last(), sets previous_swing to swings.get(swings.len - 2), draws Fibonacci levels and draws a polyline.

Open this page on its own · Markdown

Portfolio Risk Matrix

Portfolio Risk Matrix is an indicator drawn in its own pane.
indicator

several marketsstatistics and matrices

portfolio-risk-matrix.abx
1indicator "Portfolio Risk Matrix"
2pane: new
3markets: EURUSD, GBPUSD, USDJPY
4
5input lookback = 100
6
7eur = returns(close_of(EURUSD))
8gbp = returns(close_of(GBPUSD))
9jpy = returns(close_of(USDJPY))
10cov = covariance_matrix([eur, gbp, jpy], lookback)
11weights = matrix(3, 1, fill: 0.3333)
12portfolio_variance = multiply(multiply(transpose(weights), cov), weights)
13eur_gbp_corr = correlation(eur, gbp, lookback)
14eur_jpy_corr = correlation(eur, jpy, lookback)
15
16plot eur_gbp_corr as eur_gbp, color: blue
17plot eur_jpy_corr as eur_jpy, color: orange
18hline 0, style: dotted, color: gray
19cells rows: [["Pair", "Correlation"], ["EUR/GBP", "{eur_gbp_corr:0.00}"], ["EUR/JPY", "{eur_jpy_corr:0.00}"]], columns: 2
What this script says

Portfolio Risk Matrix is an indicator drawn in its own pane.

You can change one input: lookback (default 100).

It calculates eur as the returns of the close of EURUSD, gbp as the returns of the close of GBPUSD, jpy as the returns of the close of USDJPY, cov as the covariance matrix (series eur, gbp and jpy, length lookback), weights as the matrix (rows 3, columns 1, fill 0.3333), portfolio_variance as the multiply (a the multiply (a the transpose (m weights), b cov), b weights), eur_gbp_corr as the correlation (a eur, b gbp, length lookback) and eur_jpy_corr as the correlation (a eur, b jpy, length lookback).

On the chart, it plots eur_gbp_corr as eur_gbp, plots eur_jpy_corr as eur_jpy, draws a horizontal line at 0 and draws a cells.

Open this page on its own · Markdown

Volume Heatmap

Volume Heatmap is an indicator drawn over the price chart.
indicator

tables and dashboardsstate

volume-heatmap.abx
1indicator "Volume Heatmap"
2pane: price
3
4input columns = 30
5input rows = 12
6
7state heat: list<Cell> = []
8
9top = highest(high, columns)
10bottom = lowest(low, columns)
11row_height = (top - bottom) / rows
12
13if bar.confirmed:
14for i in 0..rows:
15level = bottom + row_height * i
16heat.push(Cell(bar: bar.index, price: level, value: volume * (1 - abs(close - level) / (top - bottom))))
17heat = heat.keep_last(columns * rows)
18
19heatmap cells: heat, palette: "thermal"
What this script says

Volume Heatmap is an indicator drawn over the price chart.

You can change 2 inputs: columns (default 30) and rows (default 12).

It remembers heat from one bar to the next.

It calculates top as the highest high of the last columns bars, bottom as the lowest low of the last columns bars and row_height as (top minus bottom) divided by rows.

On each bar, it checks whether the bar has closed and, if so, goes through each i in 0 to rows and sets level to bottom plus row_height × i; it also adds Cell(bar: bar.index, price: level, value: volume * (1 - abs(close - level) / (top - bottom))) to heat; it also sets heat to heat.keep_last(columns * rows).

On the chart, it draws a heatmap.

Open this page on its own · Markdown

Gradient RSI Candles

Gradient RSI Candles is an indicator drawn in its own pane.
indicator

core language

gradient-rsi-candles.abx
1indicator "Gradient RSI Candles"
2pane: new
3
4input length = 14
5
6strength = rsi(close, length)
7tint = gradient(strength, low: red, high: green, from: 30, to: 70)
8
9pane "RSI", height: 30%
10candles open: open, high: high, low: low, close: close, color: tint, pane: "RSI"
11plot strength, color: tint, width: 2, pane: "RSI"
12hline 70, style: dashed, color: gray
13hline 30, style: dashed, color: gray
What this script says

Gradient RSI Candles is an indicator drawn in its own pane.

You can change one input: length (default 14).

It calculates strength as the RSI over length bars and tint as the gradient (value strength, low red, high green, from 30, to 70).

On the chart, it draws a pane, draws a candles, plots strength, draws a horizontal line at 70 and draws a horizontal line at 30.

Open this page on its own · Markdown

X-Ray Flow Bands

X-Ray Flow Bands is an indicator drawn over the price chart.
indicator

renko, heikin ashi, x-ray

x-ray-flow-bands.abx
1indicator "X-Ray Flow Bands"
2bars: xray(20)
3
4input band_length = 30
5
6center = hma(close, band_length)
7width = stdev(close, band_length) * 2
8up_band = center + width
9down_band = center - width
10
11channel upper: up_band, lower: down_band, fill: linear_gradient(start: green.fade(80), end: red.fade(80))
12plot center, color: white, width: 2
13mark triangle_up, at: below, when: crosses_above(close, down_band), color: green, size: tiny
14mark triangle_down, at: above, when: crosses_below(close, up_band), color: red, size: tiny
What this script says

X-Ray Flow Bands is an indicator drawn over the price chart.

You can change one input: band_length (default 30).

It calculates center as the HMA of the close over band_length bars, width as 2 × the standard deviation of the close over band_length bars, up_band as center plus width and down_band as center minus width.

On the chart, it draws a channel, plots center, marks triangle up below the bar when the close crosses above down_band and marks triangle down above the bar when the close crosses below up_band.

Open this page on its own · Markdown

Multi-Timeframe Trend Table

Multi-Timeframe Trend Table is an indicator drawn over the price chart.
indicator

other bar sizestables and dashboards

multi-timeframe-trend-table.abx
1indicator "Multi-Timeframe Trend Table"
2pane: price
3
4h1 = bars(bars: 1h)
5h4 = bars(bars: 4h)
6d1 = bars(bars: 1d)
7
8h1_up = h1.close > ema(h1.close, 50)
9h4_up = h4.close > ema(h4.close, 50)
10d1_up = d1.close > ema(d1.close, 50)
11score = (if h1_up then 1 else 0) + (if h4_up then 1 else 0) + (if d1_up then 1 else 0)
12
13table position: bottom_right, rows: [["1h", if h1_up then "up" else "down"], ["4h", if h4_up then "up" else "down"], ["1d", if d1_up then "up" else "down"], ["Score", "{score}/3"]]
14bar_color if score == 3 then green else if score == 0 then red else gray
What this script says

Multi-Timeframe Trend Table is an indicator drawn over the price chart.

It calculates h1 as 1-hour bars, h4 as 4-hour bars, d1 as daily bars, h1_up as whether h1.close is above the 50-bar EMA of h1.close, h4_up as whether h4.close is above the 50-bar EMA of h4.close, d1_up as whether d1.close is above the 50-bar EMA of d1.close and score as 1 when h1_up, otherwise 0 plus 1 when h4_up, otherwise 0 plus 1 when d1_up, otherwise 0.

On the chart, it shows a table and colors the bars.

Open this page on its own · Markdown

Fractal Pitchfork

Fractal Pitchfork is an indicator drawn over the price chart.
indicator

state

fractal-pitchfork.abx
1indicator "Fractal Pitchfork"
2pane: price
3
4state points: list<tuple<int, price>> = []
5
6f = fractals(2)
7
8if f.up:
9points.push((bar.index - 2, high[2]))
10if f.down:
11points.push((bar.index - 2, low[2]))
12points = points.keep_last(3)
13
14if points.len == 3:
15pitchfork points: points
16polygon points: points, fill: blue.fade(90), border: blue
17arrow from: points.get(0), to: points.get(2), color: gray
What this script says

Fractal Pitchfork is an indicator drawn over the price chart.

It remembers points from one bar to the next.

It calculates f as the fractals (periods 2) and points as points.keep_last(3).

On each bar, it checks whether f.up and, if so, adds (bar.index - 2, high[2]) to points.

On each bar, it checks whether f.down and, if so, adds (bar.index - 2, low[2]) to points.

On each bar, it checks whether the number of points is 3 and, if so, draws a pitchfork, draws a polygon and draws an arrow.

Open this page on its own · Markdown

Move Annotations

Move Annotations is an indicator drawn over the price chart.
indicator

core language

move-annotations.abx
1indicator "Move Annotations"
2pane: price
3
4big_move = abs(close - open) > 2 * atr(14)
5gap_up = open > high[1]
6gap_down = open < low[1]
7
8if big_move:
9icon "bolt", at: (bar.index, high), color: yellow
10tooltip "Range {bar.range:0.00} vs ATR {atr(14):0.00}", at: (bar.index, high)
11if gap_up:
12label "Gap up", at: (bar.index, low), color: green
13if gap_down:
14label "Gap down", at: (bar.index, high), color: red
15image "logo.svg", at: (bar.index, close), width: 16
What this script says

Move Annotations is an indicator drawn over the price chart.

It calculates big_move as whether the absolute value of the close minus the open is above 2 × the 14-bar ATR, gap_up as whether the open is above the previous bar's high and gap_down as whether the open is below the previous bar's low.

On each bar, it checks whether big_move and, if so, draws an icon and draws a tooltip.

On each bar, it checks whether gap_up and, if so, labels "Gap up".

On each bar, it checks whether gap_down and, if so, labels "Gap down".

On the chart, it draws an image.

Open this page on its own · Markdown

Momentum Composite

Momentum Composite is an indicator drawn in its own pane.
indicator

core language

momentum-composite.abx
1indicator "Momentum Composite"
2pane: new
3
4input trix_length = 18
5
6trix_line = trix(close, trix_length)
7volume_flow = volume_osc(5, 20)
8mfi_line = mfi(14)
9export composite = (trix_line * 100 + volume_flow / 10 + (mfi_line - 50) / 50) / 3
10export bullish = composite > 0 and composite > composite[1]
11
12plot composite as composite_line, style: columns, color: if bullish then teal else gray
13hline 0, color: gray
What this script says

Momentum Composite is an indicator drawn in its own pane.

You can change one input: trix_length (default 18).

It calculates trix_line as the TRIX (source the close, length trix_length), volume_flow as the volume oscillator (fast 5, slow 20), mfi_line as the money flow index (length 14), composite as (100 × trix_line plus volume_flow divided by 10 plus (mfi_line minus 50) divided by 50) divided by 3 and bullish as whether composite is above 0 and composite is above the previous bar's composite. It shares composite and bullish with scripts that use it.

On the chart, it plots composite as composite_line and draws a horizontal line at 0.

Open this page on its own · Markdown

Daily risk guard

Daily risk guard is an alert that checks every 1 minute, can fire every time its condition is met and waits 4 hours between alerts.
alert

account and history

daily-risk-guard.abx
1alert "Daily risk guard"
2check: every 1m
3repeat: every time
4cooldown: 4h
5
6when history.today.pnl < -(2% of account.balance) or account.margin_level < 150%:
7notify "Daily P&L {history.today.pnl:$0.00}, margin level {account.margin_level:0}%"
What this script says

Daily risk guard is an alert that checks every 1 minute, can fire every time its condition is met and waits 4 hours between alerts.

When today's closed profit or loss is below minus 2% of the account balance or the margin level is below 150%, it sends the notification "Daily P&L {history.today.pnl:$0.00}, margin level {account.margin_level:0}%".

Open this page on its own · Markdown

RSI bullish divergence

RSI bullish divergence is an alert that checks every 15 minutes, fires at most once per bar and shows where it fires on the chart.
alert

core language

rsi-bullish-divergence.abx
1alert "RSI bullish divergence"
2check: every 15m
3repeat: once per bar
4show_on_chart: true
5
6input rsi_length = 14
7input lookback = 30
8
9momentum_now = rsi(close, rsi_length)
10lower_low = low < lowest(low, lookback)[1]
11higher_rsi = momentum_now > lowest(momentum_now, lookback)[1]
12
13when lower_low and higher_rsi and was(momentum_now < 30, within: 5 bars):
14notify "Bullish RSI divergence on {market.symbol}: RSI {momentum_now:0.0}"
What this script says

RSI bullish divergence is an alert that checks every 15 minutes, fires at most once per bar and shows where it fires on the chart.

You can change 2 inputs: rsi_length (default 14) and lookback (default 30).

It calculates momentum_now as the RSI over rsi_length bars, lower_low as whether the low is below the previous bar's lowest low of the last lookback bars and higher_rsi as whether momentum_now is above the previous bar's lowest momentum_now of the last lookback bars.

When lower_low and higher_rsi and momentum_now is below 30 at some point within the last 5 bars, it sends the notification "Bullish RSI divergence on {market.symbol}: RSI {momentum_now:0.0}".

Open this page on its own · Markdown

Margin and exposure

Margin and exposure is an alert that checks every 5 minutes and fires only once.
alert

account and history

margin-and-exposure.abx
1alert "Margin and exposure"
2check: every 5m
3repeat: once
4expires: 30d
5
6when account.free_margin < 20% of account.equity or positions.len >= 8:
7notify "Free margin {account.free_margin:$0} with {positions.len} open positions"
What this script says

Margin and exposure is an alert that checks every 5 minutes and fires only once.

When free margin is below 20% of equity or the number of open positions is at or above 8, it sends the notification "Free margin {account.free_margin:$0} with {positions.len} open positions".

Open this page on its own · Markdown

Stochastic cross in extremes

Stochastic cross in extremes is an alert that checks every 1 hour, can fire every time its condition is met, waits 3 bars between alerts and shows whe
alert

core language

stochastic-cross-in-extremes.abx
1alert "Stochastic cross in extremes"
2check: every 1h
3repeat: every time
4cooldown: 3 bars
5show_on_chart: true
6
7k_line = stoch().k
8d_line = stoch().d
9
10when crosses_above(k_line, d_line) and k_line < 20:
11notify "Stochastic bullish cross at {k_line:0} on {market.symbol}"
12
13when crosses_below(k_line, d_line) and k_line > 80:
14notify "Stochastic bearish cross at {k_line:0} on {market.symbol}"
What this script says

Stochastic cross in extremes is an alert that checks every 1 hour, can fire every time its condition is met, waits 3 bars between alerts and shows where it fires on the chart.

It calculates k_line as the k of the stochastic and d_line as the d of the stochastic.

When k_line crosses above d_line and k_line is below 20, it sends the notification "Stochastic bullish cross at {k_line:0} on {market.symbol}".

When k_line crosses below d_line and k_line is above 80, it sends the notification "Stochastic bearish cross at {k_line:0} on {market.symbol}".

Open this page on its own · Markdown

Intrabar spike

Intrabar spike is an alert that checks every 1 hour and fires at most once per bar.
alert

inside the bar

intrabar-spike.abx
1alert "Intrabar spike"
2check: every 1h
3repeat: once per bar close
4
5inner = intrabar(bars: 1m)
6spike = inner.high.max() - inner.low.min()
7
8when inner.len > 0 and spike > atr(14) * 1.5:
9notify "Minute-level spike of {spike:0.00} inside the hour on {market.symbol}"
What this script says

Intrabar spike is an alert that checks every 1 hour and fires at most once per bar.

It calculates inner as the bars inside this bar (bars 1 minute) and spike as inner.high.max() minus inner.low.min().

When the number of inner is above 0 and spike is above 1.5 × the 14-bar ATR, it sends the notification "Minute-level spike of {spike:0.00} inside the hour on {market.symbol}".

Open this page on its own · Markdown

Tokyo open gap

Tokyo open gap is an alert that checks every 1 minute and can fire every time its condition is met.
alert

state

tokyo-open-gap.abx
1alert "Tokyo open gap"
2check: every 1m
3repeat: every time
4
5state tokyo_open_price: price = na
6
7on session open "tokyo":
8tokyo_open_price = open
9notify "Tokyo session opened at {open:0.000} on {market.symbol}"
10
11when tokyo_open_price > 0 and abs(close - tokyo_open_price) > atr(14) * 3:
12notify "Price moved more than 3 ATR from the Tokyo open"
What this script says

Tokyo open gap is an alert that checks every 1 minute and can fire every time its condition is met.

It remembers tokyo_open_price from one bar to the next.

When the Tokyo session opens, it sets tokyo_open_price to the open and sends the notification "Tokyo session opened at {open:0.000} on {market.symbol}".

When tokyo_open_price is above 0 and the absolute value of the close minus tokyo_open_price is above 3 × the 14-bar ATR, it sends the notification "Price moved more than 3 ATR from the Tokyo open".

Open this page on its own · Markdown

Distribution shift

Distribution shift is an alert that checks every 1 hour and fires at most once per bar.
alert

statistics and matrices

distribution-shift.abx
1alert "Distribution shift"
2check: every 1h
3repeat: once per bar
4warmup: 300
5
6r = returns(close)
7skewness = skew(r, 100)
8tails = kurtosis(r, 100)
9memory = autocorrelation(r, 100, lag: 1)
10
11when abs(skewness) > 1 and tails > 5:
12notify "Fat-tailed, skewed returns: skew {skewness:0.00}, kurtosis {tails:0.0}, lag-1 autocorrelation {memory:0.00}"
What this script says

Distribution shift is an alert that checks every 1 hour and fires at most once per bar.

It calculates r as the returns of the close, skewness as the skew (source r, length 100), tails as the kurtosis (source r, length 100) and memory as the autocorrelation (source r, length 100, lag 1).

When the absolute value of skewness is above 1 and tails is above 5, it sends the notification "Fat-tailed, skewed returns: skew {skewness:0.00}, kurtosis {tails:0.0}, lag-1 autocorrelation {memory:0.00}".

Open this page on its own · Markdown

Ribbon and TSI agreement

Ribbon and TSI agreement is an alert that checks every 15 minutes and fires at most once per bar.
alert

uses a library or indicator

ribbon-and-tsi-agreement.abx
1alert "Ribbon and TSI agreement"
2check: every 15m
3repeat: once per bar
4
5use indicator "Trend Ribbon" v3 as ribbon (fast: 8, slow: 21)
6
7t = tsi(close, long: 25, short: 13, signal: 7)
8p = ppo(close)
9
10when ribbon.up and crosses_above(t.tsi, t.signal) and p.histogram > 0:
11notify "Trend Ribbon up with TSI and PPO momentum on {market.symbol}"
What this script says

Ribbon and TSI agreement is an alert that checks every 15 minutes and fires at most once per bar.

It uses the indicator "Trend Ribbon" (version 3) as ribbon, with fast set to 8 and slow set to 21.

It calculates t as the true strength index (source the close, long 25, short 13, signal 7) and p as the percentage price oscillator (source the close).

When ribbon.up and t.tsi crosses above t.signal and p.histogram is above 0, it sends the notification "Trend Ribbon up with TSI and PPO momentum on {market.symbol}".

This description may be incomplete because the script has errors.

Open this page on its own · Markdown

Quant Toolkit

Quant Toolkit is a library of reusable functions and constants for other scripts.
library

functions and types

quant-toolkit.abx
1library "Quant Toolkit"
2
3const TRADING_DAYS = 252
4
5fn kelly_fraction(win_rate: number, payoff: number) -> number:
6return win_rate - (1 - win_rate) / payoff
7
8fn annualized_volatility(source: series<number> = close, length: int = 20) -> number:
9return stdev(returns(source), length) * sqrt(TRADING_DAYS)
10
11fn position_heat(risks: list<percent>) -> percent:
12total = 0%
13for r in risks:
14total += r
15return total
What this script says

Quant Toolkit is a library of reusable functions and constants for other scripts.

It defines the constant TRADING_DAYS as 252.

It defines kelly_fraction(win_rate, payoff), which returns a number, annualized_volatility(source, length), which returns a number and position_heat(risks), which returns a percentage.

Open this page on its own · Markdown

Risk Parity

Risk Parity is a library of reusable functions and constants for other scripts.
library

functions and types

risk-parity.abx
1library "Risk Parity"
2
3const MAX_WEIGHT = 40%
4
5type Asset:
6symbol: symbol
7volatility: number
8weight: percent = 0%
9
10fn inverse_vol_weights(assets: list<Asset>) -> list<percent>:
11total = 0.0
12for a in assets:
13total += 1 / a.volatility
14weights = assets.map(a => (1 / a.volatility) / total * 100%)
15return weights.map(w => min(w, MAX_WEIGHT))
16
17fn lots_for_weight(balance: money, weight: percent, contract_value: money) -> lots:
18return (weight of balance) / contract_value * 1 lot
What this script says

Risk Parity is a library of reusable functions and constants for other scripts.

It defines the constant MAX_WEIGHT as 40%.

It defines inverse_vol_weights(assets), which returns list<percent> and lots_for_weight(balance, weight, contract_value), which returns a size in lots.

Open this page on its own · Markdown

Ranking Tools

Ranking Tools is a library of reusable functions and constants for other scripts.
library

functions and typesstatistics and matrices

ranking-tools.abx
1library "Ranking Tools"
2
3type Scored:
4symbol: symbol
5score: number
6
7fn top_n(items: list<Scored>, n: int) -> list<Scored>:
8return items.sort_by(item => item.score).keep_last(n)
9
10fn normalize(value: number, low: number, high: number) -> number:
11if high == low:
12return 0
13return clamp((value - low) / (high - low), 0, 1)
14
15fn percentile_band(source: series<number> = close, length: int = 100) -> number:
16return percentile(source, length, percent: 90%) - percentile(source, length, percent: 10%)
What this script says

Ranking Tools is a library of reusable functions and constants for other scripts.

It defines top_n(items, n), which returns list<Scored>, normalize(value, low, high), which returns a number and percentile_band(source, length), which returns a number.

Open this page on its own · Markdown

Importing, Files and Tooling

4 guides · bring scripts in, share them, and the formal grammar

Importing from other languages

Pine Script, MQL4 and MQL5, NinjaScript, EasyLanguage, thinkScript and Python.
3 min

Paste a script from another platform and AlgoBarsX works out the language, parses the source, maps each construct, and compiles the result before calling it done. An import that does not compile says so.

ReadsNotes
Pine ScriptStrategies and indicators.
MQL4 and MQL5Expert advisors. OnTick becomes the script body, and OrderSend becomes an order with its stop and target attached.
NinjaScriptOnBarUpdate carries over. The C# around it comes back as notes.
EasyLanguageTradeStation strategies.
thinkScriptStudies and conditions.
Pythonbacktrader, freqtrade, and plain pandas with pandas-ta or TA-Lib.

Every line comes back with one of three statuses: exact (carried over as is), adapted (changed, with a note saying how), or your call (a decision handed back to you, with the original kept as a comment).

What you paste · Pine Script
//@version=5
strategy("EMA Cross", overlay=true)
fast = input.int(20, "Fast")
slow = input.int(50, "Slow")
if ta.crossover(ta.ema(close, fast), ta.ema(close, slow))
strategy.entry("Long", strategy.long)
if ta.crossunder(ta.ema(close, fast), ta.ema(close, slow))
strategy.close("Long")
What you get back
1strategy "EMA Cross"
2market: EURUSD
3bars: 1h
4
5input fast = 20
6input slow = 50
7
8when crosses_above(ema(close, fast), ema(close, slow)):
9buy size: 1 lot, tag: "Long"
10
11when crosses_below(ema(close, fast), ema(close, slow)):
12close_all tag: "Long"
StatusYour lineWhat happened
Exactstrategy("EMA Cross", overlay=true)strategy() became the script header
Exactfast = input.int(20, "Fast")input() became an input
Exactslow = input.int(50, "Slow")input() became an input
Your callstrategy.entry("Long", strategy.long)strategy.entry() had no size of its own, so it became one lot: set the size or risk you want
Adaptedif ta.crossover(ta.ema(close, fast), ta.ema(close, slow))an if that places orders became a rule
Exactstrategy.close("Long")strategy.close() became close_all
Adaptedif ta.crossunder(ta.ema(close, fast), ta.ema(close, slow))an if that places orders became a rule
Your callstrategy(...)Pine scripts carry no market or bar size, so EURUSD on 1h was filled in: set the ones you want
Always read an import before you run it. Other platforms leave things unsaid that AlgoBarsX makes explicit, such as the market, the bar size and the position size. Those come back as decisions for you. Check the plain-English description against what your original did, and backtest before you deploy.

Open this page on its own · Markdown

Files: open and sealed

Share a script with or without its code.
2 min

Save any script as an .abx file to keep it, send it to someone, or import it into another account.

PropertyOpen fileSealed file
Carries the codeYesNo. The code travels sealed and only AlgoBars can open it.
Can be run and deployedYesYes
Can be read or edited by whoever imports itYesNo
States its name, what it trades, its inputs and its plain-English descriptionYesYes

A sealed script is closed about how it works, never about what it does. Sealing happens on the platform, not in your browser.

Open this page on its own · Markdown

What the Terminal does with a script

Compile, describe, run, report, versions, deploy.
2 min
The TerminalWhat it does
Compiles as you workNames, types, units, price levels against distances, R, where things may go, and imports are all checked before anything runs.
DescriptionThe script in plain English, generated from the compiled code.
Convert to AlgoBarsXType what you want in plain English. When the editor holds a description and not code, this button appears and writes the script.
RunA strategy is backtested, reported and charted. An indicator is run and charted. An alert is checked against its own settings. Before a backtest you confirm the market, bars, bar type, how far back to test (1 week to 1 year), the lot size and the starting balance.
ReplayPlays a finished backtest back. Trades appear as they open and settle as they close, and the balance moves with them. If the account ran out, the replay stops where the test stopped.
ReportHow it went, what it cost, how the trades behaved, then breakdowns by rule, exit, confirmation, side, tag and month.
VersionsEvery run is kept with the code that produced it. Restore any earlier build.
Reference and autocompleteEvery built-in is documented in the editor and offered as you type, from the same registry this page is built from.
Import, save and sealBring in a script from another language or an .abx file, and save your own as an open or sealed file.
DeployRun a strategy on a demo or live account, or switch an alert on. You choose the market, the bar size, the trade size and the balance to trade, so one script can run on more than one market. Editing a live script explains what the change would do before it is made.
Strategies listStrategies written in AlgoBarsX appear with your other strategies, where each one can be deployed, opened or deleted.
Import from a fileThe import menu takes files as well as pasted code: .pine, .mq4, .mq5, .cs, .els, .py and plain text.

The engine promises five things: no look-ahead, the same answer every time, indicators that always update, higher bar sizes that only appear once their candle has closed, and no hidden costs in the numbers. The language's own test suite has 678 tests, and all of them must pass on every build.

Open this page on its own · Markdown

The formal grammar

EBNF, reserved words and lexical rules.
EBNF

The formal grammar, for anyone building tooling such as a syntax highlighter or a linter. Notation is ISO/IEC 14977 style EBNF. The parser implements this grammar exactly, and every example on this page parses with zero diagnostics.

grammar.ebnf
(* ═══════════════════════════════════════════════════════════════════════════════
   AlgoBarsX v1 — formal grammar (Phase 0)
   ───────────────────────────────────────────────────────────────────────────────
   Notation: ISO/IEC 14977 style EBNF.  "x" = terminal,  [ ] = optional,  { } = repeat,
   ( | ) = choice.  UPPER-CASE names are tokens produced by the lexer (src/lexer/lexer.ts).
   The parser (src/parser/parser.ts) implements this grammar exactly; the acceptance scripts in
   acceptance/*.algo must parse with zero diagnostics.
   ═══════════════════════════════════════════════════════════════════════════════ *)


(* ─── 1. Lexical structure ─────────────────────────────────────────────────────── *)

(* Logical lines.  A NEWLINE ends a statement.  Line breaks inside ( ), [ ] or { } are
   ignored, so expressions may span lines there.  Blank lines and comment-only lines
   produce no tokens.  Indentation (spaces; tabs are an error) produces INDENT when a
   line is indented deeper than the enclosing block and one DEDENT per closed block. *)

NEWLINE   = ? end of a logical line ? ;
INDENT    = ? start of a deeper indentation level ? ;
DEDENT    = ? return to an enclosing indentation level ? ;
EOF       = ? end of input ? ;

comment   = "#" , { ? any character except line break ? } ;
            (* "#" followed by exactly 6 or 8 hex digits and a non-name character is a COLOR,
               except at the start of a line, where "#" always begins a comment. *)

IDENT     = letter , { letter | digit | "_" } ;          (* case-sensitive *)
letter    = "A" | … | "Z" | "a" | … | "z" | "_" ;
digits    = digit , { [ "_" ] , digit } ;                  (* 1_000_000 *)

NUMBER    = digits , [ "." , digits ] , [ ( "e" | "E" ) , [ "+" | "-" ] , digits ] ;
PERCENT   = NUMBER , "%" ;                                 (* no space: 1%  0.5% *)
RMULT     = NUMBER , "R" ;                                 (* no space: 2R  1.5R *)
MONEY     = "$" , NUMBER ;                                 (* $500 *)
DURATION  = digits , ( "s" | "m" | "h" | "d" | "w" | "M" ) ; (* 30s 15m 4h 1d 1w 1M — also timeframes *)
ORDINAL   = digits , ( "st" | "nd" | "rd" | "th" ) ;       (* 4th — only inside rule modifiers *)
TIME      = digit , [ digit ] , ":" , digit , digit ;      (* 08:00 *)
DATE      = digit , digit , digit , digit , "-" , digit , digit , "-" , digit , digit ;   (* 2026-01-15 *)
COLOR     = "#" , hex6 , [ hex2 ] ;                        (* #22c55e  #22c55e80 *)
STRING    = '"' , { character | escape | "{{" | "}}" | interpolation } , '"' ;
escape    = "\" , ( '"' | "\" | "n" | "t" ) ;
interpolation = "{" , expression , [ ":" , format ] , "}" ;   (* "RSI {rsi(close, 14):0.0}" *)

UNIT_WORD = "pips" | "pip" | "points" | "point" | "lots" | "lot" | "bars" | "bar" ;
            (* a NUMBER followed by a UNIT_WORD is one unit value: 20 pips, 10 bars *)

(* Reserved words — cannot be used as names:
     strategy indicator alert library use as input const state export type enum fn action
     return if elif else for in match when on and or not then between of true false na
     break continue confirmations sequence
   Reserved words MAY be used after "." (ribbon.on), as named-argument names (on: gold)
   and as option names (step: 0.1%).  Every other word, such as every, cooldown, session,
   bar, max, from or step, is contextual and remains usable as a name. *)


(* ─── 2. Program and header ────────────────────────────────────────────────────── *)

program       = { NEWLINE } , [ version_line ] , header , { statement } , EOF ;
version_line  = "algobarsx" , NUMBER , NEWLINE ;
header        = script_kind , STRING , NEWLINE , [ INDENT , setting , { setting } , DEDENT ] ;
script_kind   = "strategy" | "indicator" | "alert" | "library" ;
setting       = name , ":" , setting_item , { "," , setting_item } , NEWLINE ;
setting_item  = expression , { expression } ;   (* juxtaposed words: once per bar close, every 1m *)
name          = IDENT | reserved_word ;


(* ─── 3. Statements ────────────────────────────────────────────────────────────── *)

statement     = use_stmt | input_stmt | const_stmt | state_stmt | export_stmt | enum_stmt
              | type_decl | fn_decl | if_stmt | for_stmt | match_stmt | when_stmt | on_stmt
              | confirmations | sequence | command | assignment | call_stmt
              | return_stmt | "break" , NEWLINE | "continue" , NEWLINE ;

block         = NEWLINE , INDENT , statement , { statement } , DEDENT
              | statement ;                       (* one statement on the same line *)

use_stmt      = "use" , ( "indicator" | "library" ) , STRING , [ VERSION ] , "as" , IDENT ,
                [ "(" , [ arguments ] , ")" ] , NEWLINE ;
VERSION       = ? an IDENT of the form v<digits>, such as v3 ? ;

input_stmt    = "input" , IDENT , "=" , expression , { "," , option } , NEWLINE ;
const_stmt    = "const" , IDENT , [ ":" , type ] , "=" , expression , NEWLINE ;
state_stmt    = "state" , IDENT , [ ":" , type ] , "=" , expression , NEWLINE ;
export_stmt   = "export" , IDENT , "=" , expression , NEWLINE ;
enum_stmt     = "enum" , IDENT , ":" , IDENT , { "," , IDENT } , NEWLINE ;

type_decl     = "type" , IDENT , ":" , NEWLINE , INDENT , field , { field } , DEDENT ;
field         = IDENT , ":" , type , [ "=" , expression ] , NEWLINE ;
type          = name , [ "<" , type , { "," , type } , ">" ] ;     (* number, list<Level>, map<string, number> *)

fn_decl       = [ "action" ] , "fn" , IDENT , "(" , [ param , { "," , param } ] , ")" ,
                [ "->" , type ] , ":" , block ;
param         = IDENT , ":" , type , [ "=" , expression ] ;

assignment    = IDENT , ":" , type , "=" , expression , NEWLINE          (* typed declaration *)
              | target , assign_op , expression , NEWLINE ;
target        = postfix ;                         (* must be a name, a field or an item *)
assign_op     = "=" | "+=" | "-=" | "*=" | "/=" ;
call_stmt     = postfix , NEWLINE ;               (* must end in a call: levels.push(x) *)
return_stmt   = "return" , [ expression ] , NEWLINE ;

if_stmt       = "if" , expression , ":" , block ,
                { "elif" , expression , ":" , block } , [ "else" , ":" , block ] ;
for_stmt      = "for" , IDENT , "in" , expression , ":" , block ;     (* for i in 0..50 / for z in zones *)
match_stmt    = "match" , expression , ":" , NEWLINE , INDENT , match_arm , { match_arm } , DEDENT ;
match_arm     = expression , ":" , block ;


(* ─── 4. Rules, events, confirmations and sequences ────────────────────────────── *)

when_stmt     = "when" , expression , [ "as" , IDENT ] , { modifier } , ":" , block ;
modifier      = "every" , ( ORDINAL | "bar" )                 (* every 4th · every bar *)
              | "skip" , "first" , NUMBER                     (* skip first 3 *)
              | "max" , NUMBER , "per" , IDENT                (* max 2 per day *)
              | "cooldown" , ( DURATION | NUMBER , UNIT_WORD )  (* cooldown 30m · cooldown 5 bars *)
              | "once" , "per" , "bar"                        (* once per bar *)
              | "within" , ( "session" | "sessions" ) , IDENT , { "," , IDENT }
              | "from" , TIME , "to" , TIME , [ zone ] ;      (* from 08:00 to 11:00 Europe/London *)
zone          = IDENT , { "/" , IDENT } ;

on_stmt       = "on" , IDENT , { IDENT } , [ "(" , IDENT , ")" ] , [ STRING ] , ":" , block ;
                (* on start · on bar close · on exit(trade) · on session open "new_york" · on render(canvas) *)

confirmations = "confirmations" , IDENT , ":" , NEWLINE , INDENT ,
                confirm_line , { confirm_line } , DEDENT ;
confirm_line  = IDENT , ":" , expression , NEWLINE
              | "require" , ":" , ( "all" | "any" | "at" , "least" , NUMBER ) , NEWLINE ;

sequence      = "sequence" , IDENT , [ "within" , ( NUMBER , UNIT_WORD | DURATION ) ] , ":" , NEWLINE ,
                INDENT , sequence_line , { sequence_line } , DEDENT ;
sequence_line = "step" , IDENT , ":" , expression , NEWLINE
              | "reset_if" , ":" , expression , NEWLINE ;


(* ─── 5. Commands (orders, management, notifications, drawing) ─────────────────── *)

command       = COMMAND_WORD , [ command_items ] , ( NEWLINE | ":" , NEWLINE , INDENT , statement , { statement } , DEDENT ) ;
command_items = command_item , { [ "," ] , command_item } ;   (* the comma may be omitted before an option *)
command_item  = option | expression , [ "as" , IDENT ] ;      (* positional values come before options *)
option        = name , ":" , expression ;

COMMAND_WORD  = "buy" | "sell" | "close" | "close_all" | "modify" | "cancel" | "notify" | "log"
              | "partial" | "breakeven" | "trail" | "exit"
              | "plot" | "fill" | "hline" | "mark" | "label" | "line" | "box" | "table" | "bar_color"
              | "background" | "pane" | "polygon" | "polyline" | "curve" | "channel" | "profile"
              | "heatmap" | "cells" | "candles" | "fib" | "pitchfork" | "arrow" | "icon" | "image"
              | "tooltip" | "dashboard" ;
              (* A command word starts a command only when the next token can start a value or ends the
                 line; "close > open" is an expression, "close trade" is a command.  "plot (a + b) / 2"
                 is a command because of the space before "(". *)


(* ─── 6. Expressions (lowest to highest precedence) ─────────────────────────────── *)

expression    = lambda | conditional | or_expr ;
lambda        = ( IDENT | "(" , [ IDENT , { "," , IDENT } ] , ")" ) , "=>" , expression ;
conditional   = "if" , expression , "then" , expression , "else" , expression ;
or_expr       = and_expr , { "or" , and_expr } ;
and_expr      = not_expr , { "and" , not_expr } ;
not_expr      = "not" , not_expr | comparison ;
comparison    = range_expr , [ ( "==" | "!=" | "<" | "<=" | ">" | ">=" ) , range_expr
                             | "in" , range_expr
                             | "between" , range_expr , "and" , range_expr ] ;   (* non-associative *)
range_expr    = additive , [ ".." , additive ] ;
additive      = of_expr , { ( "+" | "-" ) , of_expr } ;
of_expr       = multiplicative , [ "of" , multiplicative ] ;                     (* 2% of account.balance *)
multiplicative= unary , { ( "*" | "/" | "%" ) , unary } ;
unary         = ( "-" | "+" ) , unary | power ;
power         = postfix , [ "**" , unary ] ;                                     (* right-associative *)
postfix       = primary , { "(" , [ arguments ] , ")" | "[" , expression , "]" | "." , name } ;
arguments     = argument , { "," , argument } ;
argument      = [ name , ":" ] , expression ;

primary       = NUMBER , [ UNIT_WORD ] | PERCENT | RMULT | MONEY | DURATION | TIME | DATE | COLOR | STRING
              | "true" | "false" | "na" | IDENT
              | "(" , expression , ")"
              | "(" , expression , "," , expression , { "," , expression } , ")"   (* tuple: (bar, price) *)
              | "[" , [ expression , { "," , expression } ] , "]" ;                (* list *)

Open this page on its own · Markdown

Nothing matches that.
Try a function name such as rsi, a setting such as max_open, a rule such as E11, or a code such as AS0304.