Back to Strategy Builder Docs
DocumentationStrategy Builder

Nodes: Logic

Complete reference for Condition, Logic Gate (AND/OR/NOT), and Signal Gate nodes. These nodes form the decision-making core of every strategy: they evaluate inputs, combine boolean signals, and control signal timing and duration.

Condition Node

The Condition node is the core logic unit of the strategy builder. It evaluates a comparison between a left operand (a value from an indicator, price, pattern, or other source) and a right operand (a fixed value, another indicator, a level, or nothing) using an operator. The output is a boolean (true/false) result that flows to logic gates, signal gates, or directly to entry/exit nodes.

Every condition has three core components: the left side defines what is being compared, the operator defines how it is compared, and the right side defines what it is compared against. The available choices for each component depend on the connected source nodes, creating a context-sensitive inspector that adapts as you wire the graph.

Left Side (input handle: left)

The left operand defines what is being compared. Its type field determines the source and the available downstream options. The left handle is positioned at 35% from the top of the node's left edge.

Left Side Types

Indicator (type="indicator"): When a node with a value or signal handle connects to left. The left side displays the connected node's name and its output value. For indicators, you select which field to use (e.g., sma, rsi, macd). This is the most common left-side type.

Price (type="price"): Auto-set when a level node (fibonacci, pivot_points, price_levels, volume_profile) connects to the right handle. The left side is automatically configured to price, and you select which price field: open, high, low, close, hl2, hlc3, ohlc4. This is the typical pattern for “price crosses level” conditions.

Pattern (type="pattern"): When a pattern node connects. You select the signal name from the pattern's signals_map (e.g., “Bullish”, “Bearish”).

Classifier (type="classifier"): When a classifier node connects. Generates categorical signals: Short, Neutral, or Long.

Regressor (type="regressor"): When a regressor node connects. Outputs a percentage value representing the predicted return or price change.

Strategy (type="strategy"): When a strategy reference node connects. Generates categorical signals based on the referenced strategy's direction_bias.

SMC (type="smc"): When an SMC (Smart Money Concepts) node connects. Per-signal output_types determine behavior: signals can be binary, numeric, or level.

The left side type is the single most important decision in condition configuration. It determines which operators are available, what the right side shows, and how the entire condition is evaluated. Getting the left side type wrong means the condition evaluates against the wrong data entirely.

Operator (required)

The comparison operator defines the logical relationship between left and right. The available operators depend on the left side's output_type, which is determined by the connected source node.

Numeric Operators (output_type: numeric)

Most indicators and price sources produce numeric outputs. Available operators:

ParameterTypeDefaultDescription
crosses_abovestring-Value crosses above the right-side threshold within the lookback window. Most commonly used operator for entry signals.
crosses_belowstring-Value crosses below the right-side threshold. Common for exit signals or short entries.
>string-Left value is strictly greater than the right-side value. Simple inequality check evaluated each bar.
<string-Left value is strictly less than the right-side value.
>=string-Left value is greater than or equal to the right-side value. More permissive than strict greater-than.
<=string-Left value is less than or equal to the right-side value.
==string-Left value equals the right-side value. Rarely used for exact numeric equality due to floating-point precision; prefer crosses_above/below for cross detection.
!=string-Left value does not equal the right-side value.
is_risingstring-Left value is increasing over the lookback period. The current bar value exceeds the value N bars ago.
is_fallingstring-Left value is decreasing over the lookback period. The current bar value is below the value N bars ago.
is_rising_faststring-Left value is increasing rapidly over the lookback. Uses a stricter slope threshold than is_rising.
is_falling_faststring-Left value is decreasing rapidly over the lookback. Uses a stricter negative slope threshold.
pct_change_abovestring-Percent change of left value exceeds the right-side threshold. Percentage is computed over the lookback window.
pct_change_belowstring-Percent change of left value is below the right-side threshold.
value_above_for_n_barsstring-Left value has stayed above the right-side threshold for at least N consecutive bars. Useful for persistence-based conditions.

Zero-Crossing Operators (output_type: zero_crossing)

Used for indicators that oscillate around zero (MACD histogram, momentum indicators). Includes crosses_above (crosses above zero) and crosses_below (crosses below zero), plus select numeric operators.

Binary Operators (output_type: binary)

For sources that produce only true/false signals. Right side is hidden (type=none).

ParameterTypeDefaultDescription
is_truestring-The binary signal is currently active (true). Evaluated on each bar independently.
is_falsestring-The binary signal is currently inactive (false).
just_turned_truestring-The binary signal just became true on this bar (edge detection — was false on the previous bar). Useful for entry-on-signal-change.
just_turned_falsestring-The binary signal just became false on this bar. Useful for exit-on-signal-loss.

Categorical Operators (output_type: categorical)

For patterns, classifiers, and strategies that produce named signals.

ParameterTypeDefaultDescription
==string-Match a specific category or signal name. For patterns: select from signals_map (e.g., "Bullish Engulfing"). For classifiers: Short, Neutral, or Long. For strategies: based on direction_bias.
!=string-Any category except the specified one. Useful for "not Neutral" conditions.

Percentage Operators (output_type: percentage)

For regressor nodes that output predicted return percentages.

ParameterTypeDefaultDescription
>string-Predicted return exceeds X%. Right side value input includes a % suffix.
<string-Predicted return is below X%.
crosses_abovestring-Predicted return crosses above X% within the lookback.
crosses_belowstring-Predicted return crosses below X% within the lookback.

Level Operators (output_type: level)

Auto-set when left is price and right is a level node. These operators are designed for price-versus-level interactions.

ParameterTypeDefaultDescription
crosses_abovestring-Price crosses above the level. A classic breakout signal.
crosses_belowstring-Price crosses below the level. A breakdown signal.
>string-Price is above the level on this bar. Simple positional check.
<string-Price is below the level on this bar.
bounces_fromstring-Price touches the level and reverses away from it. Indicates the level is acting as support or resistance. Requires a reversal confirmation within the lookback.
breaks_throughstring-Price breaks through the level with conviction (e.g., closes beyond it). Different from crosses_above/below which trigger on any touch.
is_nearstring-Price is within a threshold distance of the level. Threshold is configurable.
is_farstring-Price is beyond a threshold distance from the level.

Operator selection has dramatic consequences for strategy behavior. crosses_above triggers on the first bar where the condition becomes true (edge-triggered), while > triggers on every bar where it remains true (level-triggered). Using > without a cooldown or hold gate will generate a new signal every single bar, which is almost never desired. Cross operators are almost always the right choice for entry signals.

Using == (equals) on floating-point numeric values is unreliable due to floating-point precision. Two values that look equal (e.g., 50.0) may differ at the 15th decimal place. Prefer crosses_above or crosses_below for threshold-based conditions, or use a small tolerance with >=/<=.

Right Side (input handle: right)

The right operand defines what the left side is compared against. The right handle is positioned at 65% from the top of the node's left edge. The UI for the right side depends on its type:

Value (type="value"): A free-form numeric input field. Enter any number. Used when comparing an indicator to a fixed threshold (e.g., “RSI > 70”). For percentage output types, the value input includes a % suffix to indicate the unit.

Indicator (type="indicator"): When another indicator node connects to the right handle. You select the indicator and its field. Used for indicator-vs-indicator comparisons (e.g., “SMA(20) crosses_above SMA(50)”). Both left and right can reference the same indicator using different fields (e.g., “MACD line crosses_above MACD signal line”).

Signal Selector (type="signal_selector"): A dropdown listing available signal names from the connected source's signals_map (for patterns) or predefined categories (for classifiers: Short, Neutral, Long; for strategies: based on direction_bias). The dropdown options update dynamically when you connect a new source.

Event Selector (type="event_selector"): Similar to signal selector but for strategy reference nodes. Shows events like “Long Entry”, “Short Entry”, “Long Exit”, “Short Exit” — representing trade signals emitted by the referenced strategy.

Level (type="level"): Display-only field showing the level value from the connected level node (e.g., “0.618”, “R1”, “VAH”). The level value is read from the level node's output: you do not type it manually. When a level connects to right, the left side is auto-set to price type.

None (type="none"): No right side shown. Used for binary operators (is_true, is_false, just_turned_true, just_turned_false) and SMC binary signals that do not need a right operand.

Lookback (integer, optional)

Number of bars to look back for operators like crosses_above, is_rising, and edge-detection operators. The default varies by operator. For cross operators, lookback defines how many bars back to check whether the cross occurred. For example, with lookback=1 and crosses_above: the condition is true if the left value was below the right value on the previous bar and is above it on the current bar. Larger lookback values capture crosses that occurred further in the past.

The lookback value is a subtle but powerful parameter. A cross with lookback=1 detects only very recent crosses (this bar vs last bar). A cross with lookback=5 detects crosses that occurred anytime in the last 5 bars. In a strategy with a “hold until re-entry” signal gate, a larger lookback can prevent missed entries when the strategy is between signals. However, larger lookbacks also increase the risk of acting on stale signals.

MTF Override

Visible when the data source's multi-timeframe (MTF) configuration is enabled AND the left type is price. Provides symbol, bar_type, and timeframe fields that propagate from the MTF configuration. When price is selected, the condition can evaluate at a different timeframe than the main strategy. For example, a strategy running on 15m bars can have a condition checking whether daily price crosses above a pivot point.

Image Placeholder: Condition inspector showing all labeled sections: left side (type=indicator, field=sma), operator dropdown (crosses_above), right side (type=indicator with field selector), lookback input (1), and MTF override section (collapsed). Output handle (result) on the right edge.

Fig. 1: Fully configured Condition node inspector with indicator-vs-indicator comparison.

Condition Behavior Resolution

This section explains the automatic resolution logic that runs when you connect a source node to a condition. Understanding this process helps you predict how the condition inspector will reconfigure itself before you even wire the connection.

The resolveConditionBehavior() Pipeline

When you connect a node handle to a condition's left or right handle, the system runs resolveConditionBehavior() which executes four sequential steps:

  1. Determines output_type: Reads the output_types from the source node's registry definition. For indicators, this comes from indicators.json output_types[output]. For patterns: from patterns.json _condition.output_type. For SMC: per-signal from market-structure.json. Falls back to 'numeric' if not specified.
  2. Selects operator set: Uses condition.json _operator_sets[output_type] to determine which operators are available in the dropdown. Each output type maps to a curated list of semantically appropriate operators.
  3. Configures right side: Based on the operator set, determines whether the right side shows a value input, signal selector, event selector, level display, or nothing (none).
  4. Auto-populates handles: When connecting, the system auto-populates the target handle based on the source handle type. It also auto-redirects: value/ signal handles landing on right are redirected to left; level handles landing on left are redirected to right.

The auto-redirect behavior is intuitive once you understand it but can be confusing the first time. If you connect a level node to a condition's left handle and the connection appears on the right handle instead, this is not a bug: it is the auto-redirect enforcing the rule that levels always go to right and automatically set left to price.

Resolution Summary Table

ParameterTypeDefaultDescription
Data Source (price)numeric15 operatorsOpen, High, Low, Close, HL2, HLC3, OHLC4. Right side: Value input.
Indicator (default)numeric15 operatorsMost indicators: SMA, EMA, RSI, MACD, Bollinger, ATR, etc. Right side: Value input or Indicator (if another indicator connected to right).
Indicator (zero_crossing)zero_crossingCross + extraMACD histogram, momentum oscillators centered at zero. Right side: Value input (usually 0).
Indicator (binary)binary4 operatorsBinary indicators like "above_band", "below_band". Right side: None.
Patterncategorical==, !=Candlestick and chart patterns. Right side: Signal selector from signals_map (e.g., "Bullish Engulfing").
Classifiercategorical==, !=ML classification models. Right side: Signal selector (Short, Neutral, Long).
Regressorpercentage4 operatorsML regression models outputting predicted %. Right side: Value input with % suffix.
Strategy Referencecategorical==, !=Referenced strategy signals. Right side: Event selector (Long Entry, Short Exit, etc.).
SMC (binary signal)binary4 operatorsSMC patterns like FVG, Order Block presence. Right side: None.
SMC (numeric signal)numeric15 operatorsSMC output with numeric values (e.g., swing magnitude). Right side: Value input.
SMC (level signal)level8 operatorsSMC output that is a price level (retracements, BPR, previous high/low). Right side: Level display, auto-sets left=price.
Level nodeslevel8 operatorsFibonacci, Pivot Points, Price Levels, Volume Profile. Right side: Level display (read-only from node), auto-sets left=price.

When you delete a connection to a condition, the type does not automatically reset. The inspector retains the last configured type until you reconnect or manually change it. If you remove a pattern node and reconnect an indicator, the left side may still show categorical operators. Always verify the operator dropdown after rewiring.

Logic Gate (AND/OR)

Logic gates combine multiple boolean signals into a single boolean output. They take condition results (or other logic gate outputs) as inputs and produce a composite true/false signal. This is how you express multi-condition entry rules: “Enter long when RSI < 30 and price > SMA 200 and MACD > 0.”

Logic Type (required)

Select AND or OR via tabs or buttons at the top of the inspector. This is the fundamental decision for how the gate combines its inputs.

Input Handles

AND/OR gates have 5 input handles (in-0 through in-4) stacked vertically on the left edge of the node. You can connect between 1 and 5 condition results or other logic outputs. Unconnected handles are ignored during evaluation. Handles are numbered: connections auto-populate the first free slot, filling from top to bottom.

How AND Works

ALL connected inputs must be true for the output to be true. If any connected input is false, the output is false. Use AND when you need multiple conditions to align simultaneously. Example: “RSI < 30 AND price > SMA 200” means both must be true on the same bar for the entry signal to fire.

out = in0 ∧ in1 ∧ ... ∧ inn  (where n = number of connected inputs)

How OR Works

ANY connected input being true makes the output true. Use OR for alternative entry signals: “MACD crosses above OR RSI crosses above 50” means the strategy enters on whichever signal fires first.

out = in0 ∨ in1 ∨ ... ∨ inn  (where n = number of connected inputs)

Voting / Threshold

There is no explicit voting threshold in the AND/OR gates. An AND gate requires 100% of connected inputs to be true; an OR gate requires at least 1. For weighted voting (e.g., “at least 3 of 5 conditions must be true”), use a downstream Entry node with combination_mode: 'weighted' or 'majority', which can assign weights and thresholds to individual condition inputs.

Output Handle

out (right edge of the node). Produces a boolean signal that can connect to: Entry nodes (cond-0 through cond-4), Exit nodes (cond-0 through cond-4), other Logic gates (in-0 through in-4), or Signal Gates (in). Logic gates can be nested: an OR gate can feed into an AND gate to create complex boolean expressions.

Alias

A unique, user-defined label shown on the canvas node body. Name it descriptively to document the gate's purpose (e.g., “Oversold Entry”, “Breakout Confirm”). Aliases are displayed on the node in the graph canvas and appear in the node inspector header.

Image Placeholder: Canvas view showing an AND gate node with three connected conditions on its left edge (in-0, in-1, in-2). Each condition is labeled: 'RSI < 30', 'Price > SMA 200', 'Volume > AVG'. The AND gate output connects to an Entry node's cond-0 handle. The gate alias reads 'Oversold + Trend + Volume'.

Fig. 2: AND gate combining three conditions into a single entry signal.

Nesting logic gates creates arbitrarily complex boolean logic without writing code. An OR gate whose outputs feed into an AND gate expresses “(A OR B) AND C”. An AND gate feeding into an OR gate expresses “(A AND B) OR C”. Combined with NOT gates, you can express any boolean expression. This is how the visual strategy builder achieves the expressive power of code-based strategies.

An AND gate with a single connected input is functionally a pass-through: the output equals the input. This is not an error, but it adds unnecessary complexity to the graph. If you only have one condition, connect it directly to the Entry/Exit node rather than routing it through a logic gate.

Nested Gate Example: (A AND B) OR (C AND D)

A common real-world pattern using nested gates:

  1. Condition A: RSI < 30 (oversold)
  2. Condition B: Price > SMA 200 (uptrend)
  3. AND Gate 1: Combines A AND B → “Oversold in Uptrend”
  4. Condition C: MACD crosses above signal (bullish crossover)
  5. Condition D: Volume > 1.5x average (high conviction)
  6. AND Gate 2: Combines C AND D → “MACD Cross with Volume”
  7. OR Gate: Combines AND Gate 1 OR AND Gate 2 → entry signal

This pattern means: enter long when either (a) the market is oversold in an uptrend, OR (b) MACD gives a bullish crossover with strong volume confirmation.

Logic Gate (NOT)

The NOT gate inverts a single boolean input: output is true when input is false, and output is false when input is true. This is essential for expressing negative conditions (“do NOT enter when overbought”) without needing to invert every condition individually.

Logic Type (required)

Set to NOT. Unlike AND/OR gates, NOT only supports a single input.

Input Handle

Only one input handle: in-0, centered on the left edge of the node. Connect exactly one condition result or logic output. An unconnected NOT gate produces no meaningful output: the system treats an unconnected input as invalid, and the gate outputs no signal (effectively false/inactive).

out = ¬ in0

How NOT Works in Practice

Use NOT to negate a condition or a composite logic result. Common patterns include:

  • Inverse entry filter: NOT(RSI > 70) means “do not enter when overbought.” Combined with an AND gate: “MACD crosses above AND NOT(RSI > 70).”
  • Exit on condition loss: NOT(bullish pattern active) means “exit when the pattern is no longer valid.”
  • Negating composite gates: Connect a NOT gate after an AND gate to express “NOT(A AND B)” — equivalent to “NOT A OR NOT B” (De Morgan's law).
  • Ranging market filter: NOT(trend filter) means “only trade when no strong trend is detected” — useful for mean-reversion strategies.

Output Handle

out (right edge). Same connectivity as AND/OR output: connects to Entry cond-*, Exit cond-*, other Logic in-*, or Signal Gate in handles.

Double negation (NOT > NOT > Condition) is logically equivalent to the original condition but adds unnecessary nodes and evaluation overhead. Avoid this pattern. If you find yourself wanting to negate a negation, remove both NOT gates and use the condition directly.

Image Placeholder: NOT gate inspector showing the single input handle (in-0), logic type set to NOT, and output handle (out). The alias reads 'Not Overbought'. Connected upstream to a condition 'RSI > 70'. Downstream to an AND gate that also receives a MACD signal.

Fig. 3: NOT gate inverting an overbought condition before combining with other entry criteria.

Signal Gate

The Signal Gate modifies the timing and duration of a boolean signal without changing its value. It answers questions like: “How long should I hold after the signal?”, “Should I wait N bars before acting?”, “How long should I wait before taking another entry?”

Signal Gates do not affect the logical content of a signal — they affect when and for how long the signal remains active. They sit between logic gates and entry/exit nodes, forming the final timing layer before trade execution.

Mode (required)

One of five modes, selected via a dropdown in the inspector:

hold_re — Hold Until Re-Entry

Once the input signal becomes true, the output stays true until a new signal in the opposite direction is received. This is the most common mode for trend-following strategies: hold a long position until a short signal appears. The bars parameter is not used in this mode.

Use case: A moving average crossover strategy that stays long until the crossover reverses. No fixed holding period: the trade duration is determined by when the opposite signal fires.

hold_non_re — Hold, Non-Re-entrant

Once the input signal becomes true, the output stays true for exactly bars N bars, then resets to false. A new true input during the hold period does not restart the timer. This prevents rapid re-entry and ensures each signal results in a single, fixed-duration hold.

Use case: “Enter on signal and hold for exactly 5 bars, ignoring any new signals during that window.”

delay — Delayed Activation

When the input signal becomes true, wait bars N bars before setting the output to true. If the input goes false during the delay period, the delayed output is cancelled and never fires. This is an “armed but cancellable” delay.

Use case: Wait for 2 confirmation bars after a breakout signal before entering. If the breakout fails during those 2 bars (price falls back below the level), the entry is cancelled.

The delay mode with cancellation is fundamentally different from simply shifting the signal forward by N bars. The cancellation behavior means the signal must remain true for the entire delay period. This filters out false breakouts: a breakout that immediately reverses will not trigger an entry.

cooldown — Post-Signal Cooldown

After the output becomes true (from any input trigger), enforce a cooldown period of bars N bars where new input triggers are ignored. The output itself follows the input signal (passes through), but after any true output, subsequent inputs are suppressed for N bars.

Use case: Prevent overtrading by enforcing a minimum 10-bar gap between entries. The first signal fires immediately; the next signal is ignored until 10 bars have passed.

pulse — Fixed-Width Pulse

When the input signal becomes true, the output becomes true for exactly bars N bars, then goes false regardless of the input state. Each new true input restarts the pulse, even if already pulsing. This is a “retriggerable monostable” behavior.

Use case: Generate a fixed 3-bar entry window after each signal. If a new signal fires during an active pulse, the window extends for another 3 bars from the new signal.

The difference between hold_non_re and pulse is subtle but critical. In hold_non_re, new inputs during the hold period are ignored. In pulse, new inputs restart the timer. If your strategy generates signals frequently, pulse can result in a continuously extended output that never turns off. Choose based on whether you want to ignore or honor new signals during the active period.

Bars (integer, required)

The number of bars for the mode's duration. The meaning depends on the selected mode:

ParameterTypeDefaultDescription
hold_non_reinteger5Hold duration in bars. The output stays true for exactly this many bars after the initial trigger.
delayinteger2Delay duration in bars. The signal must remain true for this many bars before the output activates.
cooldowninteger5Cooldown duration in bars. New input triggers are suppressed for this many bars after any output activation.
pulseinteger3Pulse width in bars. Output stays true for exactly this many bars. Retriggers on new input.
hold_reinteger-Not used. The hold continues until the opposite-direction signal is received.

Input Handle

in (left edge, single). Connect from a condition result handle or logic gate out handle. Only one input connection is supported: if you need to combine multiple signals before timing control, use a logic gate upstream.

Output Handle

out (right edge). Connects to Entry/Exit cond-* handles or other Logic in-* handles. The output is boolean: true during the active period (hold/pulse active), false otherwise.

Alias

A unique, user-defined label. Name it descriptively for the mode and duration (e.g., “Cooldown 5 bars”, “Delay 3 bars”, “Hold 10 bars”). This appears on the canvas node and helps document the signal timing logic.

Signal Gates are the primary mechanism for controlling trade frequency. Without them, a strategy that generates a signal on every bar would enter a new trade on every bar (subject to position sizing constraints). A cooldown of 20 bars on a 15-minute chart enforces a minimum 5-hour gap between trades. A delay of 3 bars filters out impulsive, unconfirmed signals. Getting signal timing right is often the difference between a profitable strategy and one that is chopped up by noise.

Image Placeholder: Signal Gate inspector showing the mode dropdown with 'pulse' selected, the bars input set to 3, the alias field reading 'Entry Window 3 bars', and the input/output handle labels. A small timing diagram below illustrates the pulse behavior: input rising edge triggers a 3-bar true period on output.

Fig. 4: Signal Gate configured for pulse mode with a 3-bar entry window.
Nodes: Logic — Strategy Builder — BitPredict · BitPredict