Skip to main content

Strategy Canvas & Intelligence API

Strategy Canvas & Intelligence is the R&D API for defining, running, and analyzing trading strategies. Use this API to programmatically create rule-based strategy definitions (entry groups, exit controls, risk parameters), run backtests against historical market data, and monitor deployment health across backtest → paper → shadow → live phases. Built on FalkorDB (trading knowledge graph), ClickHouse (time-series), and PostgreSQL (relational state), this API serves strategy engineers, quant researchers, and live traders. All endpoints require authentication: Supabase JWT (Authorization: Bearer <token>) for users, or X-Internal-Secret header for service principals.

Base Path

Auth: Requires Supabase JWT (user) OR X-Internal-Secret (service). Strict auth enforced in prod: missing credentials → 401 Unauthorized.

Strategy CRUD & Canvas

POST /strategies

Create a new strategy with rule-based entry/exit logic, risk controls, and optional visual canvas layout.
  • Parameters: none
  • Request body: StrategyCreate
  • Response 201: StrategyResponse
Creates an initial version snapshot in strategy_versions table. If archetype is set and entry_groups is empty, injects preset rules + stop-loss configs for the archetype (momentum, trend_following, mean_reversion, volatility, or custom).

GET /strategies

List authenticated user’s strategies (paginated), optionally with latest backtest metrics.
  • Query parameters:
    • limit (integer, optional, default=20, max=100): Results per page
    • offset (integer, optional, default=0): Pagination offset
    • include (string, optional): Pass metrics to join latest backtest results
  • Response 200:
When ?include=metrics is present, each strategy includes latest_backtest (null if no runs). When absent, latest_backtest is omitted.

GET /strategies/

Get a single strategy by ID, optionally with latest backtest results.
  • Parameters:
    • strategy_id (path, required, UUID): Strategy ID
    • include (query, optional): Pass backtest to include latest backtest run (includes equity curve)
  • Response 200: Strategy object (same shape as POST response, but with optional latest_backtest including equity_curve field if requested)

GET /strategies//backtest-history

Get all backtest runs for a strategy, newest first.
  • Parameters:
    • strategy_id (path, required, UUID)
    • limit (query, optional, default=20, max=50): Number of runs to return
  • Response 200:

PUT /strategies/

Update a strategy. Increments version and records snapshots in strategy_versions if rules or risk_controls change.
  • Parameters:
    • strategy_id (path, required, UUID)
  • Request body: StrategyUpdate (all fields optional)
  • Response 200: StrategyResponse
Fields not provided are left unchanged. Canvas layout, contract selection, or any other single field can be updated independently.

DELETE /strategies/

Soft-delete a strategy (sets deleted_at timestamp).
  • Parameters:
    • strategy_id (path, required, UUID)
  • Response 204: No content

Strategy Deployment & Promotion

GET /strategies//gates

Get promotion gate status for the current deployment phase.
  • Parameters:
    • strategy_id (path, required, UUID)
  • Response 200:
Backtest→paper gates (enforced):
  • Must have run a backtest (result_row required)
  • Backtest must have sufficient trade density for walk-forward validation (oos_sharpe_pooled not null)
  • Pooled out-of-sample Sharpe ≥ 1.0
  • Minimum 5 total trades
  • At least one regime (from regime_breakdown) with positive Sharpe
  • For options strategies: stricter thresholds
Paper→shadow: Not yet available; requires live paper trading metrics. Shadow→live: No gates; operator approval required.

POST /strategies//promote

Promote a strategy to the next deployment phase if gates pass.
  • Parameters:
    • strategy_id (path, required, UUID)
  • Request body: none
  • Response 200: StrategyResponse with updated deployment_phase and (for live promotion) deployment_ramp_pct = 10
Promotion order: backtest → paper → shadow → live. Backtest→paper is gated; paper→shadow and shadow→live require manual approval + operator intent.

Strategy Health & Capacity

GET /strategy/health

Get current health snapshot of all 6 signal types (latest daily).
  • Parameters: none
  • Response 200:
Alerts flag signal types where days_until_gate_failure < 180 (warning) or < 30 (critical).

GET /strategy/health//history

Get 90-day (or custom) health history for a single signal type.
  • Parameters:
    • signal_type (path, required): Signal type name
    • days (query, optional, default=90, max=365): Lookback window in days
  • Response 200:

GET /strategy/capacity

Get capacity estimate: current utilization, max capital before Sharpe degrades to 1.0, binding constraint.
  • Parameters: none
  • Response 200:
Analyzes 90-day backtest trades to estimate where slippage scales linearly with capital and pushes Sharpe below 1.0.

Strategy Pause/Resume (Trade Execution)

GET /trade/strategies/pauses

List all paused strategies (whether paused by session or indefinitely).
  • Parameters: none
  • Response 200: StrategyPauseListResponse

POST /trade/strategies//pause

Pause a strategy (session or indefinite).
  • Parameters:
    • strategy_id (path, required, UUID)
  • Request body: PauseStrategyRequest | null
  • Response 200: StrategyPauseResponse

DELETE /trade/strategies//pause

Resume a paused strategy.
  • Parameters:
    • strategy_id (path, required, UUID)
  • Response 204: No content (shape inferred from handler — likely returns {status: "resumed"} or similar)

Strategy Matching & Recommendation

GET /stocks//strategies

Get matching trading strategies for a symbol based on current market conditions.
  • Parameters:
    • symbol (path, required): Stock ticker (e.g. “NVDA”)
  • Response 200: StrategyMatchResponse
Returns a hardcoded strategy dict (not graph-based) evaluated against real-time indicators (RSI, IV percentile, trend stack, volume, etc.). Includes match score (0-1), direction (bullish/bearish/neutral), and requirement status for each match.

Internal Acceptance & Registry

The following endpoints are for operator/QA only (/api/internal/... require X-Internal-Secret):

Key Schemas

StrategyRules

The core rule-engine encoding for entry and exit logic.

RuleCondition (Entry/Exit Condition)

Encodes a single decision rule: compare a source value (indicator, price, graph field, etc.) against an operator and a value.
  • id (string | null): Stable canvas node ID (auto-assigned on first open, max 64 chars)
  • source (ConditionSource): Where the value comes from
    • indicator: Named technical indicator (RSI, MACD, ATR, EMAs, BBands, etc.)
    • mse_signal: Real-time signal from Market Signal Engine
    • price_action: Price/VWAP/pivots
    • volume: Volume profile, bar volume, relative volume
    • options: Options-derived (IV percentile, put/call ratios, unusual activity)
    • graph_field: FalkorDB stock attribute (e.g. graph_field.iv_percentile_30d)
    • stop_loss: Meta-condition for stop-loss rules (used in exit_groups; see StopLossConfig)
    • time_exit: Time-of-day exit (HH:MM ET)
  • indicator (string | null): Indicator name when source=indicator (e.g. “rsi_14”, “macd_12_26”, “atr_14”)
  • field (string | null): Field name when source=price_action or graph_field (e.g. “close”, “vwap”, “iv_percentile_30d”)
  • operator (Operator): Comparison operator
    • gt, gte, lt, lte: Numeric comparison
    • eq, neq: Equality
    • in, not_in: List membership
    • crosses_above, crosses_below: Crossing detection (requires 2-bar history)
  • value (float | int | string | list | null): RHS of comparison. For in/not_in, must be a list. For crosses_above/below, can be null (use ref instead).
  • ref (string | null): Alternative RHS: resolves to another indicator/field value
    • Format: indicator.<name>.<key> (e.g. indicator.rsi_14) or price.<field> (e.g. price.vwap) or graph_field.<field>
  • ref_offset (RefOffset | null): Arithmetic offset applied to ref (PR-3 feature, #944)
    • op: + or -
    • coef: Scaling factor (e.g. 2.0 for 2× ATR)
    • ref: Offset value (e.g. indicator.atr_14)
    • Resolves to: base_ref ± coef * offset_ref (e.g. price.vwap + 2.0 * indicator.atr_14)
  • params (object | null): Indicator-specific params (e.g. {period: 14, threshold: 0.7})
  • type (string | null): Semantic type hint for canvas rendering (e.g. “overbought”, “breakout”)
  • update_frequency (string | null): How often the condition is evaluated (“tick”, “bar”, “daily”, etc.)
  • staleness_warn_sec (integer | null): Alert if condition value is older than N seconds

RiskControls

Position sizing, stop-loss configuration, and portfolio limits.
StopLossConfig types (discriminated union):
  • atr: ATR-based trailing stop. Params: multiplier (number)
  • trailing: Activates after return threshold; locks in gains. Params: atr_multiple, activation_r
  • target: Exit when profit reaches N ATRs. Params: target_atr (number)
  • conviction_drop: Exit if entry conviction signal drops below threshold. Params: threshold (number)
  • regime_flip: Exit if market regime shifts to hostile (e.g. from BULLISH to VOLATILE_SELLOFF). Params: exit_regimes (list of regime names)
  • time: Exit at fixed ET time-of-day (EOD, etc.). Params: time_et (HH:MM string)

UniverseConfig

Defines which symbols/sectors a strategy trades.

ContractSelectionConfig

Rule-based or specific contract picker for options strategies. RuleBasedContractConfig (parameterized rules):
SpecificContractConfig (explicit list):

CanvasLayoutPersisted

Visual canvas state (node positions, viewport, active group).
Node IDs: <group_id>:<condition_index> for conditions, stoploss:<index> for stops. Columns are: signal, filter, hub, exit.

StrategyCreate

Request to POST /strategies.

StrategyResponse

Returned by GET/PUT/POST (all CRUD + promote).

StrategyMatchResponse

Returned by GET /stocks//strategies. Hardcoded strategy dict evaluated against real-time indicators.

Enumerations

Instrument: stocks, options, both Timeframe: scalping, intraday, swing Archetype: mean_reversion, trend_following, momentum, volatility, custom AutomationLevel: monitor (alerts only), supervised (requires approval), autonomous (self-executing) DeploymentPhase: backtest, paper, shadow, live ConditionSource: indicator, mse_signal, price_action, volume, options, graph_field, stop_loss, time_exit Operator: gt, gte, lt, lte, eq, neq, in, not_in, crosses_above, crosses_below

Example Full Strategy JSON


Notes for Strategy Engineers

  • Preset rules: When creating with archetype != custom and empty entry_groups, the API injects rules from ARCHETYPE_PRESETS (e.g., momentum archetype gets RSI 70/30 + volume filters). Caller’s risk_controls (sizing, position limits) are preserved; only stop losses are merged if not already present.
  • Versioning: Strategy versions are snapshots in the strategy_versions table, keyed on (strategy_id, version). Incremented whenever rules or risk_controls change (via PUT). Query strategy_versions to audit rule evolution.
  • Canvas persistence: Node positions, viewport zoom, and active group are stored in canvas_layout JSONB. IDs are stable across edits (auto-assigned on first open if missing).
  • Rule validation: All rules are validated at the Pydantic layer (bounds on list lengths, string lengths, numeric ranges) and then by RuleValidator (semantic checks: at least one entry, at least one exit, no cross-references to missing indicators).
  • Phase gates: Backtest→paper gates are automated (oos_sharpe_pooled ≥ 1.0, regime diversity, etc.). Paper→shadow and shadow→live require human approval + operator intent.
  • Backtests: Strategies are tested on-the-fly (no separate tape rebuild needed) by the backtest engine, which sources market_data_1min and aggregates to the requested timeframe. Results are persisted in strategy_backtest_results with metrics (Sharpe, win rate, drawdown, regime breakdown, equity curve).