Symbol()
A Symbol() is a slot for a market instrument. The subscriber binds a real ticker (SPY, AAPL, TA35) to the slot when they deploy the strategy. The strategy itself never hard-codes ticker symbols.
Single-symbol strategies
When a strategy has exactly one Symbol(), it’s implicitly the trading symbol — no need for trade=True.
# Fully open — subscriber picks broker, session, and tickertrade = Symbol()
# Broker-lockedtrade = Symbol(broker="tradestation")
# Session-lockedtrade = Symbol(session=USEquityDaily)
# Fully specifiedtrade = Symbol("SPY", broker="tradestation", session=USEquityDaily)The more you specify, the more constrained the subscriber’s choice. Leave fields unset to maximize reusability.
Multi-symbol strategies (data feeds)
When you declare two or more Symbols, exactly one must be marked trade=True — that’s the only slot orders can target. The rest are data feeds.
class SPYFiltered(Strategy): trade = Symbol(session=USEquityDaily, trade=True) # required marker spy = Symbol(ticker="SPY") # data feed vix = Symbol(ticker="VIX") # data feed sizing = FixedCapital()
def execute(self): spy_sma = SMA(50, on=self.spy) vix_sma = SMA(20, on=self.vix)
if self.spy.close > spy_sma.value and self.vix.close < vix_sma.value and self.trade.is_flat: self.buy(self.trade)Data feeds expose OHLCV (self.spy.close, self.vix.high, etc.) but no position helpers — self.spy.is_flat is a compile error. You cannot place orders against a data feed.
Sub-panes don’t bind slots
A chart’s sub-panes are visualisation only — they display additional symbols next to the main chart for human consumption. They do not feed strategy slots. Putting $VIX.X in a sub-pane next to a chart running a strategy with a vix slot will not wire that sub-pane’s data into the strategy.
Slot bindings are determined, in priority order, by:
- Strategy lock. A
Symbol("$VIX.X", broker="...", session=...)declaration sets aRequiredconstraint. The backtest dispatch enforces this — an attempt to override a locked slot at run time fails with HTTP 400RC_SLOT_BINDING_REJECTED. - Per-run picker. For slots the strategy leaves open (
Symbol()with no ticker), the BacktestForm renders a picker so the user supplies the symbol for that slot at run time. - Workspace feeds (legacy). Used only when no compiled
SymbolSlotsJsonexists for the strategy.
If none of the three fills a slot, the resolver falls back to the trade-slot ticker for every open slot — which usually produces the wrong data and zero trades.
Constructor arguments
| Argument | Type | Notes |
|---|---|---|
ticker |
string (optional, positional or kwarg) | Hard-codes a specific ticker. Subscribers cannot change it. |
broker |
string (optional) | Lock to a single broker (e.g. "tradestation"). |
session |
identifier (optional) | Lock to a named session (e.g. USEquityDaily). Sessions are declared globally and referenced by class name — no quotes. |
trade |
bool (optional) | Required True on exactly one symbol in multi-symbol strategies. |
OHLCV access
Once declared, the slot exposes price data on every bar:
self.trade.close # current bar closeself.trade.open # current bar openself.trade.high # current bar highself.trade.low # current bar lowself.trade.volume # current bar volumeAll return decimal (financial precision — never float).
Position helpers (trading symbol only)
self.trade.is_flat # position == 0self.trade.is_long # position > 0self.trade.is_short # position < 0self.trade.has_position # position != 0self.trade.position # current quantity (decimal)These exist only on the trading symbol, not on data feeds. self.spy.is_flat → RC2_DATAFEED_HELPER.
Common diagnostics
| Code | What it means |
|---|---|
RC2_NO_SYMBOL |
No Symbol() declared. |
RC2_NO_TRADE |
Multi-symbol strategy without trade=True. |
RC2_MULTI_TRADE |
More than one Symbol(trade=True). |
RC2_SYMBOL_TICKER |
The ticker is not a string literal, or was given both positionally and via ticker=. |
RC2_SYMBOL_BROKER |
broker= is not a string literal. (The broker name is not validated here — an unknown one surfaces at bind time, not compile time.) |
RC2_SYMBOL_EXTRA_POSITIONAL |
More than one positional argument — only the ticker is positional. |
RC2_SYMBOL_UNKNOWN_KWARG |
A keyword outside ticker, broker, session, trade. |
RC2_UNKNOWN_SESSION |
Session name does not resolve. |
RC2_DATAFEED_HELPER |
Position helper used on a data feed. |