Market regimes

How Forven classifies markets into four regimes — TREND_UP, TREND_DOWN, RANGE_BOUND, HIGH_VOL — gates each strategy to the conditions it was built for, and vetoes entries that fight the market with the direction × regime gate.

A market regime is Forven's label for the condition a market is in right now: trending up, trending down, ranging, or violently volatile. Forven detects the regime from price structure and uses it in two ways. Each strategy only takes trades in the regimes it declares it can handle, and a system-wide gate can veto entries whose direction fights the market.

This page explains how regimes are detected and where they act. If you write strategies, also read writing custom strategies to learn how to declare compatible_regimes.

The four regimes

RegimeIn the appMeaningRough trigger
TREND_UPTREND UP ▲Sustained upward trendADX above 25 with bullish EMA alignment
TREND_DOWNTREND DOWN ▼Sustained downward trendADX above 25 with bearish EMA alignment
RANGE_BOUNDRANGE ↔No clear direction; mean-revertingLow ADX or mixed EMAs
HIGH_VOLHIGH VOL ⚡Elevated volatility regardless of directionATR ratio above 2.0

The app's chips write RANGE_BOUND as RANGE. Where the research regime model is unsure which regime a stretch belongs to, it can also show TRANSITION (amber). The thresholds are the classifier's current defaults, not promises; they may change.

How detection works

The detector reads four indicators off recent price history and combines them into one label and a confidence from 0 to 1:

  • ADX (14) — trend strength. High ADX means a directional market; low ADX means a range.
  • EMA alignment (20 / 50 / 200) — bullish when 20 > 50 > 200, bearish when the order is reversed, otherwise mixed.
  • ATR ratio — the current 14-bar ATR against its 30-bar average. Backtests, robustness tests and the live path compute it the same way, so a bar classifies identically everywhere.
  • RSI (14) — reported alongside for context.

The rules are checked in order:

  1. ATR ratio above 2.0 → HIGH_VOL.
  2. ADX ≥ 40 → a trend, whatever the EMAs say (TREND_DOWN if the EMAs are bearish, otherwise TREND_UP).
  3. ADX above 25 with aligned EMAs → TREND_UP or TREND_DOWN.
  4. ATR ratio above 1.5 → HIGH_VOL.
  5. ADX above 20 with aligned EMAs → a moderate trend, at confidence 0.4.
  6. Anything else → RANGE_BOUND.

When the indicators disagree, for example a fairly strong ADX with mixed EMAs, the fall-through to RANGE_BOUND comes with low confidence. That is by design: when the market gives no clear signal, the safe default is "no trend".

A detection needs at least 210 bars of history; with less, it reports RANGE_BOUND at confidence 0. On a cache miss the detector fetches about 300 bars, and the result is cached for 5 minutes so repeated lookups stay cheap. Latency-sensitive paths read a cached-only peek that returns nothing on a miss instead of fetching.

Strategy regime gating

Every strategy declares a compatible_regimes list, for example [TREND_UP, RANGE_BOUND]. Some families also carry ADX bounds: mean-reversion families are blocked when ADX is above 25, and trend-following families need a minimum ADX before they act.

In backtests

With regime gating on, the backtest engine computes the regime for every bar, then:

  • blocks entries on bars whose regime is not in compatible_regimes, and
  • forces an exit if the regime changes to an incompatible one mid-trade.

So a backtest measures the strategy only where it claims an edge.

Beta rough edge: regime pre-computation needs a warm-up. Windows under about 210 bars can't establish a stable regime and default the whole window to RANGE_BOUND. Backtest long enough to give the classifier real history.

In paper and live

On every bar, the scanner checks each paper (and live) strategy against the asset's current regime before it evaluates a signal. An incompatible strategy is skipped for that bar and the scan records "regime gate: … not allowed". With Strict regime gating on (the default), a detection below the minimum confidence also blocks, and strategies with no declared regime compatibility are blocked unless you allow them.

The promotion gates don't block on the current regime. They stamp the regime context onto every rejection, so you can see what the market was doing when a strategy failed.

The direction × regime gate

Separately from each strategy's own list, a system-wide direction × regime gate can veto entries whose direction fights the market. It applies to paper and live opens from the execution kernel and to live-armed Bot Factory bots.

  • Default rule: block longs while an asset reads TREND_DOWN or HIGH_VOL. No short rule ships by default. The defaults come from Forven's own audit of archived strategies, where longs opened in those regimes were the dominant loss engine.
  • Minimum confidence 0.6. When the detector agrees on the hostile label but with lower confidence, the veto is downgraded to allow. Confidence can only rescue an entry, never extend a block.
  • Modes: off (no blocking, no logging), observe (the default: nothing is blocked, but every entry the gate would have blocked is logged), and enforce (those entries are vetoed).
  • Prove it before you trust it. About 48 hours after each logged event, Forven marks what the blocked entry would have made. A green result means the blocked entry would have lost money, so the gate helped.

The Regime Gate panel on the risk page has off / observe / enforce buttons, a ledger of recent events, a verdict ("collecting evidence", "earning its keep", or "blocking winners — review rules"), and a rules line such as "block longs in TREND DOWN, HIGH VOL; block shorts in none; min confidence 60%". Its Edit rules link opens Settings → Trading → Regime gating. The environment variable FORVEN_REGIME_GATE_MODE overrides the saved mode.

Per-regime metrics

Because regimes are computed per bar, results can be sliced by regime. A backtest produces a by_regime breakdown alongside the usual metrics, split across trend_up, trend_down, range_bound and high_vol. It tells you whether an edge is broad or leaning on one lucky regime. The gauntlet's regime-split test uses the same idea as a pass/fail check; by default its verdict is recorded at the door into paper and enforced at paper → live. Prefer out-of-sample numbers; in-sample metrics are optimistic by construction.

Forven is a research tool. Backtest and regime metrics describe the past on historical data; they are not predictive of future results, and nothing here is financial advice.

Settings

Everything below is in Settings → Trading → Regime gating. Precedence is environment variable, then saved settings, then config.json, then defaults.

SettingKeyDefaultWhat it does
Strict regime gatingstrict_regime_gatingOnBlock trades when the strategy/regime compatibility check fails, and block low-confidence detections
Regime minimum confidenceregime_min_confidence0.3Confidence a detection needs before strategy gating trusts it
Allow unknown strategy typesallow_unknown_regime_strategiesOffLet strategies with no declared regime compatibility pass
Direction×regime gate moderegime_gate_modeObserveoff, observe or enforce
Gate: block longs in regimesregime_gate_block_longTREND_DOWN,HIGH_VOLRegimes where long entries are vetoed
Gate: block shorts in regimesregime_gate_block_short(none)Regimes where short entries are vetoed
Gate: minimum confidenceregime_gate_min_confidence0.6Below this, the direction veto is downgraded to allow

Raising regime_min_confidence has a sharp consequence in strict mode: a valid but low-confidence label, such as a quiet RANGE_BOUND at 0.3, will block. Tune it to your risk appetite rather than maxing it out.

Where you see it

  • The control strip at the top of every page shows a chip for BTC, ETH and SOL, such as BTC ▲ TREND UP followed by the confidence as a percentage. Click it for the ADX, EMA, ATR and RSI readings behind the label.
  • The trading desk (Paper Trades and Live Trades) has a Regimes toggle under the chart that shows a regime timeline for the market, and a Regime filter in the journal.
  • The strategy page's Robustness tab has a Regime split card: average return per trade by the regime at entry.
  • All Trades has a Regime column.
  • The risk page shows the Regime Gate panel and its ledger.
  • From a terminal, python -m forven regime status prints the current regimes.

Steps: gate a strategy to its regimes

Declare the regimes your strategy is built for with compatible_regimes; see writing custom strategies. Built-in strategies already declare theirs.

Leave Strict regime gating on to block incompatible strategies and low-confidence detections, or turn it off to allow them.

Keep Regime minimum confidence at 0.3 unless you want ambiguous regimes rejected too.

Run a backtest. The engine computes the per-bar regime, blocks out-of-regime entries and forces exits on mid-trade regime flips.

Read the by_regime breakdown and the Regime split card to confirm the edge holds where you expected it, and only there.

  • The gauntlet — the robustness battery, including the regime-split test
  • Metrics — every number a backtest computes, including the by_regime slice
  • Risk — the Regime Gate panel and the other live safety controls
  • Writing custom strategies — how to declare compatible_regimes