Operators Reference
Every technical trigger in Botmarley compares an indicator to a target using an operator. There are five operators, and choosing the right one is critical to how your strategy behaves.
[[actions.triggers]]
indicator = "rsi_14" # left side
operator = "<" # comparison
target = "30" # right side
Botmarley always reads left-to-right: indicator operator target. The trigger is true when the statement indicator operator target evaluates to true on the current candle.
The Five Operators
> -- Greater Than
Type: State-based
The trigger is true on every candle where the indicator value is greater than the target. It remains true for as long as the condition holds.
# True on every candle where RSI is above 70
[[actions.triggers]]
indicator = "rsi_14"
operator = ">"
target = "70"
If RSI stays above 70 for ten consecutive candles, this trigger is active on all ten. The action associated with this trigger can fire multiple times unless you limit it with max_count.
When to use: Continuous conditions, zone detection, and filters. "Only enter when the macro trend is bullish" (sma_50 > sma_200), "sell when RSI is overbought" (rsi_14 > 70).
< -- Less Than
Type: State-based
The trigger is true on every candle where the indicator value is less than the target. Like >, it fires continuously as long as the condition holds.
# True on every candle where RSI is below 30
[[actions.triggers]]
indicator = "rsi_14"
operator = "<"
target = "30"
If price stays below the lower Bollinger Band for five candles, the trigger fires on all five. Use max_count to limit it to a single firing per position.
When to use: Oversold detection (rsi_14 < 30), price below a band (price < bb_lower), negative momentum (roc_10 < -3).
= -- Equal
Type: State-based
The trigger is true when the indicator value exactly equals the target. This operator is only useful for indicators that output discrete integer values.
# True when TTM Trend is bullish
[[actions.triggers]]
indicator = "ttm_trend"
operator = "="
target = "1"
Indicators like RSI, SMA, EMA, MACD, and Bollinger Bands produce continuous floating-point values (e.g., 29.87, 30.12). A condition like rsi_14 = 30 will almost never be exactly true. Use < or > for these indicators instead.
When to use: TTM Trend (ttm_trend = 1 for bullish, ttm_trend = -1 for bearish). This is effectively the only practical use case for =.
cross_above -- Cross Above
Type: Event-based
The trigger fires once at the exact moment the indicator crosses from below to above the target. It requires two consecutive candles:
- Previous candle: indicator value <= target value
- Current candle: indicator value > target value
# Fires once when SMA(50) crosses above SMA(200) -- the "Golden Cross"
[[actions.triggers]]
indicator = "sma_50"
operator = "cross_above"
target = "sma_200"
timeframe = "1d"
After the crossing, the trigger does not fire again until the indicator drops back below the target and crosses above it again. This makes cross_above ideal for catching turning points.
Use cross_above instead of > when you want to catch the turning point rather than the sustained condition. A golden cross (sma_50 cross_above sma_200) fires once when the trend shifts bullish. Using sma_50 > sma_200 would fire on every candle where SMA(50) happens to be above SMA(200) -- potentially hundreds of candles.
When to use: Moving average crossovers (sma_50 cross_above sma_200), MACD signal crossovers (macd_line cross_above macd_signal), price crossing above a band (price cross_above bb_middle), zero-line crossings (macd_line cross_above 0).
cross_below -- Cross Below
Type: Event-based
The trigger fires once at the exact moment the indicator crosses from above to below the target. It requires two consecutive candles:
- Previous candle: indicator value >= target value
- Current candle: indicator value < target value
# Fires once when SMA(50) crosses below SMA(200) -- the "Death Cross"
[[actions.triggers]]
indicator = "sma_50"
operator = "cross_below"
target = "sma_200"
timeframe = "1d"
After the crossing, the trigger does not fire again until the indicator rises back above the target and crosses below it again.
When to use: Trend reversal exits (sma_50 cross_below sma_200), bearish MACD crossovers (macd_line cross_below macd_signal), price breaking below support (price cross_below bb_lower).
State-Based vs Event-Based
The most important distinction in Botmarley's operator system is between state-based and event-based operators.
| Type | Operators | Fires | Best for |
|---|---|---|---|
| State-based | >, <, = | Every candle where the condition is true | Filters, zones, continuous conditions |
| Event-based | cross_above, cross_below | Once at the moment of crossing | Entry signals, exit signals, trend shifts |
Why it matters
Consider RSI dropping below 30. With <, the trigger fires on every candle where RSI is below 30. If RSI stays oversold for 20 candles, the associated action can fire up to 20 times. With cross_below, the trigger fires once -- on the candle where RSI first drops below 30.
# STATE-BASED: fires on every candle where RSI < 30
[[actions.triggers]]
indicator = "rsi_14"
operator = "<"
target = "30"
# EVENT-BASED: fires once when RSI crosses below 30
[[actions.triggers]]
indicator = "rsi_14"
operator = "cross_below"
target = "30"
Neither is inherently better -- the right choice depends on your strategy:
- Use state-based when the condition is a prerequisite (e.g., "only enter during uptrends" with
sma_50 > sma_200). - Use event-based when you want a precise entry or exit signal (e.g., "enter when MACD crosses above signal").
Targets
The target field in a trigger accepts two types of values:
Numeric Targets
A fixed number, written as a string. Used for absolute thresholds.
target = "30" # RSI threshold
target = "0" # MACD zero-line
target = "-3" # Negative value (ROC below -3%)
target = "50000" # A specific price level
target = "500" # ATR threshold
Indicator Targets
Another indicator name. Both the indicator and target are evaluated on the same candle at the same timeframe. This enables indicator-vs-indicator comparisons.
target = "sma_200" # Compare against 200-period SMA
target = "ema_50" # Compare against 50-period EMA
target = "bb_upper" # Compare against upper Bollinger Band
target = "bb_lower" # Compare against lower Bollinger Band
target = "bb_middle" # Compare against middle Bollinger Band
target = "price" # Compare indicator against current price
target = "obv_sma_20" # Compare OBV against its SMA
target = "macd_signal" # Compare MACD line against signal line
When using an indicator as a target, the order matters. indicator = "sma_50" with target = "sma_200" and operator = ">" means "is SMA(50) greater than SMA(200)?" -- not the other way around. Botmarley always reads left-to-right.
Controlling State-Based Firing with max_count
State-based operators (>, <, =) fire on every candle where the condition holds. This can cause an action to execute many more times than intended. The max_count field limits how many times a trigger can fire per position.
[[actions.triggers]]
indicator = "rsi_14"
operator = "<"
target = "30"
max_count = 1 # Only fire once per position
Without max_count, a rsi_14 < 30 trigger would fire on every candle where RSI is below 30 -- potentially buying repeatedly. With max_count = 1, it fires once and then stays inactive for the remainder of the position.
max_count is especially important for DCA (Dollar Cost Averaging) actions. Each DCA level should typically have max_count = 1 so it only adds to the position once at each level, not repeatedly.
max_count has no effect on event-based operators (cross_above, cross_below) because crossovers inherently fire only once per crossing event.
Quick Reference
| Operator | Type | Fires | Example | Reads as |
|---|---|---|---|---|
> | State | Every matching candle | rsi_14 > 70 | "RSI is above 70" |
< | State | Every matching candle | price < bb_lower | "Price is below the lower band" |
= | State | Every matching candle | ttm_trend = 1 | "TTM Trend is bullish" |
cross_above | Event | Once at crossing | sma_50 cross_above sma_200 | "SMA 50 just crossed above SMA 200" |
cross_below | Event | Once at crossing | macd_line cross_below macd_signal | "MACD just crossed below signal" |