FOREX CRYPTO โ”‚ ALL DEMO LIVE
No terms match your search.
01

Portfolio & Allocator

Portfolio Health Portfolio
The top-level KPI tile on the dashboard. Shows healthy / total (e.g. "3/11") where "healthy" is the count of strategies currently in the healthy state. Colored green when all clear, yellow when any strategy is in watch, red when any is degrading or disabled. Clicking opens the Portfolio Intelligence page.
UI: Dashboard KPI tile ยท /portfolio header
Weight Portfolio
A strategy's normalized share of the active portfolio, expressed as 0โ€“100%. Computed by the Portfolio Intelligence engine each time an evaluation runs. Weights sum to 100% across all strategies. Probation strategies receive a fixed 5% each; the remainder is distributed among active strategies proportional to their quality score, adjusted for state, correlations, and class caps. Hard cap per strategy: 25%.
UI: /portfolio โ†’ Health Table ยท Weights tab
Weight (Raw) Portfolio
The un-normalized score before converting to a percentage. Equals quality_score ร— state_multiplier, then further adjusted by correlation penalty and class cap. After normalization, this becomes the final Weight.
UI: /portfolio โ†’ Weights tab (secondary column)
Class Exposure Portfolio
The total weight allocated to a single regime class โ€” one of trend, mean_reversion, or breakout. Capped at 40% per class so no single market regime dominates the portfolio. If adding a strategy would push its class over the cap, its weight is scaled down proportionally.
UI: /portfolio โ†’ summary API response ยท sidebar exposure bar
Max Cap Per Strategy Portfolio
Hard limit of 25% weight for any single strategy, regardless of how high its quality score is. Prevents over-concentration in one signal source. Applied after correlation penalty and class cap.
UI: /portfolio โ†’ Weights tab (bar clipped at 25%)
Probation Portfolio
The initial state for every newly deployed strategy. A strategy stays in probation until it accumulates โ‰ฅ 20 closed trades in the live DB. During probation the strategy receives a fixed 5% weight and is excluded from the live metric computation. After 20 trades the engine evaluates it normally and transitions to healthy, watch, or degrading.
UI: /portfolio โ†’ state badge (gray) ยท strategy detail health card
Correlation Clustering Portfolio
Strategies are grouped into clusters when any pair in the cluster shares a Pearson r > 0.60 on daily realized P&L (requires โ‰ฅ 20 overlapping calendar days with trades). Within a correlated pair, the lower-scoring strategy receives a 30% weight penalty to discourage double-counting similar exposures.
UI: /portfolio โ†’ Correlations tab (heatmap + cluster list)
Gross Exposure Portfolio
Total nominal position value across all currently open trades, summed in USD. Distinct from risk (which is capped at 0.1โ€“1% per trade). Gross exposure can be large even when risk is small if ATR is narrow. Shown on the risk dashboard.
UI: /risk โ†’ exposure section
Regime Shift Portfolio
A sustained change in market structure โ€” e.g. trending โ†’ ranging, low-vol โ†’ high-vol โ€” that invalidates a strategy's historical edge. The Portfolio Intelligence engine does not detect regime shifts directly; instead, sustained decay in metrics (expectancy, Sharpe, rising drawdown) is treated as the observable signal of a regime shift. A strategy may be transitioned to watch or degrading as a result.
UI: /portfolio โ†’ state transitions log
Volatility Regime Portfolio
Market classification computed by pressure_engine.py from ATR percentile (rolling 90d) and ADX breadth across all tracked instruments. Compression: ATR pctl < 35 AND ADX breadth < 35% โ€” markets quiet, ranges contracting. Normal: intermediate. Expansion: ATR pctl > 65 AND ADX breadth > 50% โ€” markets trending and volatile. Requires 2-day confirmation before a regime change is applied. See volatility_regime_state table.
ATR Percentile Portfolio
Percentile rank of today's ATR14 within the rolling 90-day ATR14 series for a given instrument. Value of 80 means today's ATR14 is larger than 80% of the past 90 days โ€” above-normal volatility. Portfolio-level value is the median across all tracked instruments. Used as the primary regime signal.
ADX Breadth Portfolio
Fraction of tracked instruments where ADX14 > 22, indicating trending conditions. Example: breadth = 0.60 means 60% of instruments are trending. Used alongside ATR percentile to confirm Expansion regime (breadth > 0.50 required).
Pressure Multiplier Portfolio
A per-strategy factor applied to base portfolio weights before re-normalization. Trend/breakout strategies get 1.15ร— in Expansion (more capital), 0.93ร— in Compression (less). Mean-reversion strategies get the inverse: 0.90ร— in Expansion, 1.07ร— in Compression. All multipliers default to 1.0 in Normal regime, during chaos, or when pressure is blocked. Stored in strategy_pressure_adjustments.multiplier.
Gross Exposure Cap Target Portfolio
Upper bound on total portfolio gross exposure as a multiple of account equity. Default 1.0ร— (100% of equity). Raised to 1.2ร— during confirmed Expansion when chaos filter is inactive and portfolio DD < 8%. Displayed on /risk as "Gross Cap Target". Does not force position sizing to exceed 1.0ร— โ€” it permits up to 1.2ร— for the risk budgeting layer.
Chaos Filter Portfolio
An emergency override in the Capital Pressure Model. Activates when ATR percentile > 95 OR the portfolio ATR percentile jumps > 25 points day-over-day. When active: all pressure multipliers forced to 1.0, gross cap target forced to 1.0. CHAOS_FILTER_ACTIVE timeline event emitted once on transition (off→on); CHAOS_FILTER_CLEARED emitted once when chaos clears (on→off). Events do not repeat on every cron cycle. Prevents aggressive sizing during sudden market dislocations (flash crashes, major news gaps).
Sizing Lineage Portfolio
A per-trade audit trail stored in the sizing_lineage table. Each order fill records how effective_risk_pct was derived: base risk, strategy weight, gross cap target, clamp reason (floored_to_min, missing_weight_fallback, etc.), weight source (pressure, health, fallback), and the snapshot timestamp. Visible on the Trades page (Sizing column) and the Strategy Detail page (Recent Sizing Decisions card). API: GET /api/sizing_lineage/recent, GET /api/strategy/{id}/sizing_lineage.
Effective Risk % Portfolio
The final risk_pct used for position sizing after applying portfolio weight scaling: effective_risk_pct = base ร— weight ร— gross_cap_target ร— safety_scalar. Floored at 0.01% (MIN_EFFECTIVE_RISK_PCT), capped at the base risk_pct. When weight-based sizing is disabled, effective_risk_pct = base_risk_pct.
Code: weight_sizing.py ยท sizing_lineage.effective_risk_pct
02

Performance Decay & Health

Strategy Health State Decay
Each strategy is assigned one of six states by the evaluation engine:
  • probation โ€” fewer than 20 closed trades; no metric evaluation
  • healthy โ€” all ratios within tolerance
  • watch โ€” one metric mildly off (e.g. Sharpe dropped 30%, or DD stress > 1.2ร—)
  • degrading โ€” significant deterioration (expectancy < 50% of baseline, or DD stress > 1.5ร—)
  • disabled โ€” automatic disable trigger hit (DD stress > 2ร—, expectancy < 30%); sticky โ€” requires manual reset
  • retired โ€” terminal; cannot be re-enabled via API
disabled and retired are sticky states โ€” a one-day metric recovery does not auto-enable a troubled strategy. Reset via POST /api/strategy/{id}/state.
UI: /portfolio โ†’ Health Table ยท Decay Gauges ยท /strategy/{id} health card
Decay Gauge Decay
A horizontal bar on the Portfolio โ†’ Decay Gauges tab showing a live metric as a ratio of its backtest baseline (e.g. Expectancy: 0.82ร—). The bar is filled to the ratio value (clipped at 1.0 = baseline). Color coding: green โ‰ฅ 0.8, yellow 0.5โ€“0.8, red < 0.5. Missing ratios (no baseline registered) show "No baseline" in muted text.
UI: /portfolio โ†’ Decay Gauges tab
Rolling Sharpe (30d) Decay
Annualized Sharpe ratio computed from the last 30 calendar days of closed trades. Formula: (mean_daily_pnl / std_daily_pnl) ร— โˆš252, where days with no trades are filled with zero P&L. Requires at least 10 non-zero trading days in the window; returns null otherwise. Compared against the backtest Sharpe to produce the Sharpe Ratio health metric.
UI: /portfolio โ†’ Health Table ยท Decay Gauges ยท /strategy/{id} health card
Rolling Expectancy (30t) Decay
The mean realized P&L over the last 30 closed trades (most-recent 30 regardless of date). Measured in USD at the live position size (typically units=1000 for demo accounts). Requires at least 15 closed trades in the window; returns null otherwise. Compared against the backtest expectancy to produce the Expectancy Ratio.
UI: /portfolio โ†’ Health Table ยท Decay Gauges
Drawdown Stress Ratio Decay
The live all-time maximum drawdown expressed as a multiple of the backtest maximum drawdown: live_max_dd% / backtest_max_dd%. A ratio of 1.0 means the live drawdown exactly matches backtest. Thresholds: >1.2 โ†’ watch, >1.5 โ†’ degrading, >2.0 โ†’ disabled. If no baseline is registered, absolute fallbacks apply: >10% โ†’ watch, >20% โ†’ degrading.
UI: /portfolio โ†’ Decay Gauges ยท Health Table (DD Stress column)
Expectancy Ratio Decay
Live rolling expectancy divided by the registered backtest expectancy: rolling_expectancy_30t / backtest_expectancy. A ratio of 1.0 = live is matching backtest. Below 0.7 โ†’ watch, below 0.5 โ†’ degrading, below 0.3 โ†’ disabled. null if either value is missing.
UI: /portfolio โ†’ Health Table ยท Decay Gauges
Sharpe Ratio (Health) Decay
The rolling 30d Sharpe divided by the registered backtest Sharpe: rolling_sharpe_30d / backtest_sharpe. Below 0.7 โ†’ watch. Unlike expectancy and drawdown, a low Sharpe ratio alone does not trigger degrading/disabled โ€” it is an early-warning signal only. null if either value is missing or the rolling window has insufficient data.
UI: /portfolio โ†’ Health Table ยท Decay Gauges
Baseline Decay
The set of reference backtest metrics registered for a strategy via POST /api/strategy/{id}/baseline. Fields: backtest_sharpe, backtest_expectancy (mean P&L per trade at units=1000), backtest_max_dd_pct, backtest_win_rate, backtest_pf, backtest_score. All fields are optional โ€” missing fields result in null ratios which are skipped in state evaluation. Registering a baseline is part of the new strategy deploy checklist.
UI: /strategy/{id} โ†’ Strategy Health card (baseline row)
03

Spread & Execution Cost

Spread Pips Spread
The modeled round-trip bid-ask spread for a currency pair, in pips. Set per strategy class (e.g. EURUSDLondonBreakoutM15 uses 1.6p). This spread is deducted from every simulated trade in the backtest engine as: spread_pips ร— pip_size per trade. For production strategies, the spread is sampled from live OANDA data using backtest/sample_spreads.py and stored in spread_config.json.
UI: /risk โ†’ execution quality ยท strategy detail exec quality card
Effective Spread Baseline Spread
The p50 (median) spread observed by sampling live OANDA candle data across the strategy's active session window. Stored in backtest/spread_config.json as p50_all (all hours) and p50_london, p50_asia, etc. The conservative p50_all is used as the backtest spread to avoid underestimating costs during off-peak hours.
UI: /risk โ†’ avg spread cost ยท execution quality
Half Spread Spread
One side of the round-trip spread โ€” the cost paid at entry (or exit). Equal to spread_pips / 2. Used when reporting per-trade entry cost separately from exit cost. For a 1.6-pip EUR_USD spread, the half spread is 0.8 pips per fill.
UI: /risk โ†’ execution quality (avg half spread column)
Avg Half Spread Spread
The average actual half-spread cost observed across recent executed trades, measured in pips. Computed from order_events by comparing fill price to the pre-fill mid price. If the measured avg half-spread is significantly above the modeled spread, the strategy's backtest assumptions may be optimistic.
UI: /risk โ†’ execution quality table
Cost Stress Multiplier Spread
A synthetic multiplier applied to the modeled spread during backtest validation. The standard test uses 2ร— spread (double the sampled spread). A strategy that remains profitable at 2ร— cost is considered robust to spread widening, liquidity gaps, and slippage. Any strategy failing the 2ร— cost test is rejected regardless of its base score.
UI: validation output (cost_stress_ok column)
Pressure Multiplier Spread
Used by the ForexSessionMomentum strategy archetype. A scale factor (e.g. 1.5ร—) applied to the ATR-based stop/TP distance when momentum is strongest โ€” typically during the first 30โ€“60 minutes after a session open (London/NY). Widens the trade boundary to accommodate the larger expected move during high-pressure periods, reducing premature stop-outs.
UI: strategy detail (session momentum strategies only)
04

Backtest & Validation / Gating

Multi-Window Score Backtest
The primary quality metric for any backtested strategy. A weighted composite of per-window scores across three time horizons: 1Y (50%), 90D (35%), 30D (15%). A 7-day window is also computed but carries zero weight (display only โ€” too few trades). A score of 1.0 = breakeven; strategies must score โ‰ฅ 1.2 to be considered for deployment. If any qualifying window (1Y or 90D) is unprofitable, the composite score is forced to 0.
UI: sweep output ยท /admin โ†’ candidates table
Window Score Backtest
The quality score for a single time window (e.g. the 90D window). Combines: profit factor (capped at 3.0), drawdown penalty, and a sample-size gate (minimum trade count per window โ€” 50 trades for 1Y, 20 for 90D, 8 for 30D). Returns 0.0 if the minimum trade count is not met or if the window is unprofitable.
UI: sweep output (per-window PF columns)
Sweep Backtest
A parameter grid search that exhausts all combinations of a strategy's hyperparameters (e.g. ATR length, BB multiplier, stop/TP ATR multiples) against historical data. Runs in parallel across all CPU cores using Python ProcessPoolExecutor. Output is ranked by multi-window score. Run locally (24-core desktop) via python backtest/sweep.py <strategy_name>. Results with score โ‰ฅ 1.2 and passing all validation gates are posted to /api/candidates.
UI: /admin โ†’ Candidates panel
ATR Regime Gate Backtest
A mandatory gating filter that restricts entry to periods matching the strategy's expected volatility regime. For breakout strategies: ATR must be above the rolling N-percentile (e.g. >55th percentile = elevated vol). For mean-reversion strategies: ATR must be below the rolling percentile (low-vol, ranging conditions). The lookback window is typically 200 bars. Strategies without a regime gate are rejected during validation.
UI: strategy detail (strategy class label)
BB Squeeze Backtest
A period where Bollinger Bands (typically 20-bar, 2ฯƒ) have compressed to a narrow range, indicating reduced volatility and potential for a directional breakout. Used by London and NY breakout strategies: the strategy waits for a BB squeeze (band width below rolling percentile), then enters on a range expansion (close outside the bands). Not used by mean-reversion strategies โ€” those trade during the squeeze, not after it.
UI: strategy detail (breakout strategy types)
Walk-Forward (WF) Backtest
An out-of-sample validation method that splits the backtest window into multiple train/test folds along the time axis. Parameters are fixed (from the sweep); each fold evaluates the strategy on data it did not "see" during parameter selection. A strategy passes walk-forward if the majority of folds are profitable (stability). Fold scores well below 1.0 on any fold indicate fragility to period-specific data.
UI: /admin โ†’ candidates table (WF folds column)
Cost Stress Test Backtest
A post-sweep robustness check that re-runs the backtest at 2ร— the modeled spread for each candidate. If the 1Y profit factor at 2ร— cost falls below 1.0, the candidate fails and is excluded from deployment consideration. This guards against strategies that are marginally profitable but would break under real-world spread widening, slippage, or execution latency.
UI: /admin โ†’ candidates (cost_stress_ok flag)
Stability Backtest
The fraction of walk-forward folds with a positive P&L (PF > 1.0). Expressed as 0โ€“100%. A stability of 100% means the strategy was profitable in every out-of-sample fold. A stability below ~60% is a warning sign that the strategy's edge is inconsistent across time.
UI: /admin โ†’ candidates table (stability column)
Profit Factor (PF) Backtest
The ratio of gross profit to gross loss across all trades in a window: sum(winning_trades) / sum(losing_trades). A PF of 1.0 = breakeven; >1.0 = profitable. Capped at 3.0 in the scoring formula to prevent very small sample sizes from inflating the score. The 90D live PF is tracked in strategy_risk_budgets and surfaced on the risk dashboard.
UI: /risk โ†’ strategy risk table ยท strategy detail metrics
Position Weight Backtest
A live composite score (0โ€“2+) computed daily by risk_budget.py from the strategy's last 90 days of closed trades. Combines PF, drawdown, win rate, and sample size into a single number. Used as the base weight for the portfolio allocator โ€” strategies with higher scores get proportionally more weight (before state multiplier and correlation adjustments).
UI: /risk โ†’ position weight column ยท /portfolio โ†’ Weights tab
Coarse→Fine Sweep Backtest
A two-stage parameter search run by backtest/coarse_fine_orchestrator.py. The coarse stage sweeps a broad, sparse grid defined in a JSON spec file (backtest/grids/*.json) and collects the top-K results. The fine stage evaluates a ยฑ1/ยฑ2-step neighborhood around the top-N seeds, capped at a maximum combo count (default 8,000). The design guarantees that all 1D neighbors of every seed are tested, providing the neighbors_checked > 0 evidence required by the stability gate. After the sweep the best config is validated (cost stress + walk-forward + stability) and, if all gates pass, submitted to /api/candidates automatically.
Code: backtest/coarse_fine_orchestrator.py ยท backtest/grids/
Neighbourhood Stability (Fine Sweep) Backtest
A metric computed from the fine sweep results. A 1D neighbor of the best config is any config that differs in exactly one parameter by one step. neighbors_checked is the count of those neighbors that were evaluated; pass_pct is the fraction whose score is ≥ 80% of the best config's score. A high pass_pct (e.g., ≥ 60%) means the performance peak is broad and not an isolated artifact of a specific parameter combination. The API server hard-rejects candidates with neighbors_checked = 0.
UI: /admin โ†’ candidates (stability column) ยท /kb/platform#sweep
Break-Even Stop (R-Based) Execution
A server-side stop-loss management technique implemented in be_manager.py. When a trade's unrealized profit reaches 1 ร— R (where R = abs(entry_price โˆ’ initial_sl)), the SL is moved to approximately break-even (entry ยฑ a small buffer). Unlike the in-memory ATR-based BE monitor in main.py, this system stores state in the break_even_state SQLite table and runs every 5 minutes as part of the ingest cron cycle. Strategies with be_atr = 9.9 in their webhook payload have BE disabled (be_enabled = 0).
Code: be_manager.py ยท break_even_state table ยท /trades BE column
BE Buffer Execution
The small price distance subtracted from (long) or added to (short) entry price when placing the break-even stop. Computed as max(1 tick, 2 ร— half_spread), then capped at min(buffer, 0.10 ร— R). The cap ensures the buffer never consumes more than 10% of the initial risk โ€” keeping the BE stop close to entry even on wide-spread instruments.
Code: be_manager._calc_buffer()
kR (be_r_multiple) Execution
The trigger distance for the server-side BE manager expressed in R multiples. trigger = entry ยฑ kR ร— R. Default 1.0 (trigger at 1R profit). Set per-strategy via the strategies.be_r_multiple DB column โ€” NULL means use the system default. Mapping from legacy Pine params: kR = be_atr / stop_atr (e.g. demo_audusd: 0.8 / 0.8 = 1.0). Displayed in /trades BE badges as Pending (kR=1.0).
Code: be_manager.py ยท strategies.be_r_multiple ยท /kb/platform#bemanager
Meta-Labeling (ML Filter) Execution
A de Prado technique: train an ML classifier to predict P(win) for an existing rule-based strategy's signals, then use a threshold to accept/reject at signal time. The rule defines when to look for a trade; the classifier decides whether the current conditions are favorable. Deployed in signal_engine/ml_filter.py with XGBoost models stored in trading-bot/ml-models/. Each model has a .meta.json with threshold, feature order, and base strategy ID. Fail-open: any error (missing model, feature NaN, candle fetch fail) returns None and the signal fires as baseline. Strategies with the _ML suffix are siblings of their base (e.g. eur_jpy_m15_meanrev_both_v3_ML filters eur_jpy_m15_meanrev_both_v3). 14 strategies deployed at v0.4.314 with +15-45% backtest PF lift at 50-80% signal retention.
Code: signal_engine/ml_filter.py ยท ml-models/ ยท /kb/platform#ml-filter
Ensemble ML Filter Execution
An upgrade to meta-labeling that averages a per-pair XGBoost prediction with a pooled cross-pair model prediction. The pooled model is trained on signals from all pairs in an archetype (e.g. v4_impulse_m5) with pair_id as a feature. Per-pair learns pair-specific nuance; pooled learns cross-pair generalizations. Averaging the two gives +6.6% avg PF lift vs +5.3% per-pair alone (POC on 7 v4 M5 pairs). Loaded automatically in signal_engine/ml_filter.py when a per-pair .meta.json has archetype + pair_id fields and the companion {archetype}_pooled_ML.json exists. Fail-open on any error โ€” falls back to per-pair only. Deployed v0.4.320.
Code: signal_engine/ml_filter.py ยท ml-research/train_pooled_models.py ยท /kb/platform#ml-filter-ensemble
_ML Suffix Ops
Naming convention for ML-filtered sibling strategies. A strategy ID ending in _ML is a sister variant of a base strategy (same class, same params, same entry rule) that additionally runs the base's trained meta-label classifier at signal time. Both strategies fire from the same entry logic; the _ML variant only dispatches webhooks when P(win) โ‰ฅ threshold. Base and _ML run in parallel โ€” the base strategy is never modified when _ML siblings are added.
Code: Meta-Labeling ยท signal_engine/engine.py suffix check
05

Crypto Instance

BPS (Basis Points) Crypto
1 basis point = 0.01%. Crypto exchange fees are expressed in BPS of notional trade value. For example, Coinbase Advanced taker fee = ~60 BPS (0.60%). Distinct from forex pip-based spread modeling where costs are in price-distance units.
Ref: /kb/platform#crypto-mode
Slippage BPS Crypto
The difference between expected fill price and actual fill price, expressed in basis points. Crypto markets can have higher slippage than forex during volatile periods. Measured as |actual - expected| / expected ร— 10000.
Ref: /kb/platform#crypto-mode
Paper Mode Crypto
The crypto equivalent of "demo" status. When ENABLE_CRYPTO_PAPER=true, incoming crypto webhooks trigger simulated paper fills using Coinbase spot prices. Paper positions are tracked with SL/TP/BE triggers, mark-to-market updates every 5 min, and equity snapshots. Account keys use crypto_demo_* prefix. In the UI, "Demo" tab is relabeled "Paper" in crypto mode.
Code: crypto_paper_engine.py ยท config.ENABLE_CRYPTO_PAPER
Paper Fill Crypto
A simulated trade execution in paper mode. The engine fetches a spot price from Coinbase, computes ATR-based SL/TP distances, sizes the position via crypto_sizing, and deducts fee + slippage costs. Paper fills are stored in crypto_paper_fills with both entry and exit records. Webhook response changes from "mode": "log_only" to "mode": "paper".
Code: crypto_paper_engine.execute_paper_entry()
Mark-to-Market (MTM) Crypto
Periodic re-evaluation of open paper positions. Runs every 5 min via the ingest cron. For each open position: fetches current price, checks SL/TP/BE triggers (closes if hit), updates current_price and unrealized_pnl, and writes equity curve snapshots to crypto_paper_equity.
Code: crypto_paper_engine.mark_to_market() ยท ingest_log_to_sqlite.py cron
Paper Equity Crypto
Time-series of a paper account's total value (balance + unrealized P&L). One snapshot per strategy per cron tick when the strategy has open positions. Includes drawdown percentage from peak equity. Used for the equity chart on the strategy detail page.
Table: crypto_paper_equity ยท GET /api/crypto/paper/equity
Perp Paper Crypto
Paper trading mode for perpetual futures. Simulated perp fills with position netting (buy against a short reduces/closes/reverses the position, matching real Coinbase FCM behaviour). Tracks avg entry price, contracts, and realized P&L. Equity updated via MTM every 5 min. Account keys use crypto_demo_* prefix with _perp_ in the name or ETP symbol. Starting balance $10,000. Fee: 8 bps taker per side.
Code: crypto_perp_paper_engine.py ยท config.ENABLE_CRYPTO_PERP_LIVE
Position Netting Crypto
When a new perp signal opposes an existing open position: if equal contracts, the position is fully closed (P&L realized). If fewer, the position is partially reduced. If more, the position is reversed — existing is closed and remainder opens in the opposite direction (two fills: reversal_close + reversal_open). Same-direction signals add to the position with weighted average entry price. Spot paper does not use netting (always flat between trades).
Code: crypto_perp_paper_engine.execute_perp_signal()
Notional Sizing Crypto
Position sizing by notional USD value. Default notional is $1,000 per trade (from crypto_config.json โ†’ trade_notional_usd). The position is discretized into integer contracts via crypto_sizing.compute_crypto_contracts(). Fee (8 bps) and slippage (2 bps) are deducted from the account balance on each fill.
Code: crypto_sizing.py ยท crypto_paper_engine.py
Asset Class Crypto
The strategies.asset_class column ('forex' or 'crypto') that isolates data between instances. All existing strategies default to 'forex'. API endpoints accept ?asset=forex|crypto|all โ€” when omitted, defaults to forex for backward compatibility.
Code: dashboard_api._asset_frag() ยท strategies.asset_class
Contract Size (CRYPTO_SPECS) Crypto
The base-asset amount per integer contract. Defined in crypto_config.json โ†’ crypto_specs per symbol. ETH-USD = 0.1 ETH, BTC-USD = 0.001 BTC. Trades are sized in integer multiples: contracts = floor(notional_usd / (entry_price ร— contract_size)). If contracts < min_contracts, the trade is blocked entirely.
Code: backtest_crypto/crypto_engine.discretize_trades() ยท crypto_sizing.py
Blocked Rate Crypto
Percentage of backtest trade signals skipped because the notional was too small for even one contract: blocked / (traded + blocked) ร— 100. A blocked_rate > 0% means trade_notional_usd is too low for some price levels. Increase notional or lower contract_size to reduce blocking.
Ref: backtest_crypto/README_crypto.md#blocked-trades
Log-Only Mode Crypto
The fallback crypto execution mode. Webhook alerts are received and stored in crypto_webhook_events but no orders are placed. Used when: paper mode is disabled for demo strategies, live execution is disabled for live strategies, or for perp strategies (monitoring only). Response: {"ok": true, "mode": "log_only"}.
Code: main.py webhook handler
Spot Live Execution Crypto
Live Coinbase market orders for spot crypto pairs (ETH-USD, BTC-USD). Gated by ENABLE_CRYPTO_SPOT_LIVE=true + strategy row with status='live' and asset_class='crypto'. Buys sized by notional USD (CRYPTO_TRADE_NOTIONAL_USD). Sells require explicit base_size or qty in the webhook payload. Perp strategies are rejected at the spot execution layer.
Code: coinbase_spot_exec.submit_spot_order() ยท config.ENABLE_CRYPTO_SPOT_LIVE
Live Gate Crypto
Prerequisites checked before a crypto_live_* webhook triggers a real order: (1) strategy row exists with asset_class='crypto', (2) strategy status is 'live', (3) symbol is in the supported set (ETH-USD, BTC-USD). Failure returns {"ok":false, "blocked":true} with an alert.
Code: main._crypto_live_gate()
CFM (Certified Futures Market) Crypto
Coinbase's futures trading platform. The system discovers CFM products (ETP contracts, nano contracts) via list_products(product_type="FUTURE") and caches them in crypto_perp_products. Position snapshots are polled via list_futures_positions() every 5 min. Phase C is read-only โ€” no live perp trading.
Code: coinbase_cfm_api.py ยท config.COINBASE_CFM_KEY_FILE
Perp Strategy Detection Crypto
A webhook is classified as a perp strategy if the account key contains _perp_ or ends with _perp, or the symbol matches ETP, *-PERP, *FUT*, or *SWAP*. Perp webhooks are logged but not executed on the spot exchange (SPOT_DERIVATIVE_REJECT). Perp live execution is gated by ENABLE_CRYPTO_PERP_LIVE (future).
Code: coinbase_spot_exec._is_perp_strategy()
Spot Fill Poller Crypto
Cron job (every 5 min) that polls Coinbase get_fills() for new fills on active live strategies. Uses cursor-based pagination with timestamp fallback. Fills are deduplicated via entry_id UNIQUE on crypto_fills. Matches fills to crypto_orders and reconciles orders stuck in submitted status.
Code: coinbase_spot_poller.poll_spot_fills()
06

Ops & Infrastructure

Signal Engine Ops
A separate systemd process that polls OANDA candles, runs strategy.prepare(), and dispatches signals to POST /webhook for execution. The sole execution source for all strategies (TradingView retired 2026-03-13). Runs in live mode (dispatch) or shadow mode (log only). Writes to signal_engine.db (separate from dashboard.db).
Code: signal_engine/ · Platform Docs
Shadow Mode Ops
The signal engine operating mode where signals are logged but never executed. Every evaluated bar produces an event in signal_engine_events with mode='shadow'. Strategies in shadow mode observe signals without any webhook dispatch or paper execution โ€” used for monitoring and debugging.
Config: signal_engine/config.py · mode field
Signal Parity Ops
The comparison between signal engine dispatch events and actual webhook executions for a given strategy. Matches by signal direction (buy/long, sell/short) and time proximity. Produces a match_rate (0.0–1.0). Engine-only signals indicate cooldown/guard blocks; execution-only events indicate unexpected fills.
CLI: python -m signal_engine.run --parity
Disk Usage Ops
The percentage of EC2 disk space consumed. Displayed as a KPI tile on the /ops page (both Forex and Crypto views). Sourced from GET /api/ops/disk via shutil.disk_usage('/'). Thresholds: green < 70%, yellow 70–85%, red ≥ 85%.
UI: /ops · GET /api/ops/disk
Software Trailing Stop Ops
A server-side trailing stop implementation for strategies where the required trail distance (0.08-0.10 ATR, ~0.5 pips) is below OANDA's 5-pip minimum. trail_daemon.py consumes OANDA PricingStream for sub-100ms tick data and closes positions via TradeClose when the trail SL is hit at bar-close boundaries. Handles both paper and OANDA (live/demo) positions. State tracked in trail_monitor_state table. Orders are placed with a wide safety SL (2.0 ATR) and no OANDA-native trailing stop.
Code: trail_daemon.py · Platform Docs
Bracket Order Ops
An IBKR order type that submits a parent MKT (market) order together with two child orders โ€” a STP (stop loss) and a LMT (take profit) โ€” as a single atomic request. The child orders reference the parent by a client order ID. Used by ibkr_exec.submit_ibkr_order() because IBKR does not support stopLossOnFill/takeProfitOnFill like OANDA.
Code: ibkr_exec.py · IBKR Docs
Broker Ops
The execution target for live orders. Currently supported: OANDA (v20 REST API) and IBKR (Web API v1.0 + OAuth 1.0a). Set per strategy at promotion time. Stored in dynamic_account_config.broker. Market data (ATR, price feeds) always comes from OANDA regardless of the execution broker.
Code: config.py, ibkr_client.py · IBKR Docs
Contract ID (conid) Ops
IBKR's numeric identifier for a tradeable instrument. Every FX pair on IBKR is uniquely identified by a conid (e.g. EUR/USD = 12087792 on IDEALPRO). Cached in the ibkr_conid_cache table. Resolved from OANDA symbol format via ibkr_client.oanda_symbol_to_conid(). The static OANDA_TO_IBKR_CONID dict in ibkr_client.py covers all ~22 traded FX pairs.
Code: ibkr_client.py · IBKR Docs
IBKR Web API v1.0 Ops
Interactive Brokers REST API using OAuth 1.0a with RSA-SHA256 signing. Base URL: https://api.ibkr.com/v1/api/. Requires session initialisation via GET /iserver/ssodh/init and periodic keepalive via POST /tickle (every ≤60 s). Implemented in ibkr_client.py. Dependency: requests-oauthlib with RSA support.
Code: ibkr_client.py · IBKR Docs
Tickle Ops
IBKR session heartbeat โ€” POST /tickle. Must be called every ≤60 seconds to prevent the IBKR Web API session from timing out (5-minute inactivity limit). Managed by the ibkr-session.service systemd daemon (ibkr_session_daemon.py), which tickles every 55 s and persists state to the ibkr_session_state table.
Code: ibkr_session_daemon.py · IBKR Docs
Last updated: 2026-03-18  ·  Source of truth: code + CLAUDE.md. Update KB alongside any architecture change. Docs Sync Policy →