Skip to main content

Conditions

Conditions are the true/false comparisons that control your strategy's decision-making. They appear in two places:

  • Guards — conditions attached to transitions that determine whether the transition is allowed to fire.
  • Conditional actions — conditions embedded inside an action step that branch the action's logic (if/then/else).

Both use the same condition system. This page covers how conditions work, where to find them, and what they can reference.

Where Conditions Live

There is no standalone "Manage Conditions" option in the Strategy Toolbar. Conditions are always created and edited inside a guard or a conditional action step:

ContainerToolbar EntryWhat It Controls
GuardManage GuardsWhether a transition is allowed to fire
Conditional action stepManage ActionsWhich branch of an action executes

Conditions in Guards

A guard is a named, reusable set of conditions that you attach to one or more transitions. When an event arrives and a transition's trigger matches, FORJ evaluates the guard's conditions — if they pass, the transition fires.

To manage guards:

  1. In SMITH, click the gear icon to open the Strategy Toolbar.
  2. Select Manage Guards.

Each guard contains conditions organized into two groups:

  • All (AND) — every condition in this group must be true.
  • Any (OR) — at least one condition in this group must be true.

You can mix both groups in a single guard. The guard passes when all AND conditions are true and at least one OR condition is true (if any OR conditions are defined).

Conditions in Conditional Actions

A conditional action step embeds the same condition logic inside an action. It evaluates conditions and then executes different steps depending on the result:

  • True branch — steps that run when the condition passes.
  • False branch — steps that run when the condition fails.

Both branches can contain any action step type, including nested conditional steps. See Managing Actions for full details on action steps.

How a Condition Works

Each condition compares two operands using an operator:

left operand   operator   right operand
─────────── ──────── ──────────────
RSI < 30

Operators

OperatorMeaning
==Equal to
!=Not equal to
>Greater than
<Less than
>=Greater than or equal to
<=Less than or equal to

Operand Sources

Each side of a condition can reference a value from one of these sources:

SourceDescriptionExample
StaticA fixed value you enter directly.30, true, "bullish"
ContextA custom variable defined in your strategy's context.tradeCount, entryPrice
EventA field from the incoming market event payload.close, high, volume
IndicatorsAn output from a subscribed base indicator.EMA_10 value, RSI period_14 value, BB upper
Indicator EventsThe boolean result of a derived indicator signal (crossover, trend).EMA_Cross_Up, RSI_Trending_Down
TimeA component of the event's timestamp in a chosen timezone.hour, minuteOfDay, dayOfWeek, Session Active

Using Time in Conditions

The Time source lets you create conditions based on when an event occurred — time of day, day of week, or market session membership. Select a timezone, pick a time field, and compare it like any other operand.

For full details on available time fields, timezone selection, and session membership checks, see Time-Based Conditions.

Using Indicator Events in Conditions

Indicator events are derived signals configured in your strategy — such as detecting when one indicator crosses above another, or when a value is trending in a particular direction.

When you select Indicator Events as an operand source, you pick from your defined indicator events and the comparison becomes boolean — checking whether the signal is true or false. For example:

  • EMA_10_crosses_above_EMA_50 == true — fires when the crossover occurs.
  • RSI_trending_down == true — fires when RSI is moving downward.

See Indicators — Indicator Events for how to configure these signals.

Cross-Stream Conditions

When your strategy subscribes to multiple data streams, you can build conditions that reference indicator values from different streams — not just the stream that triggered the current event.

When selecting the Indicators operand source, the first dropdown lets you choose:

  • Triggering Stream — the indicator value from whichever stream produced the current event.
  • A specific named stream — a fixed reference to indicator values from that particular stream, regardless of which stream triggered the event.

This enables cross-stream comparisons directly in conditions, without context-variable workarounds:

  • [EURUSD 5m] EMA 200 > [EURUSD 1h] EMA 200 — compare the 5-minute EMA against the hourly EMA.
  • [BTCUSD 1m] RSI < 30 AND [BTCUSD 5m] RSI < 40 — require oversold readings on both timeframes.

Each operand independently selects its stream, indicator, and output. You can mix triggering-stream references with fixed-stream references in the same guard.

tip

Cross-stream conditions are especially useful for multi-timeframe strategies. Instead of manually caching higher-timeframe values in context variables, you can reference them directly — FORJ resolves the latest indicator snapshot for each stream automatically.

Creating a Guard

  1. Open the Strategy Toolbar and select Manage Guards.
  2. Click New Guard.
  3. Give the guard a descriptive name (e.g., RSI_Oversold, Price_Above_EMA).
  4. Add conditions to the All (AND) or Any (OR) groups.
  5. For each condition, configure the left operand, operator, and right operand.
  6. Save the guard.

Once created, you can attach the guard to any transition. A guard can be reused across multiple transitions.

Editing and Deleting Guards

  • Click a guard in the list to expand it, then click Edit to modify its conditions.
  • Click Delete to remove a guard. If the guard is referenced by transitions, SMITH shows an impact analysis so you can see which transitions will be affected before confirming.

Usage Counts

Each guard in the list shows a usage count — the number of transitions that reference it. This helps identify unused guards and understand the impact of changes.

tip

Give guards clear names that reflect what they check. Names like RSI_Below_30 or Price_Crossed_EMA are much easier to work with than Guard1.