{
  "admission_notes": [
    {
      "detail_refs": [
        "condition:fixed_targets",
        "condition:trailing_stop",
        "condition:eod_flatten"
      ],
      "id": "protective-policy-placement",
      "text": "Protective exit policies belong directly in exit rules, not under Boolean combinators. fixed_targets with only time_stop_bars is a predicate and may be combined."
    },
    {
      "detail_refs": [
        "condition:at_time",
        "condition:at_session",
        "condition:calendar_schedule"
      ],
      "id": "current-rule-scheduling",
      "text": "Clock schedules retain current role/nesting admission; there is no separate rule schedule slot."
    },
    {
      "detail_refs": [
        "value_ref:entry_bar",
        "value_ref:live_position",
        "value_ref:tracked"
      ],
      "id": "position-context",
      "text": "Position-scoped operands need a position context; a signal scan does not provide one."
    },
    {
      "detail_refs": [
        "config:allocation",
        "config:portfolio_allocation",
        "portfolio:create",
        "portfolio:update"
      ],
      "id": "collection-authoring",
      "text": "Basket instruments share one strategy definition; portfolios combine member strategies. Allocation uses construction.kind and rebalance.kind. Manual weights belong only in construction. Portfolio updates use a patch: omitted fields preserve, allocation null clears, shared_signals [] clears. Construction-managed rotation refuses member entry/gate/exit/protective logic. Member rotation retains member logic but may trim and top up holdings. Member rotations require partitioned capital; cash reserves are refused on rotations. Portfolio walk-forward has no parameter optimization. Published structure does not replace mode-specific allocation admission or compiled-member plan checks."
    },
    {
      "detail_refs": [
        "config:execution",
        "config:allocation"
      ],
      "id": "narrow-consumer-schemas",
      "text": "Execution price and allocation score positions have narrower schemas than ValueRef."
    }
  ],
  "catalog": [
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "composition"
      ],
      "construct_with": "add_rule",
      "description": "Logical AND -- all child conditions must be true.",
      "discriminator": "kind",
      "families": [
        "combinators"
      ],
      "incompatibilities": [],
      "kind": "combinator",
      "legacy_refs": [
        "all_of",
        "combinator:all_of"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "condition",
              "combinator"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "This object composes nested conditions."
        }
      ],
      "name": "all_of",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "ref": "condition:all_of",
      "requires_state": [],
      "schema_etag": "sha256:dfcc4157738a5dadb862813389e15c3cf7641074e3c08b1695af1cd54189ddb0"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "composition"
      ],
      "construct_with": "add_rule",
      "description": "Always true -- fires on every bar. Use as a no-op placeholder or unconditional trigger.",
      "discriminator": "kind",
      "families": [
        "combinators"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "always_true"
      ],
      "links": [],
      "name": "always_true",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "ref": "condition:always_true",
      "requires_state": [],
      "schema_etag": "sha256:5659c4b5d2db168d93c93e614a483543a567985652a4a2572ac471ba88634f80"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "composition"
      ],
      "construct_with": "add_rule",
      "description": "Logical OR -- at least one child condition must be true.",
      "discriminator": "kind",
      "families": [
        "combinators"
      ],
      "incompatibilities": [],
      "kind": "combinator",
      "legacy_refs": [
        "any_of",
        "combinator:any_of"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "condition",
              "combinator"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "This object composes nested conditions."
        }
      ],
      "name": "any_of",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "ref": "condition:any_of",
      "requires_state": [],
      "schema_etag": "sha256:dde6a0be3ce2054a08cfdd199eb60fa8a4d4d8285c71995d44db3840d5f247d2"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "composition"
      ],
      "construct_with": "add_rule",
      "description": "At least N of M conditions true on same bar \u2014 e.g. 3 of [CCI < -100, Donchian lower touch, volume spike, bullish divergence, hammer candle]",
      "discriminator": "kind",
      "families": [
        "temporal"
      ],
      "incompatibilities": [],
      "kind": "combinator",
      "legacy_refs": [
        "at_least",
        "combinator:at_least"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "condition",
              "combinator"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "This object composes nested conditions."
        }
      ],
      "name": "at_least",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry"
      ],
      "ref": "condition:at_least",
      "requires_state": [],
      "schema_etag": "sha256:1c9fa693a0f1abd438ca058d1ac612bf4e2b8f6ee9e36357594da97bdd149419"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "edge_trigger",
        "time_window"
      ],
      "construct_with": "add_rule",
      "description": "Execute N minutes after the session open or before the session close, on every session (anchor:open|close, offset_minutes: int >= 0 after the open, <= 0 before the close; -5 with close = five minutes before the close, half-days resolved against that date's real close). Schedules the decision at that instant and fills from the 1-minute execution clock, on ANY timeframe. The rule is evaluated ONLY then and places a market order, so other conditions on it are sampled at that moment; never put a protective exit on one. Equity only: refused for crypto (24h sessions have no open or close; use at_time). Only an entry or an exit trigger, alone or under all_of.",
      "discriminator": "kind",
      "families": [
        "time_and_events"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "at_session"
      ],
      "links": [],
      "name": "at_session",
      "nested_under_combinator": "conditional",
      "placement_guidance": "Schedule admission permits an entry/exit root or an all_of-only path; other nesting and signal scans are refused. Session requirements still apply.",
      "recommended_roles": [
        "entry",
        "exit"
      ],
      "ref": "condition:at_session",
      "requires_state": [],
      "schema_etag": "sha256:16e6200b468f9a2db9daefb4f3edd2919af3d38bd77c5247a9ace801817753c7"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "edge_trigger",
        "time_window"
      ],
      "construct_with": "add_rule",
      "description": "Execute at a specific clock time (e.g. 'buy at 10:16'). Time is HH:MM in the exchange session timezone. Schedules the decision at that instant and fills from the 1-minute execution clock, so the time is exact on ANY strategy timeframe -- daily included. The rule is evaluated ONLY then, so other conditions on it are sampled at that moment; never put a protective exit on one. A time outside that date's session (15:30 on a 13:00 half-day) simply does not occur that day, so an exit on one holds the position instead of firing.",
      "discriminator": "kind",
      "families": [
        "time_and_events"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "at_time"
      ],
      "links": [],
      "name": "at_time",
      "nested_under_combinator": "conditional",
      "placement_guidance": "Schedule admission permits an entry/exit root or an all_of-only path; other nesting and signal scans are refused. Session requirements still apply.",
      "recommended_roles": [
        "entry",
        "exit"
      ],
      "ref": "condition:at_time",
      "requires_state": [],
      "schema_etag": "sha256:0b24b91b4b46d0e4f08f26ba695700e3afe38241a10a436cc40753e8e74c5933"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "breakout",
        "edge_trigger",
        "reentry",
        "stateful"
      ],
      "construct_with": "add_rule",
      "description": "Breakout followed by pullback retest",
      "discriminator": "kind",
      "families": [
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "breakout_retest"
      ],
      "links": [],
      "name": "breakout_retest",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry"
      ],
      "ref": "condition:breakout_retest",
      "requires_state": [],
      "schema_etag": "sha256:76cc5e80d6e2ac2a4ba73c95502f6e2683c0dc15e66c401dc00a6ebac588ac23"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "recurring_schedule"
      ],
      "construct_with": "add_rule",
      "description": "Periodic schedule (daily, weekly, monthly). Also the way to trigger once at an exact wall-clock time in a named timezone (time + tz, e.g. every='1d', time='10:30', tz='America/New_York'), including on 24/7 assets.",
      "discriminator": "kind",
      "families": [
        "time_and_events"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "calendar_schedule"
      ],
      "links": [],
      "name": "calendar_schedule",
      "nested_under_combinator": "conditional",
      "placement_guidance": "Schedule admission permits an entry/exit root or an all_of-only path; other nesting and signal scans are refused. Session requirements still apply.",
      "recommended_roles": [
        "entry",
        "exit"
      ],
      "ref": "condition:calendar_schedule",
      "requires_state": [],
      "schema_etag": "sha256:55cb949c3680c967f4ab915ed5d5691ac8e0a40de9fa4b171454026e84fd50d0"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [],
      "construct_with": "add_rule",
      "description": "Candlestick patterns (bullish_engulfing, bearish_engulfing, hammer, doji, morning_star, three_white_soldiers, etc. \u2014 see full enum via builder_discover(action='get', ref='condition:candle_pattern'))",
      "discriminator": "kind",
      "families": [
        "patterns"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "candle_pattern"
      ],
      "links": [],
      "name": "candle_pattern",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry"
      ],
      "ref": "condition:candle_pattern",
      "requires_state": [],
      "schema_etag": "sha256:6ae26ec4c2e27aa334470d5162a80187ec2220163e8e8f18a424567d4beb462d"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "level_state"
      ],
      "construct_with": "add_rule",
      "description": "LEVEL comparison on continuous values: left op right, true every bar the relation holds. USE WHEN: gating on a sustained condition (e.g. close > SMA(200), RSI < 30 throughout the consolidation). DO NOT USE for one-shot edge events \u2014 use 'cross' to fire once on the crossing bar. DO NOT USE for membership in a discrete set \u2014 use 'in_set'. For named zones inspect builder_discover(action='get', ref='workflow:named_anchor_zone'); for anchor fields use value_ref:anchor.",
      "discriminator": "kind",
      "families": [
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "compare",
        "pattern:named_zone_compare"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "One or more fields accept typed value references."
        },
        {
          "kind": "detail",
          "reason": "Saved named zones can be used as operands.",
          "ref": "workflow:named_anchor_zone"
        }
      ],
      "name": "compare",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "ref": "condition:compare",
      "requires_state": [],
      "schema_etag": "sha256:b0633af5c57703c3a70af461e090c18cdb9581562611e4d27971083f309e01d9"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "resource",
      "binding_only": true,
      "capabilities": [],
      "construct_with": "add_rule",
      "description": "Owned reference to a saved definition: {kind: condition_ref, definition_id: ...}. Use it as an ordinary child in composition. It binds before compilation; the target must belong to this strategy, exist, and satisfy its placement context.",
      "discriminator": "kind",
      "families": [
        "custom_structures"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "condition_ref"
      ],
      "links": [],
      "name": "condition_ref",
      "nested_under_combinator": "conditional",
      "placement_guidance": "Placement is checked after binding the referenced owned source.",
      "recommended_roles": [],
      "ref": "condition:condition_ref",
      "requires_state": [],
      "schema_etag": "sha256:7292c74830ad45f90ea457ae60203b52154c36bc573a200b5bd7ab9253c2849a"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "stateful"
      ],
      "construct_with": "add_rule",
      "description": "Condition true for N consecutive bars (or N of M with strict=false) \u2014 e.g. close > SMA(100) for 5 consecutive bars. The window INCLUDES the current bar, so for 'X now but not in the preceding N bars' use window_bars=N+1 with min_true=2; window_bars=N with min_true=1 can never fire alongside X",
      "discriminator": "kind",
      "families": [
        "temporal"
      ],
      "incompatibilities": [],
      "kind": "combinator",
      "legacy_refs": [
        "consecutive",
        "combinator:consecutive"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "condition",
              "combinator"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "This object composes nested conditions."
        }
      ],
      "name": "consecutive",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "exit"
      ],
      "ref": "condition:consecutive",
      "requires_state": [],
      "schema_etag": "sha256:b1dfabfeffc31bc01138c6224ca447f66844ebfa1e4d4815b8b315562ab60017"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "edge_trigger"
      ],
      "construct_with": "add_rule",
      "description": "EDGE event on continuous values: fires once on the bar where left crosses right (was below/above, now the other side). USE WHEN: price crosses a moving average, indicator crosses a level (e.g. RSI crosses 30), Stochastic K crosses D. DO NOT USE for discrete/categorical refs like supertrend.direction ({-1,+1}) \u2014 use 'transition' instead. DO NOT USE when you want every bar the relation holds \u2014 use 'compare' for level/state semantics. For named zones inspect builder_discover(action='get', ref='workflow:named_anchor_zone').",
      "discriminator": "kind",
      "families": [
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "cross",
        "pattern:named_zone_cross"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "One or more fields accept typed value references."
        },
        {
          "kind": "detail",
          "reason": "Saved named zones can be used as operands.",
          "ref": "workflow:named_anchor_zone"
        }
      ],
      "name": "cross",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "exit"
      ],
      "ref": "condition:cross",
      "requires_state": [],
      "schema_etag": "sha256:5836b689d7387cc18eebfbbca47881c4f7a4b5a7823bb1b91cc782e82ec74af1"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "position_policy",
      "binding_only": false,
      "capabilities": [
        "exit_management",
        "time_window"
      ],
      "construct_with": "add_rule",
      "description": "End-of-day flatten exit: the position is flat from N minutes before the session close until the close. At close - N (resolved against the DATE's real close, so a half-day flattens early instead of being missed) it closes the position and cancels any resting entry; entries decided in the window are skipped as policy:eod_flat_window. A daily/hourly entry filling at the open is flattened the same session. A scheduled entry at or after close - N is refused at compile. Attach it as its own exit. Equity only: refused for crypto (24h sessions have no close).",
      "discriminator": "kind",
      "families": [
        "time_and_events"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "eod_flatten"
      ],
      "links": [],
      "name": "eod_flatten",
      "nested_under_combinator": "forbidden",
      "placement_guidance": "Pass directly to add_rule(role='exit'). eod_flatten (flat before the close) cannot sit inside 'any_of': eod_flatten is a policy on the position (a resting order or a flat window), not a true/false condition, so 'any_of' would have no effect on it and the policy would apply unconditionally. Attach the policy definition directly as its own exit rule, and attach the conditional exit as a separate exit rule.",
      "recommended_roles": [
        "exit"
      ],
      "ref": "condition:eod_flatten",
      "requires_state": [],
      "schema_etag": "sha256:810effbcb16046720bd87a3e9d5294befe4641115b244ec544e0227048c4141a"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "position_policy",
      "binding_only": false,
      "capabilities": [
        "exit_management"
      ],
      "construct_with": "add_rule",
      "description": "Fixed stop-loss / take-profit / time-stop (supports take_profit_tiers for staged partial exits)",
      "discriminator": "kind",
      "families": [
        "risk_management"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "fixed_targets"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "One or more fields accept typed value references."
        }
      ],
      "name": "fixed_targets",
      "nested_under_combinator": "conditional",
      "placement_guidance": "With only time_stop_bars, this is a predicate and may be composed. With stop-loss or take-profit orders, it is a protective policy: attach it directly in an exit rule, outside combinators.",
      "recommended_roles": [
        "exit"
      ],
      "ref": "condition:fixed_targets",
      "requires_state": [
        "live_position"
      ],
      "schema_etag": "sha256:cc2c36ff6472c792221ef5105270f9989d94a8f27dbefa5f838a46998210cccf"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "breakout"
      ],
      "construct_with": "add_rule",
      "description": "Flag chart pattern (momentum + consolidation + breakout)",
      "discriminator": "kind",
      "families": [
        "patterns"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "flag_pattern"
      ],
      "links": [],
      "name": "flag_pattern",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry"
      ],
      "ref": "condition:flag_pattern",
      "requires_state": [],
      "schema_etag": "sha256:ae34e10424b52db8840e383d59ea78fd99cf94cfb8b766a8d44fd03491253d82"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [],
      "construct_with": "add_rule",
      "description": "Fair Value Gap -- 3-candle imbalance zones",
      "discriminator": "kind",
      "families": [
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "fvg"
      ],
      "links": [],
      "name": "fvg",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry"
      ],
      "ref": "condition:fvg",
      "requires_state": [],
      "schema_etag": "sha256:d7604360ae8f1e77b03ba1467e0319b40e31c1cd9b2aacd0750ae0741dbae4f2"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "discrete_transition",
        "level_state"
      ],
      "construct_with": "add_rule",
      "description": "LEVEL membership on discrete/categorical values: true every bar value \u2208 members (or its negation). USE WHEN: gating on SuperTrend direction == +1, regime label in {bull, neutral}. DO NOT USE on continuous values \u2014 use 'compare' instead. Cleaner than anyOf(compare(value == m) ...). The discrete-valued counterpart to 'compare'.",
      "discriminator": "kind",
      "families": [
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "in_set"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "One or more fields accept typed value references."
        }
      ],
      "name": "in_set",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "gate"
      ],
      "ref": "condition:in_set",
      "requires_state": [],
      "schema_etag": "sha256:d77edb3253d55adc4a746802995be0e1b95e8953347aa85d6e2a1963d95364f9"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "composition",
        "edge_trigger",
        "stateful"
      ],
      "construct_with": "add_rule",
      "description": "EDGE with memory: true on the one close where `fire` holds after `arm` held on an earlier close, then disarmed. USE WHEN an event must follow a precondition \u2014 price re-enters a band after leaving it (arm=outside, fire=inside), first touch of a level after being clear of it, a rising edge of any condition (arm=not(c), fire=c). `arm` wins if both are true on one close; if either side has no value the result has none and the latch keeps its state. Never reset by positions. Children are inline conditions or condition_refs; it cannot hold a schedule or a stop/target. DO NOT USE for a plain level \u2014 use 'compare'.",
      "discriminator": "kind",
      "families": [
        "temporal"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "latch"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "condition",
              "combinator"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "This object composes nested conditions."
        }
      ],
      "name": "latch",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "ref": "condition:latch",
      "requires_state": [],
      "schema_etag": "sha256:3e58e79e5e61d8b128239ed95c41c44d57310c49e12452e9d675a48b6d52981f"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "edge_trigger"
      ],
      "construct_with": "add_rule",
      "description": "Sweep below support then reclaim",
      "discriminator": "kind",
      "families": [
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "liquidity_sweep"
      ],
      "links": [],
      "name": "liquidity_sweep",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry"
      ],
      "ref": "condition:liquidity_sweep",
      "requires_state": [],
      "schema_etag": "sha256:14c81072a930764ee7f5f9d7e5c7ca2a55600f4b7b751304f8da5942cb85af26"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "composition"
      ],
      "construct_with": "add_rule",
      "description": "Logical NOT -- inverts the inner condition.",
      "discriminator": "kind",
      "families": [
        "combinators"
      ],
      "incompatibilities": [],
      "kind": "combinator",
      "legacy_refs": [
        "not",
        "combinator:not"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "condition",
              "combinator"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "This object composes nested conditions."
        }
      ],
      "name": "not",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "ref": "condition:not",
      "requires_state": [],
      "schema_etag": "sha256:a707779c6bce9c31f60bc1f42a0540eda7f4b158d03eb6607d16d7181b16bfe4"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [],
      "construct_with": "add_rule",
      "description": "Order Block -- institutional S/R zone",
      "discriminator": "kind",
      "families": [
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "order_block"
      ],
      "links": [],
      "name": "order_block",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry"
      ],
      "ref": "condition:order_block",
      "requires_state": [],
      "schema_etag": "sha256:145617a8d9c2b6800c311975c7b7f0c1e36ebedca87e411abc4e4bec399921c7"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [],
      "construct_with": "add_rule",
      "description": "OTE -- Fibonacci retracement zone",
      "discriminator": "kind",
      "families": [
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "ote"
      ],
      "links": [],
      "name": "ote",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry"
      ],
      "ref": "condition:ote",
      "requires_state": [],
      "schema_etag": "sha256:2645a8c707358890939cf0561f15d05e9dc7cee74aebb9100eab6bc8353bc212"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "breakout"
      ],
      "construct_with": "add_rule",
      "description": "Pennant chart pattern",
      "discriminator": "kind",
      "families": [
        "patterns"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "pennant_pattern"
      ],
      "links": [],
      "name": "pennant_pattern",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry"
      ],
      "ref": "condition:pennant_pattern",
      "requires_state": [],
      "schema_etag": "sha256:160a638c87153855b61e10a431de981889414cdb7f1b7aa782689b3ae1471cb2"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "level_state"
      ],
      "construct_with": "add_rule",
      "description": "LEVEL interval on continuous values: true every bar low <= subject <= high, with EACH bound's inclusivity set separately \u2014 low_inclusive and high_inclusive are BOTH REQUIRED, because the two two-bound sites this replaces disagree (band_level inside is exclusive on both edges, zone membership is inclusive on both), so any default would be a silent choice between them. USE WHEN: 'RSI between 30 and 70', 'price inside the Bollinger band', any half-open window like [30, 70) that a single flag cannot express. Bounds may be signal refs, not just constants, so they can be moving series. DO NOT USE for a one-sided threshold \u2014 use 'compare'. DO NOT USE for membership in a discrete set \u2014 use 'in_set'. A literal interval that is empty (low above high, or equal bounds with an exclusive end) is refused at construction rather than shipped as a strategy that never fires.",
      "discriminator": "kind",
      "families": [
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "range"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "One or more fields accept typed value references."
        }
      ],
      "name": "range",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "ref": "condition:range",
      "requires_state": [],
      "schema_etag": "sha256:ba23340bd41b86ac2b36f9e5db24a0d50d7bcce5bdf2cd985b9566aa4d8ba74a"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "composition",
        "sequence",
        "stateful"
      ],
      "construct_with": "add_rule",
      "description": "Ordered sequence -- steps must fire in order, each optionally within N bars.",
      "discriminator": "kind",
      "families": [
        "combinators"
      ],
      "incompatibilities": [],
      "kind": "combinator",
      "legacy_refs": [
        "sequence",
        "combinator:sequence"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "One or more fields accept typed value references."
        },
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "condition",
              "combinator"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "This object composes nested conditions."
        }
      ],
      "name": "sequence",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "ref": "condition:sequence",
      "requires_state": [],
      "schema_etag": "sha256:57a62e3974a9f32f469ca340ba8737f94bcc32e762d6eb0287a1596fef0419ab"
    },
    {
      "altitude": "pair",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "relative_value"
      ],
      "construct_with": "add_rule",
      "description": "Spread between two instruments (ratio, difference, log_ratio, zscore)",
      "discriminator": "kind",
      "families": [
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "spread"
      ],
      "links": [],
      "name": "spread",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry"
      ],
      "ref": "condition:spread",
      "requires_state": [],
      "schema_etag": "sha256:66ed9b34fdcb8c5a20ad841294866b77534a9555116c5ef288ed3502ba93cab2"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "position_policy",
      "binding_only": false,
      "capabilities": [
        "exit_management",
        "stateful"
      ],
      "construct_with": "add_rule",
      "description": "Trailing stop from the extreme price since entry; trail distance is either an ATR multiple (atr_multiplier) or a percent (trailing_pct)",
      "discriminator": "kind",
      "families": [
        "risk_management"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "trailing_stop"
      ],
      "links": [],
      "name": "trailing_stop",
      "nested_under_combinator": "forbidden",
      "placement_guidance": "Pass directly to add_rule(role='exit'). trailing_stop cannot sit inside 'any_of': trailing_stop is a policy on the position (a resting order or a flat window), not a true/false condition, so 'any_of' would have no effect on it and the policy would apply unconditionally. Attach the policy definition directly as its own exit rule, and attach the conditional exit as a separate exit rule.",
      "recommended_roles": [
        "exit"
      ],
      "ref": "condition:trailing_stop",
      "requires_state": [
        "live_position"
      ],
      "schema_etag": "sha256:83c1313707fc96a0341d085aa7c9924c5b8dc970a8e564ef258980d6bbe55998"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [
        "entry",
        "exit",
        "gate"
      ],
      "authority": "signal",
      "binding_only": false,
      "capabilities": [
        "discrete_transition",
        "edge_trigger",
        "stateful"
      ],
      "construct_with": "add_rule",
      "description": "EDGE event on discrete/categorical values: fires once on the bar where ref's value differs from the prior bar (optionally constrained to a (from, to) pair). USE WHEN: SuperTrend direction flips (-1 \u2192 +1), regime label changes, any small-set categorical ref changes value. DO NOT USE on continuous values like price or RSI \u2014 use 'cross' for those. The discrete-valued counterpart to 'cross'.",
      "discriminator": "kind",
      "families": [
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "condition",
      "legacy_refs": [
        "transition"
      ],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "One or more fields accept typed value references."
        }
      ],
      "name": "transition",
      "nested_under_combinator": "allowed",
      "placement_guidance": "Predicate/combinator source may be nested; child and context admission still applies.",
      "recommended_roles": [
        "entry",
        "exit"
      ],
      "ref": "condition:transition",
      "requires_state": [],
      "schema_etag": "sha256:b1824087586592f92b84bfc7e66ce905c2739fe1d5f092ab6f8cfa47a9ef0e91"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "builder_set_allocation",
      "description": "Public basket allocation and collection-risk authoring contract.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this exact public allocation mode.",
          "ref": "config:allocation:equal_weight"
        },
        {
          "kind": "detail",
          "reason": "Inspect this exact public allocation mode.",
          "ref": "config:allocation:manual"
        },
        {
          "kind": "detail",
          "reason": "Inspect this exact public allocation mode.",
          "ref": "config:allocation:rank_based"
        },
        {
          "kind": "detail",
          "reason": "Inspect this exact public allocation mode.",
          "ref": "config:allocation:signal_proportional"
        }
      ],
      "name": "allocation",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "config:allocation",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:3171c9d1d21b59d75137aab8e8d3cb232afee4b49d16e0e35cee0ba0d57229cc",
      "setter": "builder_set_allocation"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "builder_set_allocation",
      "description": "equal_weight public basket-allocation mode.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [],
      "name": "allocation.equal_weight",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "config:allocation:equal_weight",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:0323f9e8d189c8920524f21d0252ec8062a736fb954b1d1cecb353081f3458e8",
      "setter": "builder_set_allocation"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "builder_set_allocation",
      "description": "manual public basket-allocation mode.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [],
      "name": "allocation.manual",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "config:allocation:manual",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:002dff2f2813256206a31dfca54f5bb2f85c4917c287539f33b01e78cc6a60e0",
      "setter": "builder_set_allocation"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "builder_set_allocation",
      "description": "rank_based public basket-allocation mode.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [],
      "name": "allocation.rank_based",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "config:allocation:rank_based",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:ca2e625310fdd405dc9f0b65794826fd68499d0e0b40d7e9e5359b84e9a6e797",
      "setter": "builder_set_allocation"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "builder_set_allocation",
      "description": "signal_proportional public basket-allocation mode.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [],
      "name": "allocation.signal_proportional",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "config:allocation:signal_proportional",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:381b8da57be2e11385bf4a068b949182a99bd8cae0aa7f3778b5812e4d571328",
      "setter": "builder_set_allocation"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "create_portfolio",
      "description": "Typed portfolio/collection authoring contract. See allocation admission and compiled-member plan checks for mode restrictions.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect portfolio allocation policy.",
          "ref": "config:portfolio_allocation"
        }
      ],
      "name": "config.collection_risk",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "config:collection_risk",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:d33a68d32ce92e377516d36686d87ea97db63424740a45ff056926558f82385d",
      "setter": "create_portfolio"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "create_portfolio",
      "description": "Typed portfolio/collection authoring contract. See allocation admission and compiled-member plan checks for mode restrictions.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect portfolio allocation policy.",
          "ref": "config:portfolio_allocation"
        }
      ],
      "name": "config.construction_constraints",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "config:construction_constraints",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:1e3379f972b564acac6bd446ace19cf979fa5fbb8149f1b90fe2313aa08ee2e3",
      "setter": "create_portfolio"
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "execution",
      "capabilities": [
        "execution"
      ],
      "construct_with": "builder_set_strategy_config",
      "description": "Order placement configuration. Refused: a non-market order type with both a long and a short entry group (bidirectional entries are market-only).",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [
        {
          "incompatible_with": {
            "entry.groups": "bidirectional"
          },
          "reason": "A bidirectional strategy (one long entry group plus one short) currently requires order_type='market'; non-market entry orders are rejected at compile time.",
          "when": {
            "order_type": [
              "limit",
              "stop",
              "stop_limit"
            ]
          }
        },
        {
          "incompatible_with": {
            "entry.groups": "bidirectional"
          },
          "reason": "A bidirectional entry the compiler lowers to an auction order type \u2014 a bare at_time entry on the session open, or an equity stateless-calendar entry \u2014 is rejected; only plain market entries merge across directions.",
          "when": {
            "entry.lowered_order_type": "auction",
            "order_type": "market"
          }
        }
      ],
      "kind": "config",
      "legacy_refs": [],
      "links": [],
      "name": "execution",
      "patch_key": "execution",
      "recommended_roles": [],
      "ref": "config:execution",
      "requires_state": [],
      "schema_etag": "sha256:696702db0def123ea07311131939c73635f7fb3bd66b4d63f0314b9f7ef349fe",
      "setter": "builder_set_strategy_config"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "create_portfolio",
      "description": "Typed portfolio/collection authoring contract. See allocation admission and compiled-member plan checks for mode restrictions.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [],
      "name": "config.portfolio_allocation",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "config:portfolio_allocation",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:03282325bb2386de8672d4a56bc24fbe310eda334970665ff723cd340867513c",
      "setter": "create_portfolio"
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "position_policy",
      "capabilities": [],
      "construct_with": "builder_set_strategy_config",
      "description": "Position accumulation and reversal configuration. Refused: reverse with only one entry direction. accumulate/scale_in alongside both entry groups is allowed; an opposite-side entry fired while the sleeve is invested is skipped (policy:opposite_side_while_invested), because one sleeve cannot hold long and short lots at once.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [],
      "name": "position_policy",
      "patch_key": "position_policy",
      "recommended_roles": [],
      "ref": "config:position_policy",
      "requires_state": [],
      "schema_etag": "sha256:67cf6f3510af221ec6c3a91f57106bf4a6179c16f4bdadac329ffefeb3610d8a",
      "setter": "builder_set_strategy_config"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "create_portfolio",
      "description": "Typed portfolio/collection authoring contract. See allocation admission and compiled-member plan checks for mode restrictions.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect portfolio allocation policy.",
          "ref": "config:portfolio_allocation"
        }
      ],
      "name": "config.rebalance",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "config:rebalance",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:a8ff5ce68d7a86a3744ed8e5b0685e36578a66096edd175afee15e21d608160b",
      "setter": "create_portfolio"
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "risk",
      "capabilities": [],
      "construct_with": "builder_set_strategy_config",
      "description": "Strategy-level risk controls.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [],
      "name": "risk",
      "patch_key": "risk",
      "recommended_roles": [],
      "ref": "config:risk",
      "requires_state": [],
      "schema_etag": "sha256:6477d558cb66e8bc9d0d20f149d5ecfd205eeca9959ae930a5fa631da8fc484c",
      "setter": "builder_set_strategy_config"
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "sizing",
      "capabilities": [],
      "construct_with": "builder_set_strategy_config",
      "description": "Capital-per-trade sizing configuration. pct_equity allocation is 0 < a <= 1.0 (spot only; above 1.0 is leverage and is refused).",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [
        {
          "incompatible_with": {
            "exit.stop": "dynamic_price_ref"
          },
          "reason": "Stop distance is currently derived only from fixed_targets.stop_loss_pct or trailing_stop.",
          "when": {
            "mode": "fixed_risk_pct"
          }
        }
      ],
      "kind": "config",
      "legacy_refs": [],
      "links": [],
      "name": "sizing",
      "patch_key": "sizing",
      "recommended_roles": [],
      "ref": "config:sizing",
      "requires_state": [],
      "schema_etag": "sha256:e9918d533da9c16faf54a5857cefe3cb0a95c6f7fe2d4572850a634c2ecaebca",
      "setter": "builder_set_strategy_config"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "create_portfolio",
      "description": "Typed portfolio/collection authoring contract. See allocation admission and compiled-member plan checks for mode restrictions.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect portfolio allocation policy.",
          "ref": "config:portfolio_allocation"
        }
      ],
      "name": "construction.portfolio",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "construction:portfolio",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:6edb07b21a62e966af50db3965aba26725cc7a66dc89f6efae43c752272db298",
      "setter": "create_portfolio"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "execution",
      "capabilities": [
        "execution"
      ],
      "construct_with": null,
      "consumer_context": "execution",
      "description": "Typed execution-price input for builder_set_execution.",
      "discriminator_value": "anchor",
      "families": [
        "execution"
      ],
      "incompatibilities": [],
      "kind": "execution_price",
      "legacy_refs": [],
      "links": [],
      "name": "anchor",
      "recommended_roles": [],
      "ref": "execution_price:anchor",
      "requires_state": [
        "anchor"
      ],
      "schema_etag": "sha256:4736e464826cf213c6bfa80a758174cc2386bc7928ca8576937278b45974cce2"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "execution",
      "capabilities": [
        "execution"
      ],
      "construct_with": null,
      "consumer_context": "execution",
      "description": "Typed execution-price input for builder_set_execution.",
      "discriminator_value": "atr_offset",
      "families": [
        "execution"
      ],
      "incompatibilities": [],
      "kind": "execution_price",
      "legacy_refs": [],
      "links": [],
      "name": "atr_offset",
      "recommended_roles": [],
      "ref": "execution_price:atr_offset",
      "requires_state": [],
      "schema_etag": "sha256:3cfeb122c1dcd3698c3e438a573ca1c305d8f304ec11fec061078e36e2aa6f21"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "execution",
      "capabilities": [
        "execution"
      ],
      "construct_with": null,
      "consumer_context": "execution",
      "description": "Typed execution-price input for builder_set_execution.",
      "discriminator_value": "named_zone",
      "families": [
        "execution"
      ],
      "incompatibilities": [],
      "kind": "execution_price",
      "legacy_refs": [],
      "links": [],
      "name": "named_zone",
      "recommended_roles": [],
      "ref": "execution_price:named_zone",
      "requires_state": [
        "named_zone"
      ],
      "schema_etag": "sha256:4a769bd7067cb314330e186dd0ee772e847d08465614520562114d44ac9fd9e5"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "execution",
      "capabilities": [
        "execution"
      ],
      "construct_with": null,
      "consumer_context": "execution",
      "description": "Typed execution-price input for builder_set_execution.",
      "discriminator_value": "pct_offset",
      "families": [
        "execution"
      ],
      "incompatibilities": [],
      "kind": "execution_price",
      "legacy_refs": [],
      "links": [],
      "name": "pct_offset",
      "recommended_roles": [],
      "ref": "execution_price:pct_offset",
      "requires_state": [],
      "schema_etag": "sha256:2c37d7e8a2680b67914fa41c384736be7ff3fb315ee8df2d338c742379a9948d"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "execution",
      "capabilities": [
        "execution"
      ],
      "construct_with": null,
      "consumer_context": "execution",
      "description": "Typed execution-price input for builder_set_execution.",
      "discriminator_value": "zone",
      "families": [
        "execution"
      ],
      "incompatibilities": [
        {
          "incompatible_with": {
            "entry.zone_condition.zone_type": "the same zone_type"
          },
          "reason": "The execution-price zone lookup and the entry's zone condition are decoupled registry queries that can resolve to different zones. Use an entry signal that is not a zone condition of the same type, or the triggering-zone execution price.",
          "when": {
            "zone_type": "any"
          }
        }
      ],
      "kind": "execution_price",
      "legacy_refs": [],
      "links": [],
      "name": "zone",
      "recommended_roles": [],
      "ref": "execution_price:zone",
      "requires_state": [],
      "schema_etag": "sha256:53538fcc993fed1c7d407e120df1c01fb488c1831b3b0fdb0aca30b75f186a5d"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "AD emits scalar output with series value.",
      "discriminator_value": "AD",
      "families": [
        "indicators",
        "volume"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:AD"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='ad' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "ad",
      "recommended_roles": [],
      "ref": "indicator_shape:ad",
      "requires_state": [],
      "schema_etag": "sha256:d3592bf81aa5fee4117493073a2ee3ae6bff76a65c6652078f16e1fcd33fad61"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "ADX emits composite output with series value, plus_di, minus_di.",
      "discriminator_value": "ADX",
      "families": [
        "indicators",
        "trend"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:ADX",
        "indicator_shape:ADX_DI",
        "indicator_shape:adx_di"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='adx_di' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "adx",
      "recommended_roles": [],
      "ref": "indicator_shape:adx",
      "requires_state": [],
      "schema_etag": "sha256:6b2a5a11798122e9f9335e90e4de7b5696e01c6d049181624b9733a7562a6270"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "AROON emits composite output with series value, up, down.",
      "discriminator_value": "AROON",
      "families": [
        "indicators",
        "trend"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:AROON"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='aroon' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "aroon",
      "recommended_roles": [],
      "ref": "indicator_shape:aroon",
      "requires_state": [],
      "schema_etag": "sha256:610c31449262ab213d77cf0f4d6d33ab62734e1949dd424c3b50491555e0bd6f"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "ATR emits scalar output with series value.",
      "discriminator_value": "ATR",
      "families": [
        "indicators",
        "volatility"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:ATR"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='atr' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "atr",
      "recommended_roles": [],
      "ref": "indicator_shape:atr",
      "requires_state": [],
      "schema_etag": "sha256:1711a714320174629ff9b2b9493f86676aaa6ccba0725816b78f1eb27ae6dd1f"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "AVWAP emits composite output with series value, std_dev.",
      "discriminator_value": "AVWAP",
      "families": [
        "indicators",
        "price_levels",
        "volume"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:AVWAP"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='avwap' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "avwap",
      "recommended_roles": [],
      "ref": "indicator_shape:avwap",
      "requires_state": [],
      "schema_etag": "sha256:4be94fdf735c19e0fdbaf4f77bc400b16e5cfae4a1604a0cee88cdff692b135c"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "BB emits composite output with series upper, middle, lower, StandardDeviation, BandWidth.",
      "discriminator_value": "BB",
      "families": [
        "indicators",
        "bands",
        "volatility"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:BB",
        "indicator_shape:BOLLINGER",
        "indicator_shape:bollinger"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='bollinger' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "bb",
      "recommended_roles": [],
      "ref": "indicator_shape:bb",
      "requires_state": [],
      "schema_etag": "sha256:2738f3fa07b6da61d978961f1ac30a089462980a68faccbb53f8284f137746f8"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "CANDLESTICK emits scalar output with series value.",
      "discriminator_value": "CANDLESTICK",
      "families": [
        "indicators",
        "patterns"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:CANDLESTICK"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='candlestick' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "candlestick",
      "recommended_roles": [],
      "ref": "indicator_shape:candlestick",
      "requires_state": [],
      "schema_etag": "sha256:32162282810bdc57dfb0a4e1aef48a38c74db261f35ef92cb7f30c362c1e95bf"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "CCI emits scalar output with series value.",
      "discriminator_value": "CCI",
      "families": [
        "indicators",
        "momentum"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:CCI"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='cci' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "cci",
      "recommended_roles": [],
      "ref": "indicator_shape:cci",
      "requires_state": [],
      "schema_etag": "sha256:76545efcf3ba3244acca48ee076732c2897ccfbb7f6e9ef14395af1e79cb0957"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "CMF emits scalar output with series value.",
      "discriminator_value": "CMF",
      "families": [
        "indicators",
        "volume"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:CMF"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='cmf' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "cmf",
      "recommended_roles": [],
      "ref": "indicator_shape:cmf",
      "requires_state": [],
      "schema_etag": "sha256:4e69edffaffe1c27df011ee56a903378ddbc3fcaf26da59f07a23317114a9e68"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "DC emits band output with series upper, middle, lower.",
      "discriminator_value": "DC",
      "families": [
        "indicators",
        "bands",
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:DC",
        "indicator_shape:DONCHIAN",
        "indicator_shape:donchian"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='donchian' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "dc",
      "recommended_roles": [],
      "ref": "indicator_shape:dc",
      "requires_state": [],
      "schema_etag": "sha256:6a290629344c59b5a84a2d744dfdbd2bc6630eed8128d77b1cc0cd5256fd141e"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "EMA emits scalar output with series value.",
      "discriminator_value": "EMA",
      "families": [
        "indicators",
        "trend"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:EMA"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='ema' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "ema",
      "recommended_roles": [],
      "ref": "indicator_shape:ema",
      "requires_state": [],
      "schema_etag": "sha256:5f0bc0ec0a0a438eccf5f5889fbbd7c70e228589481071e9c81846b652a4f367"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "GAP emits scalar output with series value.",
      "discriminator_value": "GAP",
      "families": [
        "indicators",
        "momentum",
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:GAP"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='gap' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "gap",
      "recommended_roles": [],
      "ref": "indicator_shape:gap",
      "requires_state": [],
      "schema_etag": "sha256:1a0e69cdee33c6a7a4efd937fe977efdab09d01ab2dfac48bca6cfa569c409e4"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "KC emits band output with series upper, middle, lower.",
      "discriminator_value": "KC",
      "families": [
        "indicators",
        "bands",
        "volatility"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:KC",
        "indicator_shape:KELTNER",
        "indicator_shape:keltner"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='keltner' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "kc",
      "recommended_roles": [],
      "ref": "indicator_shape:kc",
      "requires_state": [],
      "schema_etag": "sha256:fa33e2f7677c536dc7651d690e19e12ec1c85e8bc8cdc5ab0b4cdaf7ce5a2abb"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "MACD emits composite output with series value, signal, histogram.",
      "discriminator_value": "MACD",
      "families": [
        "indicators",
        "momentum",
        "trend"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:MACD",
        "indicator_shape:MACD_SIGNAL",
        "indicator_shape:macd_signal",
        "indicator_shape:MACD_HISTOGRAM",
        "indicator_shape:macd_histogram"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as one of indicator='macd', 'macd_signal', 'macd_histogram' (value_ref:indicator) -- one series per reference.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "macd",
      "recommended_roles": [],
      "ref": "indicator_shape:macd",
      "requires_state": [],
      "schema_etag": "sha256:2cf25d96e6e93ccf8aeba3efb59756e3c12047c442c6dd899499029499c47fdc"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "INTERNAL PLUMBING -- not selectable. MAX emits scalar output with series value. This shape is an engine building block for other handlers and is absent from the `indicator` enum on `value_ref:indicator`, so it cannot be referenced from a strategy. Use `rolling_max` (RollingMaxValueRef) instead.",
      "discriminator_value": "MAX",
      "families": [
        "indicators"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:MAX"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Engine-internal shape: NOT selectable through an indicator value reference. It is computed for other handlers, not referenced directly.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "max",
      "recommended_roles": [],
      "ref": "indicator_shape:max",
      "requires_state": [],
      "schema_etag": "sha256:68db028ee337218e5ec59c804a9451fc413e6d5c06b455426058bb254cdf3cb3"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "MEDIAN emits scalar output with series value.",
      "discriminator_value": "MEDIAN",
      "families": [
        "indicators",
        "trend"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:MEDIAN"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='median' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "median",
      "recommended_roles": [],
      "ref": "indicator_shape:median",
      "requires_state": [],
      "schema_etag": "sha256:9f2f0645fbc63a6599216db394f7de81fbba16dba3cd3871e4dded9ff665f284"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "MFI emits scalar output with series value.",
      "discriminator_value": "MFI",
      "families": [
        "indicators",
        "momentum",
        "volume"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:MFI"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='mfi' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "mfi",
      "recommended_roles": [],
      "ref": "indicator_shape:mfi",
      "requires_state": [],
      "schema_etag": "sha256:2bf806b20fefb2ca0c373eb08969db9b24f1ae7d5505c9278b532b30f8c599c2"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "INTERNAL PLUMBING -- not selectable. MIN emits scalar output with series value. This shape is an engine building block for other handlers and is absent from the `indicator` enum on `value_ref:indicator`, so it cannot be referenced from a strategy. Use `rolling_min` (RollingMinValueRef) instead.",
      "discriminator_value": "MIN",
      "families": [
        "indicators"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:MIN"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Engine-internal shape: NOT selectable through an indicator value reference. It is computed for other handlers, not referenced directly.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "min",
      "recommended_roles": [],
      "ref": "indicator_shape:min",
      "requires_state": [],
      "schema_etag": "sha256:c969c829484a60bcf2a9eca039ef5e95056407b476bcd137d5edd64419d9edfb"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "OBV emits scalar output with series value.",
      "discriminator_value": "OBV",
      "families": [
        "indicators",
        "volume"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:OBV"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='obv' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "obv",
      "recommended_roles": [],
      "ref": "indicator_shape:obv",
      "requires_state": [],
      "schema_etag": "sha256:9e9a14e019d9dd93267da6a5ccebe1b6cf6f9be8b8b458d9fa0e1da9635cb715"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "INTERNAL PLUMBING -- not selectable. PCTILE emits scalar output with series value. This shape is an engine building block for other handlers and is absent from the `indicator` enum on `value_ref:indicator`, so it cannot be referenced from a strategy. Use `percentile` (PercentileValueRef) instead.",
      "discriminator_value": "PCTILE",
      "families": [
        "indicators"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:PCTILE"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Engine-internal shape: NOT selectable through an indicator value reference. It is computed for other handlers, not referenced directly.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "pctile",
      "recommended_roles": [],
      "ref": "indicator_shape:pctile",
      "requires_state": [],
      "schema_etag": "sha256:86e194d41c2b070bb12e041546a3fcfe848bb0df76e79bd349199a010ac875eb"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "PIVOT emits composite output with series value, p, r1, s1, r2, s2, r3, s3.",
      "discriminator_value": "PIVOT",
      "families": [
        "indicators",
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:PIVOT",
        "indicator_shape:PIVOT_P",
        "indicator_shape:pivot_p",
        "indicator_shape:PIVOT_S1",
        "indicator_shape:pivot_s1",
        "indicator_shape:PIVOT_S2",
        "indicator_shape:pivot_s2",
        "indicator_shape:PIVOT_S3",
        "indicator_shape:pivot_s3",
        "indicator_shape:PIVOT_R1",
        "indicator_shape:pivot_r1",
        "indicator_shape:PIVOT_R2",
        "indicator_shape:pivot_r2",
        "indicator_shape:PIVOT_R3",
        "indicator_shape:pivot_r3"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as one of indicator='pivot_p', 'pivot_s1', 'pivot_s2', 'pivot_s3', 'pivot_r1', 'pivot_r2', 'pivot_r3' (value_ref:indicator) -- one series per reference.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "pivot",
      "recommended_roles": [],
      "ref": "indicator_shape:pivot",
      "requires_state": [],
      "schema_etag": "sha256:b1d484b3ed76b1f78511b3197f59791ea089688fab688715a1a32a88f6df9b02"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "INTERNAL PLUMBING -- not selectable. PPHL emits scalar output with series value. This shape is an engine building block for other handlers and is absent from the `indicator` enum on `value_ref:indicator`, so it cannot be referenced from a strategy. Use `swing` (SwingValueRef) instead.",
      "discriminator_value": "PPHL",
      "families": [
        "indicators"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:PPHL"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Engine-internal shape: NOT selectable through an indicator value reference. It is computed for other handlers, not referenced directly.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "pphl",
      "recommended_roles": [],
      "ref": "indicator_shape:pphl",
      "requires_state": [],
      "schema_etag": "sha256:86392db05e6daf0b58b50221efad169d911219878b3f7b13cfc8de80aadee497"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "INTERNAL PLUMBING -- not selectable. RMM emits scalar output with series value. This shape is an engine building block for other handlers and is absent from the `indicator` enum on `value_ref:indicator`, so it cannot be referenced from a strategy. Use `rolling_max` / `rolling_min` (RollingMaxValueRef / RollingMinValueRef) instead.",
      "discriminator_value": "RMM",
      "families": [
        "indicators"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:RMM"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Engine-internal shape: NOT selectable through an indicator value reference. It is computed for other handlers, not referenced directly.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "rmm",
      "recommended_roles": [],
      "ref": "indicator_shape:rmm",
      "requires_state": [],
      "schema_etag": "sha256:ec9812a62d895d188920fe3d370e468e5fc3780a88ef90c0e645cf8a93aebf55"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "ROC emits scalar output with series value.",
      "discriminator_value": "ROC",
      "families": [
        "indicators",
        "momentum"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:ROC"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='roc' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "roc",
      "recommended_roles": [],
      "ref": "indicator_shape:roc",
      "requires_state": [],
      "schema_etag": "sha256:b24766795eafa25313a9b2535894e6fd223c6175e02fab75d56dc19b0a002644"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "RSI emits scalar output with series value.",
      "discriminator_value": "RSI",
      "families": [
        "indicators",
        "momentum"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:RSI"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='rsi' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "rsi",
      "recommended_roles": [],
      "ref": "indicator_shape:rsi",
      "requires_state": [],
      "schema_etag": "sha256:2e26c956b5ab90467d96936be007e735dcb96b400b0df2fb6c1bfeb3823e4526"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "INTERNAL PLUMBING -- not selectable. RW emits scalar output with series value. This shape is an engine building block for other handlers and is absent from the `indicator` enum on `value_ref:indicator`, so it cannot be referenced from a strategy. Use `price` with an explicit `offset` (PriceValueRef) instead.",
      "discriminator_value": "RW",
      "families": [
        "indicators"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:RW"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Engine-internal shape: NOT selectable through an indicator value reference. It is computed for other handlers, not referenced directly.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "rw",
      "recommended_roles": [],
      "ref": "indicator_shape:rw",
      "requires_state": [],
      "schema_etag": "sha256:c53f5bdf5ee2c11c7dc609ed6ee5c989fa87518de7f11b6279a8c0f472c5ef9e"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "SMA emits scalar output with series value.",
      "discriminator_value": "SMA",
      "families": [
        "indicators",
        "trend"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:SMA"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='sma' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "sma",
      "recommended_roles": [],
      "ref": "indicator_shape:sma",
      "requires_state": [],
      "schema_etag": "sha256:091c49a5e5b076ddf22bd759ac72ce0c53906f8753def62a49bb2ede3cb8549a"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "STD emits scalar output with series value.",
      "discriminator_value": "STD",
      "families": [
        "indicators",
        "volatility"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:STD"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='std' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "std",
      "recommended_roles": [],
      "ref": "indicator_shape:std",
      "requires_state": [],
      "schema_etag": "sha256:86e970d04b590e4485eb6e716963cb1b895749443525f3c51f14269822d02517"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "STO emits composite output with series value, k, d.",
      "discriminator_value": "STO",
      "families": [
        "indicators",
        "momentum"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:STO",
        "indicator_shape:STOCHASTIC_K",
        "indicator_shape:stochastic_k",
        "indicator_shape:STOCHASTIC_D",
        "indicator_shape:stochastic_d"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as one of indicator='stochastic_k', 'stochastic_d' (value_ref:indicator) -- one series per reference.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "sto",
      "recommended_roles": [],
      "ref": "indicator_shape:sto",
      "requires_state": [],
      "schema_etag": "sha256:feaa58fe9b1bfa87d3e7d4d8d7c32d9764804b31b77600c73ccec4edff402a88"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "STOCH_RSI emits composite output with series value, k, d.",
      "discriminator_value": "STOCH_RSI",
      "families": [
        "indicators",
        "momentum"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:STOCH_RSI",
        "indicator_shape:SRSI_K",
        "indicator_shape:srsi_k",
        "indicator_shape:SRSI_D",
        "indicator_shape:srsi_d"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as one of indicator='srsi_k', 'srsi_d' (value_ref:indicator) -- one series per reference.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "stoch_rsi",
      "recommended_roles": [],
      "ref": "indicator_shape:stoch_rsi",
      "requires_state": [],
      "schema_etag": "sha256:4982a552e1f0e678571cc4a20997c2e19e06b5ab122ec1c6081ac1693cd5043f"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "STR emits composite output with series value, direction.",
      "discriminator_value": "STR",
      "families": [
        "indicators",
        "trend"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:STR",
        "indicator_shape:SUPERTREND",
        "indicator_shape:supertrend"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='supertrend' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "str",
      "recommended_roles": [],
      "ref": "indicator_shape:str",
      "requires_state": [],
      "schema_etag": "sha256:840154941747364ec04f6565f1f7bb28365c76d409cfeefd52a6993234c235ab"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "VAR emits scalar output with series value.",
      "discriminator_value": "VAR",
      "families": [
        "indicators",
        "volatility"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:VAR"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='var' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "var",
      "recommended_roles": [],
      "ref": "indicator_shape:var",
      "requires_state": [],
      "schema_etag": "sha256:a58d71cd8ab2fc3bfbe4be9c1e4611e24b288f9595dff287cb08dcd5cbe9171b"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "VOL_SMA emits scalar output with series value.",
      "discriminator_value": "VOL_SMA",
      "families": [
        "indicators",
        "volume"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:VOL_SMA",
        "indicator_shape:VOLUME_SMA",
        "indicator_shape:volume_sma"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='volume_sma' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "vol_sma",
      "recommended_roles": [],
      "ref": "indicator_shape:vol_sma",
      "requires_state": [],
      "schema_etag": "sha256:b3dc9bbceb4e4459c8ef75df8160ce711271bc2169b91c11ecb0422e9d3f4600"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "VWAP emits scalar output with series value.",
      "discriminator_value": "VWAP",
      "families": [
        "indicators",
        "price_levels",
        "volume"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:VWAP"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='vwap' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "vwap",
      "recommended_roles": [],
      "ref": "indicator_shape:vwap",
      "requires_state": [],
      "schema_etag": "sha256:257666e1baccb23b5e5aa06f47aabc747cb0ae3a3b82ce3da0aee01154581bad"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "VWAP_BANDS emits composite output with series upper, middle, lower, std_dev.",
      "discriminator_value": "VWAP_BANDS",
      "families": [
        "indicators",
        "bands",
        "volatility"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:VWAP_BANDS"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='vwap_bands' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "vwap_bands",
      "recommended_roles": [],
      "ref": "indicator_shape:vwap_bands",
      "requires_state": [],
      "schema_etag": "sha256:6938a227aac77241bc81b5af374eb999eea68924a98f01a752da858a61f26160"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "VWMA emits scalar output with series value.",
      "discriminator_value": "VWMA",
      "families": [
        "indicators",
        "trend",
        "volume"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:VWMA"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='vwma' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "vwma",
      "recommended_roles": [],
      "ref": "indicator_shape:vwma",
      "requires_state": [],
      "schema_etag": "sha256:707fadde66a0859318add0c7d1f8f8eabce8b95ec22e8669ccd05aa7f1508cac"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [],
      "construct_with": null,
      "consumer_context": "value_ref:indicator",
      "description": "WMA emits scalar output with series value.",
      "discriminator_value": "WMA",
      "families": [
        "indicators",
        "trend"
      ],
      "incompatibilities": [],
      "kind": "indicator_shape",
      "legacy_refs": [
        "indicator_shape:WMA"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Select through an indicator value reference as indicator='wma' (value_ref:indicator).",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "wma",
      "recommended_roles": [],
      "ref": "indicator_shape:wma",
      "requires_state": [],
      "schema_etag": "sha256:da9f5302eea0842ceaad0bab51b9cdc5ee518c0ecdfd8cff6744c4d109d45181"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "create_portfolio",
      "description": "Typed portfolio/collection authoring contract. See allocation admission and compiled-member plan checks for mode restrictions.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect portfolio allocation policy.",
          "ref": "config:portfolio_allocation"
        }
      ],
      "name": "portfolio.create",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "portfolio:create",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:f6bfa7bade199a95ad202fbf5044a39b4def72e69bede1e10bb58cc19b0e825b",
      "setter": "create_portfolio"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "create_portfolio",
      "description": "Typed portfolio/collection authoring contract. See allocation admission and compiled-member plan checks for mode restrictions.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect portfolio allocation policy.",
          "ref": "config:portfolio_allocation"
        }
      ],
      "name": "portfolio.member",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "portfolio:member",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:f3f3e529a3e1632da7cc66646ccd27434c8606a7beb51850b44b5b869c72c64c",
      "setter": "create_portfolio"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "create_portfolio",
      "description": "Typed portfolio/collection authoring contract. See allocation admission and compiled-member plan checks for mode restrictions.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect portfolio allocation policy.",
          "ref": "config:portfolio_allocation"
        }
      ],
      "name": "portfolio.shared_signal",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "portfolio:shared_signal",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:3f9885d58d8e23b511aac36372bb16af9a3725a95721b89226d4fc55e1bfb747",
      "setter": "create_portfolio"
    },
    {
      "altitude": "portfolio",
      "attachable_roles": [],
      "authority": "construction",
      "capabilities": [
        "portfolio_construction"
      ],
      "construct_with": "update_portfolio",
      "description": "Typed portfolio/collection authoring contract. See allocation admission and compiled-member plan checks for mode restrictions.",
      "families": [
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "config",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect portfolio allocation policy.",
          "ref": "config:portfolio_allocation"
        }
      ],
      "name": "portfolio.update",
      "patch_key": null,
      "recommended_roles": [],
      "ref": "portfolio:update",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:802d246709d86c921315ca97c10fbf2ed47a1488dabc505ce1f9999023aff1b6",
      "setter": "update_portfolio"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "edge_trigger"
      ],
      "construct_with": null,
      "description": "Attach upside and downside crosses to the long and short entry groups. Position policy controls reversal.",
      "families": [
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:cross"
        }
      ],
      "name": "Bidirectional EMA cross",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:bidirectional_ema_cross",
      "requires_state": [
        "previous_bar"
      ],
      "schema_etag": "sha256:413f0c424f1014d26aac276c16c1685af45019ab10b19cdcafad0d5c0d886ff2",
      "steps": [
        {
          "arguments": {
            "condition": {
              "direction": "above",
              "kind": "cross",
              "left": {
                "indicator": "ema",
                "kind": "indicator",
                "period": 20
              },
              "right": {
                "indicator": "ema",
                "kind": "indicator",
                "period": 50
              }
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the long cross.",
          "order": 1,
          "tool": "add_rule"
        },
        {
          "arguments": {
            "condition": {
              "direction": "below",
              "kind": "cross",
              "left": {
                "indicator": "ema",
                "kind": "indicator",
                "period": 20
              },
              "right": {
                "indicator": "ema",
                "kind": "indicator",
                "period": 50
              }
            },
            "direction": "short",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the short cross.",
          "order": 2,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "edge_trigger"
      ],
      "construct_with": null,
      "description": "Use the ordinary cross condition for an edge-triggered 20/50 EMA cross.",
      "families": [
        "trend"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:cross"
        }
      ],
      "name": "EMA crossover",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:ema_crossover",
      "requires_state": [],
      "schema_etag": "sha256:28cacdb69b9be82432016eab6a0f33a42fe9a35b164e87539d601de6faaf9c61",
      "steps": [
        {
          "arguments": {
            "condition": {
              "direction": "above",
              "kind": "cross",
              "left": {
                "indicator": "ema",
                "kind": "indicator",
                "offset": 0,
                "period": 20
              },
              "right": {
                "indicator": "ema",
                "kind": "indicator",
                "offset": 0,
                "period": 50
              }
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the long-entry crossover definition.",
          "order": 1,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "event_payload",
        "time_window"
      ],
      "construct_with": null,
      "description": "Gate entries outside a window around a registered custom event.",
      "families": [
        "time_and_events"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:not"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:compare"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "value_ref:event_distance"
        }
      ],
      "name": "Event blackout",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:event_blackout",
      "requires_state": [
        "event_data"
      ],
      "schema_etag": "sha256:191c2e9adc396cea23edd4ddd04e2be9b0eaa30b5351fcae8733c2940366a32f",
      "steps": [
        {
          "arguments": {
            "condition": {
              "condition": {
                "conditions": [
                  {
                    "kind": "compare",
                    "left": {
                      "direction": "next",
                      "event_type_id": "<registered_event_type_id>",
                      "kind": "event_distance",
                      "unit": "minutes"
                    },
                    "op": "<=",
                    "right": 60.0
                  },
                  {
                    "kind": "compare",
                    "left": {
                      "direction": "previous",
                      "event_type_id": "<registered_event_type_id>",
                      "kind": "event_distance",
                      "unit": "minutes"
                    },
                    "op": "<=",
                    "right": 60.0
                  }
                ],
                "kind": "any_of"
              },
              "kind": "not"
            },
            "role": "gate",
            "strategy_id": "<strategy_id>"
          },
          "description": "Attach the outside-window gate; replace the registered-event placeholder first.",
          "order": 1,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "event_payload",
        "level_state"
      ],
      "construct_with": null,
      "description": "Compare a numeric custom-event payload field with a constant.",
      "families": [
        "time_and_events",
        "value_refs"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:compare"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "value_ref:event_field"
        }
      ],
      "name": "Event payload threshold",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:event_payload_threshold",
      "requires_state": [
        "event_data"
      ],
      "schema_etag": "sha256:2494f4425658bd8f0007c0aa9bc0143370c2bca38443961c0bbb646d4ec52619",
      "steps": [
        {
          "arguments": {
            "condition": {
              "kind": "compare",
              "left": {
                "event_field": "score",
                "event_type_id": "<registered_event_type_id>",
                "kind": "event_field"
              },
              "op": ">",
              "right": 0.7
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Attach the payload comparison; register a numeric score field and supply its event type ID first.",
          "order": 1,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "value_expression"
      ],
      "construct_with": null,
      "description": "Use explicit constant nodes inside recursive sizing expressions.",
      "families": [
        "value_refs",
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:compare"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "value_ref:binary_expr"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "config:sizing"
        }
      ],
      "name": "Formula-sized VWAP dislocation",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:formula_sized_vwap_dislocation",
      "requires_state": [
        "strategy_equity"
      ],
      "schema_etag": "sha256:ad21c0be9348fd78d2ab1318ebfeffa2654b16ee481c5141b1b3743e768fac8f",
      "steps": [
        {
          "arguments": {
            "condition": {
              "kind": "compare",
              "left": {
                "kind": "unary_expr",
                "op": "abs",
                "source": {
                  "kind": "binary_expr",
                  "left": {
                    "kind": "binary_expr",
                    "left": {
                      "kind": "binary_expr",
                      "left": {
                        "field": "close",
                        "kind": "price"
                      },
                      "op": "-",
                      "right": {
                        "anchor": "session",
                        "indicator": "vwap",
                        "kind": "indicator"
                      }
                    },
                    "op": "/",
                    "right": {
                      "anchor": "session",
                      "indicator": "vwap",
                      "kind": "indicator"
                    }
                  },
                  "op": "*",
                  "right": {
                    "kind": "constant",
                    "value": 100.0
                  }
                }
              },
              "op": ">",
              "right": 2.0
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the dislocation condition.",
          "order": 1,
          "tool": "add_rule"
        },
        {
          "arguments": {
            "patch": {
              "sizing": {
                "formula": {
                  "kind": "binary_expr",
                  "left": {
                    "kind": "binary_expr",
                    "left": {
                      "field": "current",
                      "kind": "equity"
                    },
                    "op": "*",
                    "right": {
                      "kind": "constant",
                      "value": 0.01
                    }
                  },
                  "op": "/",
                  "right": {
                    "indicator": "atr",
                    "kind": "indicator",
                    "period": 14
                  }
                },
                "formula_unit": "usd",
                "max_usd": 10000,
                "mode": "formula"
              }
            },
            "strategy_id": "<strategy_id>"
          },
          "description": "Set formula sizing with an explicit constant operand.",
          "order": 2,
          "tool": "builder_set_strategy_config"
        }
      ]
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "edge_trigger",
        "reentry"
      ],
      "construct_with": null,
      "description": "Trigger once when price re-enters the lower Keltner boundary.",
      "families": [
        "bands"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:latch"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:compare"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "Keltner re-entry",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:keltner_reentry",
      "requires_state": [
        "previous_bar"
      ],
      "schema_etag": "sha256:def2fef560020073699d39494da01c36e50ca73a3c49ed79b903c9190fe9e1de",
      "steps": [
        {
          "arguments": {
            "condition": {
              "arm": {
                "kind": "compare",
                "left": {
                  "field": "close",
                  "kind": "price"
                },
                "op": "<",
                "right": {
                  "indicator": "keltner",
                  "kind": "indicator",
                  "multiplier": 2.0,
                  "output": "lower",
                  "period": 20
                }
              },
              "fire": {
                "kind": "compare",
                "left": {
                  "field": "close",
                  "kind": "price"
                },
                "op": ">=",
                "right": {
                  "indicator": "keltner",
                  "kind": "indicator",
                  "multiplier": 2.0,
                  "output": "lower",
                  "period": 20
                }
              },
              "kind": "latch"
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the band re-entry edge.",
          "order": 1,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "time_window",
        "dynamic_level",
        "edge_trigger",
        "breakout"
      ],
      "construct_with": null,
      "description": "Cross above the high of each instrument session's local 09:30-10:00 window.",
      "families": [
        "time_and_events",
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:cross"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "value_ref:session"
        }
      ],
      "name": "Opening-range breakout",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:opening_range_breakout",
      "requires_state": [
        "previous_bar"
      ],
      "schema_etag": "sha256:0f81f9249757bf9827cf6203a5062762e67a3a24e81cde60442bd3af85e18933",
      "steps": [
        {
          "arguments": {
            "condition": {
              "direction": "above",
              "kind": "cross",
              "left": {
                "field": "close",
                "kind": "price"
              },
              "right": {
                "kind": "session",
                "session_field": "high",
                "window_duration_minutes": 30,
                "window_start": "09:30"
              }
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Cross the completed opening-window high.",
          "order": 1,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "pair",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "relative_value"
      ],
      "construct_with": null,
      "description": "Trigger from the standardized SPY/QQQ relative-value spread.",
      "families": [
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:spread"
        }
      ],
      "name": "Pairs spread z-score",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:pairs_spread_zscore",
      "requires_state": [],
      "schema_etag": "sha256:5f39a64f941bd30486f1a18f70d3d7bc4d2f624d81b1b5e1dde0c2a59a337d6b",
      "steps": [
        {
          "arguments": {
            "condition": {
              "calc_type": "zscore",
              "kind": "spread",
              "symbol_a": "SPY",
              "symbol_b": "QQQ",
              "threshold": -2.0,
              "trigger_op": "below",
              "window_bars": 100
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the relative-value entry.",
          "order": 1,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "composition",
        "stateful"
      ],
      "construct_with": null,
      "description": "Gate entries using persisted trade-history state after an exit.",
      "families": [
        "combinators",
        "value_refs"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:any_of"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "value_ref:trade_history"
        }
      ],
      "name": "Post-loss cooldown",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:post_loss_cooldown",
      "requires_state": [
        "trade_history"
      ],
      "schema_etag": "sha256:96ffd3a6ffcf1b378fbad89a92d542c451a88e6f33229f639ca2ba6946a8b85b",
      "steps": [
        {
          "arguments": {
            "condition": {
              "conditions": [
                {
                  "kind": "compare",
                  "left": {
                    "field": "trade_count",
                    "kind": "trade_history"
                  },
                  "op": "==",
                  "right": 0
                },
                {
                  "kind": "compare",
                  "left": {
                    "field": "bars_since_last_exit",
                    "kind": "trade_history"
                  },
                  "op": ">",
                  "right": 5
                }
              ],
              "kind": "any_of"
            },
            "role": "gate",
            "strategy_id": "<strategy_id>"
          },
          "description": "Attach the stateful cooldown gate to a strategy with an entry rule.",
          "order": 1,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "edge_trigger"
      ],
      "construct_with": null,
      "description": "Trigger on a volatility squeeze release with trend confirmation.",
      "families": [
        "volatility"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:latch"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:compare"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "value_ref:indicator"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "value_ref:percentile"
        }
      ],
      "name": "Squeeze release",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:squeeze_release",
      "requires_state": [],
      "schema_etag": "sha256:22b8c35e7a8413833a37dcb5435c8c1c7d688f6a697e7822a1ec0f039bcd92df",
      "steps": [
        {
          "arguments": {
            "condition": {
              "arm": {
                "conditions": [
                  {
                    "kind": "compare",
                    "left": {
                      "indicator": "bollinger",
                      "kind": "indicator",
                      "multiplier": 2.0,
                      "output": "lower",
                      "period": 20
                    },
                    "op": ">",
                    "right": {
                      "indicator": "keltner",
                      "kind": "indicator",
                      "multiplier": 1.5,
                      "output": "lower",
                      "period": 20
                    }
                  },
                  {
                    "kind": "compare",
                    "left": {
                      "indicator": "bollinger",
                      "kind": "indicator",
                      "multiplier": 2.0,
                      "output": "upper",
                      "period": 20
                    },
                    "op": "<",
                    "right": {
                      "indicator": "keltner",
                      "kind": "indicator",
                      "multiplier": 1.5,
                      "output": "upper",
                      "period": 20
                    }
                  },
                  {
                    "kind": "compare",
                    "left": {
                      "kind": "percentile",
                      "lookback_bars": 100,
                      "source": {
                        "indicator": "bollinger",
                        "kind": "indicator",
                        "multiplier": 2.0,
                        "output": "bandwidth",
                        "period": 20
                      }
                    },
                    "op": "<=",
                    "right": 20.0
                  },
                  {
                    "kind": "compare",
                    "left": {
                      "indicator": "ema",
                      "kind": "indicator",
                      "period": 20
                    },
                    "op": ">",
                    "right": {
                      "indicator": "ema",
                      "kind": "indicator",
                      "period": 50
                    }
                  }
                ],
                "kind": "all_of"
              },
              "fire": {
                "condition": {
                  "conditions": [
                    {
                      "kind": "compare",
                      "left": {
                        "indicator": "bollinger",
                        "kind": "indicator",
                        "multiplier": 2.0,
                        "output": "lower",
                        "period": 20
                      },
                      "op": ">",
                      "right": {
                        "indicator": "keltner",
                        "kind": "indicator",
                        "multiplier": 1.5,
                        "output": "lower",
                        "period": 20
                      }
                    },
                    {
                      "kind": "compare",
                      "left": {
                        "indicator": "bollinger",
                        "kind": "indicator",
                        "multiplier": 2.0,
                        "output": "upper",
                        "period": 20
                      },
                      "op": "<",
                      "right": {
                        "indicator": "keltner",
                        "kind": "indicator",
                        "multiplier": 1.5,
                        "output": "upper",
                        "period": 20
                      }
                    },
                    {
                      "kind": "compare",
                      "left": {
                        "kind": "percentile",
                        "lookback_bars": 100,
                        "source": {
                          "indicator": "bollinger",
                          "kind": "indicator",
                          "multiplier": 2.0,
                          "output": "bandwidth",
                          "period": 20
                        }
                      },
                      "op": "<=",
                      "right": 20.0
                    },
                    {
                      "kind": "compare",
                      "left": {
                        "indicator": "ema",
                        "kind": "indicator",
                        "period": 20
                      },
                      "op": ">",
                      "right": {
                        "indicator": "ema",
                        "kind": "indicator",
                        "period": 50
                      }
                    }
                  ],
                  "kind": "all_of"
                },
                "kind": "not"
              },
              "kind": "latch"
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the squeeze-release entry.",
          "order": 1,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "composition",
        "sequence"
      ],
      "construct_with": null,
      "description": "Use sequence for an ordered squeeze release followed by breakout within ten bars.",
      "families": [
        "combinators",
        "temporal"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:sequence"
        }
      ],
      "name": "Squeeze then breakout",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:squeeze_then_breakout",
      "requires_state": [
        "previous_bar"
      ],
      "schema_etag": "sha256:aaf3de1674c1f45f78ef1a8082045066ae0d7e2e414a59192ab49023f5c5ee2d",
      "steps": [
        {
          "arguments": {
            "condition": {
              "kind": "sequence",
              "steps": [
                {
                  "condition": {
                    "arm": {
                      "conditions": [
                        {
                          "kind": "compare",
                          "left": {
                            "indicator": "bollinger",
                            "kind": "indicator",
                            "multiplier": 2.0,
                            "output": "lower",
                            "period": 20
                          },
                          "op": ">",
                          "right": {
                            "indicator": "keltner",
                            "kind": "indicator",
                            "multiplier": 1.5,
                            "output": "lower",
                            "period": 20
                          }
                        },
                        {
                          "kind": "compare",
                          "left": {
                            "indicator": "bollinger",
                            "kind": "indicator",
                            "multiplier": 2.0,
                            "output": "upper",
                            "period": 20
                          },
                          "op": "<",
                          "right": {
                            "indicator": "keltner",
                            "kind": "indicator",
                            "multiplier": 1.5,
                            "output": "upper",
                            "period": 20
                          }
                        },
                        {
                          "kind": "compare",
                          "left": {
                            "kind": "percentile",
                            "lookback_bars": 100,
                            "source": {
                              "indicator": "bollinger",
                              "kind": "indicator",
                              "multiplier": 2.0,
                              "output": "bandwidth",
                              "period": 20
                            }
                          },
                          "op": "<=",
                          "right": 20.0
                        }
                      ],
                      "kind": "all_of"
                    },
                    "fire": {
                      "condition": {
                        "conditions": [
                          {
                            "kind": "compare",
                            "left": {
                              "indicator": "bollinger",
                              "kind": "indicator",
                              "multiplier": 2.0,
                              "output": "lower",
                              "period": 20
                            },
                            "op": ">",
                            "right": {
                              "indicator": "keltner",
                              "kind": "indicator",
                              "multiplier": 1.5,
                              "output": "lower",
                              "period": 20
                            }
                          },
                          {
                            "kind": "compare",
                            "left": {
                              "indicator": "bollinger",
                              "kind": "indicator",
                              "multiplier": 2.0,
                              "output": "upper",
                              "period": 20
                            },
                            "op": "<",
                            "right": {
                              "indicator": "keltner",
                              "kind": "indicator",
                              "multiplier": 1.5,
                              "output": "upper",
                              "period": 20
                            }
                          },
                          {
                            "kind": "compare",
                            "left": {
                              "kind": "percentile",
                              "lookback_bars": 100,
                              "source": {
                                "indicator": "bollinger",
                                "kind": "indicator",
                                "multiplier": 2.0,
                                "output": "bandwidth",
                                "period": 20
                              }
                            },
                            "op": "<=",
                            "right": 20.0
                          }
                        ],
                        "kind": "all_of"
                      },
                      "kind": "not"
                    },
                    "kind": "latch"
                  }
                },
                {
                  "condition": {
                    "direction": "above",
                    "kind": "cross",
                    "left": {
                      "field": "close",
                      "kind": "price"
                    },
                    "right": {
                      "field": "high",
                      "kind": "rolling_max",
                      "lookback_bars": 20
                    }
                  },
                  "within_bars": 10
                }
              ]
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the ordered temporal condition.",
          "order": 1,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "composition"
      ],
      "construct_with": null,
      "description": "Use at_least rather than hand-expanding every three-of-five Boolean combination.",
      "families": [
        "combinators"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:at_least"
        }
      ],
      "name": "Three-of-five confluence",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:three_of_five_confluence",
      "requires_state": [],
      "schema_etag": "sha256:a4a04e7ef8804e013e0f60a4a2d5e8a23017151f1f9465f95afb8139a29e16cb",
      "steps": [
        {
          "arguments": {
            "condition": {
              "conditions": [
                {
                  "kind": "compare",
                  "left": {
                    "indicator": "rsi",
                    "kind": "indicator",
                    "period": 14
                  },
                  "op": "<",
                  "right": 35
                },
                {
                  "kind": "compare",
                  "left": {
                    "kind": "binary_expr",
                    "left": {
                      "kind": "volume"
                    },
                    "op": "/",
                    "right": {
                      "indicator": "volume_sma",
                      "kind": "indicator",
                      "period": 20
                    }
                  },
                  "op": ">",
                  "right": 1.5
                },
                {
                  "kind": "candle_pattern",
                  "pattern": "hammer"
                },
                {
                  "kind": "compare",
                  "left": {
                    "kind": "binary_expr",
                    "left": {
                      "indicator": "roc",
                      "kind": "indicator",
                      "period": 5
                    },
                    "op": "*",
                    "right": {
                      "kind": "constant",
                      "value": 100.0
                    }
                  },
                  "op": ">",
                  "right": 1.0
                },
                {
                  "arm": {
                    "kind": "compare",
                    "left": {
                      "field": "low",
                      "kind": "price"
                    },
                    "op": ">",
                    "right": {
                      "indicator": "bollinger",
                      "kind": "indicator",
                      "multiplier": 2.0,
                      "output": "lower",
                      "period": 20
                    }
                  },
                  "fire": {
                    "conditions": [
                      {
                        "kind": "compare",
                        "left": {
                          "field": "low",
                          "kind": "price"
                        },
                        "op": "<=",
                        "right": {
                          "indicator": "bollinger",
                          "kind": "indicator",
                          "multiplier": 2.0,
                          "output": "lower",
                          "period": 20
                        }
                      },
                      {
                        "kind": "compare",
                        "left": {
                          "field": "high",
                          "kind": "price"
                        },
                        "op": ">=",
                        "right": {
                          "indicator": "bollinger",
                          "kind": "indicator",
                          "multiplier": 2.0,
                          "output": "lower",
                          "period": 20
                        }
                      }
                    ],
                    "kind": "all_of"
                  },
                  "kind": "latch"
                }
              ],
              "kind": "at_least",
              "min_true": 3
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the threshold combinator.",
          "order": 1,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "cross_section",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "cross_sectional",
        "portfolio_construction"
      ],
      "construct_with": null,
      "description": "Compare cross-sectional ranks inside a multi-instrument basket. Create the strategy with multiple symbols first.",
      "families": [
        "cross_sectional"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:compare"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "value_ref:rank"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "config:allocation:equal_weight"
        }
      ],
      "name": "Top-decile momentum basket",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:top_decile_momentum_basket",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:e1640837dc5f068e4866e323885218c4c421a033188a5f49e8c2d8b8197082f9",
      "steps": [
        {
          "arguments": {
            "allocation": {
              "construction": {
                "kind": "equal_weight"
              }
            },
            "strategy_id": "<strategy_id>"
          },
          "description": "Give the basket an explicit allocation.",
          "order": 1,
          "tool": "builder_set_allocation"
        },
        {
          "arguments": {
            "condition": {
              "kind": "compare",
              "left": {
                "kind": "rank",
                "source": {
                  "indicator": "roc",
                  "kind": "indicator",
                  "offset": 0,
                  "period": 20
                }
              },
              "op": ">",
              "right": 0.9
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the top-decile condition.",
          "order": 2,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "level_state"
      ],
      "construct_with": null,
      "description": "Combine an RSI pullback entry with a sustained long-term trend gate.",
      "families": [
        "trend",
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:compare"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "value_ref:indicator"
        }
      ],
      "name": "Trend pullback",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:trend_pullback",
      "requires_state": [],
      "schema_etag": "sha256:3c454e2309119aa8827e1454dcdd52d940b8eb2036ad80a45b340a5fe381bc6f",
      "steps": [
        {
          "arguments": {
            "condition": {
              "kind": "compare",
              "left": {
                "indicator": "rsi",
                "kind": "indicator",
                "period": 14
              },
              "op": "<",
              "right": 35
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the RSI pullback entry.",
          "order": 1,
          "tool": "add_rule"
        },
        {
          "arguments": {
            "condition": {
              "kind": "compare",
              "left": {
                "field": "close",
                "kind": "price"
              },
              "op": ">",
              "right": {
                "indicator": "sma",
                "kind": "indicator",
                "period": 200
              }
            },
            "role": "gate",
            "strategy_id": "<strategy_id>"
          },
          "description": "Attach the sustained trend gate.",
          "order": 2,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "documentation",
      "capabilities": [
        "recurring_schedule"
      ],
      "construct_with": null,
      "description": "Use a weekly calendar schedule and fixed-dollar sizing for recurring entries.",
      "families": [
        "time_and_events",
        "strategy_config"
      ],
      "incompatibilities": [],
      "kind": "recipe",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "condition:calendar_schedule"
        },
        {
          "kind": "detail",
          "reason": "Inspect this recipe dependency.",
          "ref": "config:sizing"
        }
      ],
      "name": "Weekly DCA",
      "recommendation_disclaimer": "construction_example_not_trading_advice",
      "recommended_roles": [],
      "ref": "recipe:weekly_dca",
      "requires_state": [],
      "schema_etag": "sha256:dcf18309d40213b214989077671726c43a54067be07c34502e553f6198657d0a",
      "steps": [
        {
          "arguments": {
            "condition": {
              "day": "monday",
              "every": "1w",
              "kind": "calendar_schedule",
              "time": "15:00",
              "tz": "America/New_York"
            },
            "direction": "long",
            "role": "entry",
            "strategy_id": "<strategy_id>"
          },
          "description": "Create the weekly entry schedule.",
          "order": 1,
          "tool": "add_rule"
        },
        {
          "arguments": {
            "patch": {
              "position_policy": {
                "max_positions": 100,
                "mode": "accumulate"
              },
              "sizing": {
                "fixed_usd": 500,
                "mode": "fixed_usd"
              }
            },
            "strategy_id": "<strategy_id>"
          },
          "description": "Set fixed-dollar sizing and allow up to 100 recurring lots while invested.",
          "order": 2,
          "tool": "builder_set_strategy_config"
        }
      ]
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "resource",
      "capabilities": [
        "dynamic_level",
        "resource_definition"
      ],
      "construct_with": "builder_save_anchor",
      "description": "Strategy-level anchor definition for builder_save_anchor.",
      "families": [
        "custom_structures"
      ],
      "incompatibilities": [],
      "inspect_tool": "builder_get_strategy",
      "kind": "resource",
      "legacy_refs": [
        "anchor"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Consume the saved resource from a condition.",
          "ref": "value_ref:anchor"
        }
      ],
      "name": "anchor",
      "recommended_roles": [],
      "ref": "resource:anchor",
      "requires_state": [],
      "save_tool": "builder_save_anchor",
      "schema_etag": "sha256:2d5e52666beb912f0f0e5d99d9a0a6d737cb190b8f74d520e3afc13621078fba"
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "resource",
      "capabilities": [
        "dynamic_level",
        "resource_definition"
      ],
      "construct_with": "builder_save_zone",
      "description": "Strategy-level named zone definition for builder_save_zone.",
      "families": [
        "custom_structures"
      ],
      "incompatibilities": [],
      "inspect_tool": "builder_get_strategy",
      "kind": "resource",
      "legacy_refs": [
        "zone"
      ],
      "links": [
        {
          "kind": "detail",
          "reason": "Consume the saved resource from a condition.",
          "ref": "value_ref:named_zone"
        }
      ],
      "name": "zone",
      "recommended_roles": [],
      "ref": "resource:zone",
      "requires_state": [],
      "save_tool": "builder_save_zone",
      "schema_etag": "sha256:873ee32646a0e19e11268b2a65303b21d13e2531437ce92a4650cf065377ca0f"
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "dynamic_level",
        "stateful"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition",
        "execution"
      ],
      "description": "A field of a named anchor \u2014 a single bar captured earlier and then held.\n\nThe anchor is declared in the strategy's ``anchors`` (captured by\ntimestamp, bar index, or the first false-to-true flip of a condition);\nreferencing an ``anchor_id`` that is not declared fails at compile time.\nUntil the anchor actually fires the value is typed absence. A comparison\nover that absent operand is UNKNOWN; the action boundary takes no action.\n``mid`` and ``range`` are derived from the captured bar's high and low.\nDoes not accept ``resolution``.",
      "discriminator_value": "anchor",
      "families": [
        "value_refs",
        "price_levels",
        "custom_structures"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "anchor",
      "output_units": [
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "anchor_field": "open"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "anchor_field": "high"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "anchor_field": "low"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "anchor_field": "close"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "anchor_field": "mid"
          }
        },
        {
          "note": "high - low of the captured bar: a price difference",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "anchor_field": "range"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:anchor",
      "requires_state": [
        "anchor"
      ],
      "schema_etag": "sha256:5bb3f3a26f089b5d023d3ef2f3ce717ed0c60f64f03420a6f97d85bea8f4d1ba",
      "unit_scales": {
        "price": "quote-currency price level (a difference of prices is also in price units)"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "value_expression"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition",
        "sizing"
      ],
      "description": "Binary expression over two ValueRef operands.\n\nProvided alongside UnaryExprValueRef so tests / flat-Condition authors can\nbuild composite expressions like ``abs(close - 100)``. Compiles to a binary\nIRExpression.",
      "discriminator_value": "binary_expr",
      "families": [
        "value_refs"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "Each operand accepts a nested value reference or a plain number."
        }
      ],
      "name": "binary_expr",
      "output_units": [
        {
          "note": "the operands are expected to share a unit; mixing units is legal and unchecked",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "op": "+"
          }
        },
        {
          "note": "the operands are expected to share a unit; mixing units is legal and unchecked",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "op": "-"
          }
        },
        {
          "note": "the operands are expected to share a unit; mixing units is legal and unchecked",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "op": "max"
          }
        },
        {
          "note": "the operands are expected to share a unit; mixing units is legal and unchecked",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "op": "min"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": "the unit derives from both operands and the operator; unit inference through expressions is tracked as later work",
          "unit": "not_determined",
          "when": {
            "op": "*"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": "the unit derives from both operands and the operator; unit inference through expressions is tracked as later work",
          "unit": "not_determined",
          "when": {
            "op": "/"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:binary_expr",
      "requires_state": [],
      "schema_etag": "sha256:6aab8634e007d17e6c214ebe45a9daecac6e8e649ac7cf8978d55b1a604fc15f",
      "unit_scales": {
        "not_determined": "not confirmed; see reason",
        "same_as_source": "same unit and scale as the source operand"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "value_expression"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition",
        "sizing"
      ],
      "description": "A fixed numeric literal, usable anywhere a value ref is accepted.\n\nThe one ref that is NOT a ``ValueRefBaseModel``: it has no ``symbol`` or\n``resolution`` qualifier. A bare int/float written into ``binary_expr``/\n``unary_expr`` operands or ``compare.right`` is coerced to this type\nautomatically, so writing it out explicitly is rarely necessary.",
      "discriminator_value": "constant",
      "families": [
        "value_refs"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "constant",
      "output_units": [
        {
          "note": "a literal: write it in the unit of the operand it is compared with or combined with",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:constant",
      "requires_state": [],
      "schema_etag": "sha256:518d394bdb2a473a880b9d7a390eb2256dbb0a2755f1601acf73f9d1a6b014db",
      "unit_scales": {
        "same_as_source": "same unit and scale as the source operand"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "stateful"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Reference to a field of the signal bar for the currently-open position.\n\nAuto-captured by the engine when a position opens. Returns NaN when no\nposition is open. Clears on position close. Use for ORB-style \"stop out\nbelow the signal-bar low\" without AnchorDefinition's silent-latching bug.\n\nFields:\n  - open / high / low / close: signal-bar OHLC\n  - range: high - low\n  - body_high: max(open, close)\n  - body_low: min(open, close)",
      "discriminator_value": "entry_bar",
      "families": [
        "value_refs",
        "risk_management"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "entry_bar",
      "output_units": [
        {
          "note": "range is a price difference",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:entry_bar",
      "requires_state": [
        "entry_bar"
      ],
      "schema_etag": "sha256:70596eda2f415ffa34a13c4690ae80b135e4601245ec07ef466f675bf3ce74bf",
      "unit_scales": {
        "price": "quote-currency price level (a difference of prices is also in price units)"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "stateful"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "The strategy's running equity-curve value.\n\n``field`` selects: ``current`` (equity right now), ``peak`` (the running\nhigh-water mark), or ``drawdown_pct`` (percent below that peak \u2014 0 at a\nnew high, positive while underwater). Use ``drawdown_pct`` directly for a\ncircuit-breaker gate rather than deriving it from ``current``/``peak``.\n\nVIB-1370 / VIB-1319: the sub-metric selector is named ``field``\nacross every ValueRef-style type. The legacy name ``equity_metric`` was\nremoved.",
      "discriminator_value": "equity",
      "families": [
        "value_refs",
        "risk_management"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "equity",
      "output_units": [
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "currency_amount",
          "when": {
            "field": "current"
          }
        },
        {
          "note": "running high-water mark",
          "range": null,
          "reason": null,
          "unit": "currency_amount",
          "when": {
            "field": "peak"
          }
        },
        {
          "note": "0 at a new high; positive while underwater",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "percent",
          "when": {
            "field": "drawdown_pct"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:equity",
      "requires_state": [
        "strategy_equity"
      ],
      "schema_etag": "sha256:f4ae8eaffade41d3998290a0598ccf1a6bf29465405380190b24146ba00ef45d",
      "unit_scales": {
        "currency_amount": "account-currency amount",
        "percent": "percent: 2 means 2%"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "event_payload"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Distance from the current bar to an event type's next or previous occurrence.\n\n``direction=\"previous\"`` counts back to the latest occurrence at or before the\nbar: 0 on the bar the occurrence is assigned to. ``direction=\"next\"`` counts\nforward to the earliest occurrence strictly after the bar, so it is never 0\nin minutes. ``unit`` is wall-clock minutes or bars.\n\nWhen no such occurrence is known the value is infinity (present, not absent), so\n``distance <= N`` is false and ``not (distance <= N)`` is true: that is how a\n\"stay away from events\" gate is written.\n\nA ``next`` distance needs the event's date to be known in advance. Among system\nevents only those with a forward release calendar (macro.cpi,\nmacro.nonfarm_payrolls, macro.unemployment) qualify; any other system event is\nrefused with ``direction=\"next\"``, because the platform cannot anticipate it.\nCustom events are unrestricted. Use ``direction=\"previous\"`` to react after a\nsystem event.\n\nExample, within 5 bars after an event:\n  {\"kind\": \"event_distance\", \"event_type_id\": \"my-signal\", \"direction\": \"previous\",\n   \"unit\": \"bars\"}",
      "discriminator_value": "event_distance",
      "families": [
        "value_refs",
        "time_and_events"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "event_distance",
      "output_units": [
        {
          "note": "infinity when no such occurrence is known (not absent)",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "minutes",
          "when": {
            "unit": "minutes"
          }
        },
        {
          "note": "infinity when no such occurrence is known (not absent)",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "bar_count",
          "when": {
            "unit": "bars"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:event_distance",
      "requires_state": [
        "event_data"
      ],
      "schema_etag": "sha256:d03f1485169160acb6f41c848092a04e654d66f0ccf2d4b61b434f90ec185166",
      "unit_scales": {
        "bar_count": "a number of bars",
        "minutes": "a number of minutes"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "event_payload"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Field from latest event payload.\n\nAuthoring flow:\n  1. Call list_event_types().\n  2. Pick event_type_id from a returned event type.\n  3. Pick event_field from payload_schema.fields.\n\nExample:\n  {\"kind\": \"event_field\", \"event_type_id\": \"macro.cpi\",\n   \"event_field\": \"value\"}\n\nTo compare a release against a previous one, set occurrences_back on a\nsecond ref and subtract:\n  {\"kind\": \"binary_expr\", \"op\": \"-\",\n   \"left\":  {\"kind\": \"event_field\", \"event_type_id\": \"macro.cpi\",\n             \"event_field\": \"value\"},\n   \"right\": {\"kind\": \"event_field\", \"event_type_id\": \"macro.cpi\",\n             \"event_field\": \"value\", \"occurrences_back\": 1}}",
      "discriminator_value": "event_field",
      "families": [
        "value_refs",
        "time_and_events"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [
        "value_ref:event"
      ],
      "links": [],
      "name": "event_field",
      "output_units": [
        {
          "note": "the unit is whatever the event type's payload publishes for this field",
          "range": null,
          "reason": null,
          "unit": "payload_declared",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:event_field",
      "requires_state": [
        "event_data"
      ],
      "schema_etag": "sha256:06b8acda0af52978059ce536ae217fa800707a41ef5b8a43f134b24e2440aea0",
      "unit_scales": {
        "payload_declared": "the unit the event type's payload schema declares"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Indicator output \u2014 RSI, CCI, EMA/SMA, ATR, ADX, ROC (decimal: 0.05=5%), oscillators (rsi, srsi_k/d, stochastic_k/d, mfi) are 0-100 NOT 0-1 \u2014 oversold is `<= 5`, not `<= 0.05`.\n\nMACD/signal/histogram, stochastic_k/d, Bollinger bands, volume_sma, pivot levels. Use schema.variants.shape_refs to find the canonical shape ref for your authored indicator, then fetch it with builder_discover(action='get', ref=<returned ref>).",
      "discriminator_value": "indicator",
      "families": [
        "value_refs",
        "volatility",
        "momentum",
        "trend",
        "volume",
        "bands"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "indicator_shape"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "Choose an exact indicator input and output shape."
        }
      ],
      "name": "indicator",
      "output_units": [
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "ema"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "sma"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "wma"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "vwma"
          }
        },
        {
          "note": null,
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {
            "indicator": "rsi"
          }
        },
        {
          "note": "Wilder-smoothed average true range",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "atr"
          }
        },
        {
          "note": "0.05 is a 5% move; a threshold of 5 means 500%",
          "range": null,
          "reason": null,
          "unit": "ratio",
          "when": {
            "indicator": "roc"
          }
        },
        {
          "note": "unbounded; not a percent",
          "range": null,
          "reason": null,
          "unit": "dimensionless",
          "when": {
            "indicator": "cci"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "volume",
          "when": {
            "indicator": "volume_sma"
          }
        },
        {
          "note": null,
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {
            "indicator": "mfi"
          }
        },
        {
          "note": null,
          "range": {
            "max": 1.0,
            "min": -1.0
          },
          "reason": null,
          "unit": "ratio",
          "when": {
            "indicator": "cmf"
          }
        },
        {
          "note": "population standard deviation of the close",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "std"
          }
        },
        {
          "note": "population variance of the close",
          "range": null,
          "reason": null,
          "unit": "price_squared",
          "when": {
            "indicator": "var"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "median"
          }
        },
        {
          "note": "a difference of exponential averages, in price units",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "macd"
          }
        },
        {
          "note": "a difference of exponential averages, in price units",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "macd_signal"
          }
        },
        {
          "note": "a difference of exponential averages, in price units",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "macd_histogram"
          }
        },
        {
          "note": null,
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {
            "indicator": "stochastic_k"
          }
        },
        {
          "note": null,
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {
            "indicator": "stochastic_d"
          }
        },
        {
          "note": "0-100, not 0-1",
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {
            "indicator": "srsi_k"
          }
        },
        {
          "note": "0-100, not 0-1",
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {
            "indicator": "srsi_d"
          }
        },
        {
          "note": "cumulative from the first loaded bar; the absolute level is arbitrary",
          "range": null,
          "reason": null,
          "unit": "volume",
          "when": {
            "indicator": "ad"
          }
        },
        {
          "note": "cumulative signed volume; the absolute level is arbitrary",
          "range": null,
          "reason": null,
          "unit": "volume",
          "when": {
            "indicator": "obv"
          }
        },
        {
          "note": null,
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {
            "indicator": "aroon",
            "line": "up"
          }
        },
        {
          "note": null,
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {
            "indicator": "aroon",
            "line": "down"
          }
        },
        {
          "note": "the active band; jumps across price when the trend flips",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "supertrend",
            "output": "value"
          }
        },
        {
          "note": "+1 uptrend, -1 downtrend",
          "range": {
            "max": 1.0,
            "min": -1.0
          },
          "reason": null,
          "unit": "enum_code",
          "when": {
            "indicator": "supertrend",
            "output": "direction"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "bollinger",
            "output": "upper"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "bollinger",
            "output": "middle"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "bollinger",
            "output": "lower"
          }
        },
        {
          "note": "(upper - lower) / middle * 100, so 5 means 5% of the middle band",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "percent",
          "when": {
            "indicator": "bollinger",
            "output": "bandwidth"
          }
        },
        {
          "note": "population standard deviation",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "bollinger",
            "output": "stddev"
          }
        },
        {
          "note": "excludes the current bar",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "donchian",
            "output": "upper"
          }
        },
        {
          "note": "excludes the current bar",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "donchian",
            "output": "middle"
          }
        },
        {
          "note": "excludes the current bar",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "donchian",
            "output": "lower"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "keltner",
            "output": "upper"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "keltner",
            "output": "middle"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "keltner",
            "output": "lower"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "vwap_bands",
            "output": "upper"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "vwap_bands",
            "output": "middle"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "vwap_bands",
            "output": "lower"
          }
        },
        {
          "note": "volume-weighted standard deviation of typical price around the VWAP; not scaled by multiplier",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "vwap_bands",
            "output": "std_dev"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "vwap"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "avwap",
            "output": "value"
          }
        },
        {
          "note": "volume-weighted standard deviation around the anchored VWAP",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "avwap",
            "output": "std_dev"
          }
        },
        {
          "note": null,
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {
            "indicator": "adx_di",
            "output": "adx"
          }
        },
        {
          "note": null,
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {
            "indicator": "adx_di",
            "output": "plus_di"
          }
        },
        {
          "note": null,
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {
            "indicator": "adx_di",
            "output": "minus_di"
          }
        },
        {
          "note": "constant for the UTC day; rolls at the UTC day, not the session",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "pivot_p"
          }
        },
        {
          "note": "constant for the UTC day; rolls at the UTC day, not the session",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "pivot_s1"
          }
        },
        {
          "note": "constant for the UTC day; rolls at the UTC day, not the session",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "pivot_s2"
          }
        },
        {
          "note": "constant for the UTC day; rolls at the UTC day, not the session",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "pivot_s3"
          }
        },
        {
          "note": "constant for the UTC day; rolls at the UTC day, not the session",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "pivot_r1"
          }
        },
        {
          "note": "constant for the UTC day; rolls at the UTC day, not the session",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "pivot_r2"
          }
        },
        {
          "note": "constant for the UTC day; rolls at the UTC day, not the session",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "indicator": "pivot_r3"
          }
        },
        {
          "note": "-1 bearish hit, 0 no hit, +1 bullish hit",
          "range": {
            "max": 1.0,
            "min": -1.0
          },
          "reason": null,
          "unit": "enum_code",
          "when": {
            "indicator": "candlestick"
          }
        },
        {
          "note": "2 means a 2% gap; present only on the session's opening bar, absent elsewhere",
          "range": null,
          "reason": null,
          "unit": "percent",
          "when": {
            "indicator": "gap"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:indicator",
      "requires_state": [],
      "schema_etag": "sha256:618d8cb0cf1f510d290d8bd1897568fa8cc921e1fb5373b92f1a8c29e89c4795",
      "unit_scales": {
        "bounded_oscillator": "fixed-range oscillator; see range",
        "dimensionless": "unitless number",
        "enum_code": "coded value; see note",
        "percent": "percent: 2 means 2%",
        "price": "quote-currency price level (a difference of prices is also in price units)",
        "price_squared": "squared quote-currency price units (variance)",
        "ratio": "ratio: 0.02 means 2%",
        "volume": "traded volume units (shares, or coins for crypto)"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "stateful"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "A metric of the CURRENTLY OPEN position, read live every bar (not a\nfrozen snapshot from entry \u2014 contrast ``entry_bar``/``sequence_step``,\nwhich capture a value once and hold it).\n\n``field`` selects: ``entry_price``, ``bars_in_position``,\n``unrealized_pnl_pct`` / ``unrealized_pnl_usd``, or\n``max_excursion_pct`` / ``min_excursion_pct`` (the best/worst unrealized\nPnL% reached since entry \u2014 MAE/MFE). All are NaN while flat.\n\n``bars_in_position`` counts the bars the position has been open in,\nINCLUDING the bar it filled in: it is 1 at the close of the fill bar, not\n0. An exit on ``bars_in_position >= N`` therefore decides at the close of\nthe Nth held bar and fills at the next bar's open, so the trade's\n``exit_bar - entry_bar`` is exactly N.\n\nVIB-1398 / VIB-1370 / VIB-1319: the sub-metric selector is named\n``field`` across every ValueRef-style type. The legacy name\n``position_metric`` was removed (mirrors the IR-side\n``LivePositionRef.metric \u2192 field`` rename that VIB-1394 shipped).",
      "discriminator_value": "live_position",
      "families": [
        "value_refs",
        "risk_management"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "live_position",
      "output_units": [
        {
          "note": "first lot only",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "field": "entry_price"
          }
        },
        {
          "note": "includes the fill bar; counted from the first lot",
          "range": null,
          "reason": null,
          "unit": "bar_count",
          "when": {
            "field": "bars_in_position"
          }
        },
        {
          "note": "first lot only",
          "range": null,
          "reason": null,
          "unit": "percent",
          "when": {
            "field": "unrealized_pnl_pct"
          }
        },
        {
          "note": "all lots; quote currency despite the _usd suffix",
          "range": null,
          "reason": null,
          "unit": "currency_amount",
          "when": {
            "field": "unrealized_pnl_usd"
          }
        },
        {
          "note": "best unrealized PnL since entry; first lot only",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "percent",
          "when": {
            "field": "max_excursion_pct"
          }
        },
        {
          "note": "worst unrealized PnL since entry; first lot only",
          "range": {
            "max": 0.0,
            "min": null
          },
          "reason": null,
          "unit": "percent",
          "when": {
            "field": "min_excursion_pct"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:live_position",
      "requires_state": [
        "live_position"
      ],
      "schema_etag": "sha256:52bd68c703f624106d1e5263d378ba5b4ab55473ddac8ebf1f068aad70b57b68",
      "unit_scales": {
        "bar_count": "a number of bars",
        "currency_amount": "account-currency amount",
        "percent": "percent: 2 means 2%",
        "price": "quote-currency price level (a difference of prices is also in price units)"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "dynamic_level",
        "stateful"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition",
        "execution"
      ],
      "description": "A boundary of a named strategy-level zone: its `upper`, `lower`, or derived `mid`.\n\n``mid`` is computed as ``(upper + lower) / 2`` at read time and is not a\nstored field. Zone boundaries may themselves be anchor refs, in which case\nthe whole zone reads NaN until that anchor fires. Referencing an undeclared\n``zone_id`` fails at compile time. Does not accept ``resolution``.",
      "discriminator_value": "named_zone",
      "families": [
        "value_refs",
        "price_levels",
        "custom_structures"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "named_zone",
      "output_units": [
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "zone_field": "upper"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "zone_field": "lower"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "zone_field": "mid"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:named_zone",
      "requires_state": [
        "named_zone"
      ],
      "schema_etag": "sha256:60975355d90664a5273c61d7b46406ef433f9ceb101dcf058128ae238d1e0d85",
      "unit_scales": {
        "price": "quote-currency price level (a difference of prices is also in price units)"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "value_expression"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Percentile RANK of the current bar's `field` (or of any `source` value) within the trailing `lookback_bars` window.\n\nReturns ``100 * (values strictly below the current one) / (lookback_bars - 1)``\nover a window that **includes the current bar**: a new window high reads\n100, a new window low reads 0. Ties are not counted, so a perfectly flat\nwindow reads 0.\n\n**This is the inverse of** ``rolling_stats(stat=\"percentile\")``, which\nreturns the *value* sitting at a given percentile level. Use this ref to\nask \"how extreme is price right now\", and ``rolling_stats`` to ask \"what\nprice is the 90th percentile\". NaN propagates: any missing value in the\nwindow returns NaN.\n\n``source`` ranks any value ref rather than a price field, so \"is the volume\nunusually high\" or \"is the band width unusually narrow\" is one operand:\n``lookback_bars`` (2 to 500) is the window the current value is ranked in.\nEvery bar in the window is evaluated, so a long window over a nested\nexpression costs more than a price field does.\n\nExample, the percentile of the Bollinger band width over 100 bars:\n  {\"kind\": \"percentile\", \"lookback_bars\": 100,\n   \"source\": {\"kind\": \"binary_expr\", \"op\": \"-\",\n              \"left\": {\"kind\": \"indicator\", \"indicator\": \"bollinger\", \"output\": \"upper\"},\n              \"right\": {\"kind\": \"indicator\", \"indicator\": \"bollinger\", \"output\": \"lower\"}}}",
      "discriminator_value": "percentile",
      "families": [
        "value_refs",
        "momentum"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "percentile",
      "output_units": [
        {
          "note": "percent rank in the window; the window includes the current bar",
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:percentile",
      "requires_state": [],
      "schema_etag": "sha256:95dac0611a40f0d8b294d50c767a77e3ace9f3ca3b37a0670b45f6f1a77bdce6",
      "unit_scales": {
        "bounded_oscillator": "fixed-range oscillator; see range"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "A single OHLC field of the current bar, or of a bar `offset` bars back.\n\n``offset=0`` (the default) is the bar being evaluated. Reading past the\nstart of loaded history returns NaN rather than clamping to the first bar,\nand a NaN operand makes the enclosing compare false.",
      "discriminator_value": "price",
      "families": [
        "value_refs",
        "price_signals"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "price",
      "output_units": [
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:price",
      "requires_state": [],
      "schema_etag": "sha256:4eebf57396376d5b7801eb92bdaf3075254e8cb8f50e00a14bfe1baf17ab5078",
      "unit_scales": {
        "price": "quote-currency price level (a difference of prices is also in price units)"
      }
    },
    {
      "altitude": "cross_section",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "cross_sectional"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Cross-sectional rank of ``source`` among the universe's symbols on the current bar, 0 to 1.\n\nThe lowest symbol reads 0, the highest 1 (mid-rank for ties). With fewer than 2\nsymbols holding a value there is no rank: it is absent, so a comparison over it\nis unknown (not 0.5). ``source`` is evaluated once per symbol; it cannot carry a\n``symbol`` and cannot contain another cross-sectional operand. Requires a universe\nor portfolio strategy with two or more symbols.\n\nExample, the top tercile of the universe by 20-bar rate of change:\n  {\"kind\": \"rank\", \"source\": {\"kind\": \"indicator\", \"indicator\": \"roc\", \"period\": 20}}\ncompared with ``> 0.66``.",
      "discriminator_value": "rank",
      "families": [
        "value_refs",
        "cross_sectional"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "rank",
      "output_units": [
        {
          "note": "0 is the lowest symbol, 1 the highest; absent with fewer than 2 values",
          "range": {
            "max": 1.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "bounded_oscillator",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:rank",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:da753d90ff9d026ca67071247463495855728ea826f642f69cbb3a879288741f",
      "unit_scales": {
        "bounded_oscillator": "fixed-range oscillator; see range"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "value_expression"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition",
        "sizing"
      ],
      "description": "Highest value of `source` over the prior `lookback_bars` \u2014 **excludes the current bar**.\n\n``source`` accepts ANY value ref, not just a price field: an indicator, a\nspread, or a nested expression. That is what makes normalisations\ncomposable \u2014 e.g. a stochastic of the MACD line is\n``(macd - rolling_min(macd)) / (rolling_max(macd) - rolling_min(macd))``\nbuilt with ``binary_expr``, with no dedicated indicator type.\n\nTwo behaviours to design around, both deliberate:\n\n- **The current bar is excluded** (same convention as ``donchian``), so a\n  close-exceeds-max breakout is meaningful \u2014 the current bar cannot\n  contaminate its own threshold. For a stochastic you want an INCLUSIVE\n  window, so rebuild one with ``binary_expr``:\n  ``{\"kind\": \"binary_expr\", \"op\": \"max\", \"left\": <source>,\n     \"right\": {\"kind\": \"rolling_max\", \"source\": <source>,\n               \"lookback_bars\": N - 1}}``\n- **NaN propagates**: one missing value anywhere in the window returns NaN\n  (no silent zero-substitution while `source` is still warming up), and a\n  NaN operand makes the enclosing compare false. Indicators with their own\n  NaN-compacting buffers \u2014 ``srsi_k``, ``stochastic_k`` \u2014 do NOT behave\n  this way, which is why they are not redundant with this ref.",
      "discriminator_value": "rolling_max",
      "families": [
        "value_refs",
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "This expression accepts nested value references."
        }
      ],
      "name": "rolling_max",
      "output_units": [
        {
          "note": "highest of the prior N bars; excludes the current bar",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:rolling_max",
      "requires_state": [],
      "schema_etag": "sha256:45c2e22dfa329d5e1efa4776450ce6932d290f18cb227bd1af8b429cfd16bf8d",
      "unit_scales": {
        "same_as_source": "same unit and scale as the source operand"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "value_expression"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition",
        "sizing"
      ],
      "description": "Lowest value of `source` over the prior `lookback_bars` \u2014 **excludes the current bar**.\n\nThe mirror of ``rolling_max``; see that class for the composition pattern,\nthe inclusive-window workaround via ``binary_expr`` ``min``, and the\nNaN-propagation rule. ``source`` accepts any value ref, not just a price\nfield.",
      "discriminator_value": "rolling_min",
      "families": [
        "value_refs",
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "This expression accepts nested value references."
        }
      ],
      "name": "rolling_min",
      "output_units": [
        {
          "note": "lowest of the prior N bars; excludes the current bar",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:rolling_min",
      "requires_state": [],
      "schema_etag": "sha256:6c9b191a5c7712f851c1c3deef5b1d79a8a44fd08e71e819e4d03facd9e7494f",
      "unit_scales": {
        "same_as_source": "same unit and scale as the source operand"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "value_expression"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition",
        "sizing"
      ],
      "description": "A rolling statistic of `source` over `lookback_bars` \u2014 mean, std, zscore, sum, count, rank, percentile or ema.\n\n``source`` accepts ANY value ref, including a nested ``binary_expr``, so\nthis is the general smoothing and normalisation primitive: an SMA of an\narbitrary expression is ``stat=\"mean\"``, and a rolling z-score of a spread\nis ``stat=\"zscore\"``. Combined with ``rolling_max``/``rolling_min`` it\nexpresses whole indicator families that have no dedicated type \u2014 the %K of\na stochastic over any series is a 3-bar ``\"mean\"`` of the normalised ratio.\n\n**NaN propagates**: one missing value in the window returns NaN, and a NaN\noperand makes the enclosing compare false. Purpose-built indicators that\ncompact their buffers to finite samples (``srsi_k``, ``stochastic_k``)\nsurvive undefined stretches that this ref does not, so they are not\nredundant with it.\n\n``percentile_level`` is required when ``stat=\"percentile\"`` and must be\nomitted otherwise.",
      "discriminator_value": "rolling_stats",
      "families": [
        "value_refs",
        "volatility",
        "momentum",
        "volume"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "This expression accepts nested value references."
        }
      ],
      "name": "rolling_stats",
      "output_units": [
        {
          "note": "the window includes the current bar",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "stat": "mean"
          }
        },
        {
          "note": "population standard deviation, in source units",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "stat": "std"
          }
        },
        {
          "note": "unbounded",
          "range": null,
          "reason": null,
          "unit": "dimensionless",
          "when": {
            "stat": "zscore"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "stat": "sum"
          }
        },
        {
          "note": "the number of values in the window: always lookback_bars",
          "range": null,
          "reason": null,
          "unit": "count",
          "when": {
            "stat": "count"
          }
        },
        {
          "note": "1 to lookback_bars, not 0-1 and not 0-100",
          "range": null,
          "reason": null,
          "unit": "rank",
          "when": {
            "stat": "rank"
          }
        },
        {
          "note": "the VALUE at percentile_level, in source units: not a rank, unlike `percentile`",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "stat": "percentile"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "stat": "ema"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:rolling_stats",
      "requires_state": [],
      "schema_etag": "sha256:9883579fa733047255816555ccd94ac8f82889e8b229a5c94a06d0ae14da6ee5",
      "unit_scales": {
        "count": "a plain count",
        "dimensionless": "unitless number",
        "rank": "ordinal rank, 1 is the lowest",
        "same_as_source": "same unit and scale as the source operand"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "stateful"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Reference to a field of the bar that matched a named sequence step.\n\nAddress the bar that satisfied a specific step inside a specific\nSequenceCondition. Useful for \"stop at the retest bar's low\" in\nbreak-retest setups.\n\nLifecycle mirrors EntryBarValueRef: the snapshot is captured at step\nfire, preserved for the lifetime of the open position, cleared on\nposition close. NaN when no position is open or the step has not yet\nfired on the current match.\n\nFields:\n  - open / high / low / close: step-bar OHLC\n  - range: high - low\n  - body_high: max(open, close)\n  - body_low: min(open, close)",
      "discriminator_value": "sequence_step",
      "families": [
        "value_refs",
        "combinators"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "sequence_step",
      "output_units": [
        {
          "note": "range is a price difference",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:sequence_step",
      "requires_state": [],
      "schema_etag": "sha256:37b20d2a4ff050ed25dbab1ebe40ce58e49f4e70c1384a17d556c4bdb9d8e6a4",
      "unit_scales": {
        "price": "quote-currency price level (a difference of prices is also in price units)"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Session-level value reference.\n\nDay-scoped mode (default): resolves against the full trading day in the\nsession timezone. field in {open, high, low, close, prior_close,\nbars_into_session, range, mid}.\n\nIntraday window mode: set ``window_start`` (HH:MM wall-clock in the\nsession timezone) and ``window_duration_minutes`` to aggregate OHLC\nacross a fixed intraday slot (e.g., Asian session 00:00+480, ORB\n09:30+30). Before the window opens each day: NaN. During the window:\nevolving aggregate. After close: frozen aggregate for the rest of the\nday; resets at the next day's window_start. Fields prior_close and\nbars_into_session are day-scope only (not valid with a window).",
      "discriminator_value": "session",
      "families": [
        "value_refs",
        "time_and_events",
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "session",
      "output_units": [
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "session_field": "open"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "session_field": "high"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "session_field": "low"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "session_field": "close"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "session_field": "prior_close"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "session_field": "mid"
          }
        },
        {
          "note": "session high - session low: a price difference",
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "session_field": "range"
          }
        },
        {
          "note": null,
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "bar_count",
          "when": {
            "session_field": "bars_into_session"
          }
        },
        {
          "note": "1.0 inside the session, 0.0 outside",
          "range": {
            "max": 1.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "boolean",
          "when": {
            "session_field": "in_session"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:session",
      "requires_state": [],
      "schema_etag": "sha256:7fb83768b469e0fd9959938e80fafaa4e46b6334949b3e2636c958d1c3987479",
      "unit_scales": {
        "bar_count": "a number of bars",
        "boolean": "0.0 for false, 1.0 for true",
        "price": "quote-currency price level (a difference of prices is also in price units)"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "cross_sectional",
        "stateful"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Reference to a portfolio-level shared signal by name (VIB-2102).\n\nResolves only inside a multi-member portfolio that declares a matching\n``shared_signals`` entry; bound to a member-local metric at portfolio\ncompile time. Illegal in a standalone strategy.",
      "discriminator_value": "shared_signal",
      "families": [
        "value_refs",
        "cross_sectional"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "shared_signal",
      "output_units": [
        {
          "note": null,
          "range": null,
          "reason": "declared by the portfolio shared_signals entry this name binds to, not by this operand",
          "unit": "not_determined",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:shared_signal",
      "requires_state": [],
      "schema_etag": "sha256:8c4de65f01c611e02e06b01eb2c416ca1152970f23caebdd619665b6c02e7302",
      "unit_scales": {
        "not_determined": "not confirmed; see reason"
      }
    },
    {
      "altitude": "sleeve",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "cross_sectional",
        "relative_value"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "The value of ``source`` on another symbol of the universe, on the current bar.\n\n``symbol`` must be a member of the strategy's universe; one outside it never has\na value, so such a strategy is refused when it is compiled. ``source`` is\nevaluated on that symbol's own data, not this one's; it cannot carry a ``symbol``\nand cannot contain another cross-sectional operand. Requires a universe or\nportfolio strategy with two or more symbols.\n\nExample, QQQ's close, to compare this symbol's close with:\n  {\"kind\": \"sibling\", \"symbol\": \"QQQ\", \"source\": {\"kind\": \"price\", \"field\": \"close\"}}",
      "discriminator_value": "sibling",
      "families": [
        "value_refs",
        "cross_sectional"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "sibling",
      "output_units": [
        {
          "note": "the named symbol's own value of source",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:sibling",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:a65fb00c64596f63625c941c9248ae1f7f646af5de3a4868c14e1b904ccec550",
      "unit_scales": {
        "same_as_source": "same unit and scale as the source operand"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "dynamic_level",
        "stateful"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Price of a confirmed swing high/low \u2014 a bar whose extreme beats `strength` bars each side.\n\nConfirmation is **lagging by design**: a swing at bar N is not visible\nuntil bar ``N + strength``, because the bars to its right have to print\nfirst. That is what makes it lookahead-free, and it means the newest\nreadable swing is always at least ``strength`` bars old.\n\nThe comparison is strict, so a level matched exactly by a neighbouring bar\nnever forms a swing. ``offset`` counts back through confirmed swings\n(0 = most recent); typed absence if that many have not been confirmed yet.\nA comparison over that absent operand is UNKNOWN; the action boundary\ntakes no action.",
      "discriminator_value": "swing",
      "families": [
        "value_refs",
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "swing",
      "output_units": [
        {
          "note": "the confirmed swing's price (a price) when value_at_swing is omitted, otherwise the unit of value_at_swing; absent until a swing is confirmed",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:swing",
      "requires_state": [],
      "schema_etag": "sha256:68fd5efef968f7690e6b5b4a054aa8df9f6939455122a06a3c64d4c75637e7be",
      "unit_scales": {
        "same_as_source": "same unit and scale as the source operand"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "time_window"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Reference to the current bar's time field.\n\nVIB-1370 / VIB-1319: the sub-metric selector is named ``field`` across\nevery ValueRef-style type. The legacy name ``component`` was removed.\n\nCalendar/intraday fields: ``hour``, ``minute``, ``day_of_week`` (0=Mon),\n``day_of_month``, ``month`` (1=Jan), ``minutes_since_midnight``.\n\nSession-aware fields (use the strategy's session metadata):\n``minutes_to_close``, ``minutes_since_open``. Have no value for crypto (24h)\nand pre/post-market bars. A comparison over a missing value is unknown and\ntakes no action, negated or not: ``not(minutes_to_close <= 5)`` does not\nfire outside the session.",
      "discriminator_value": "time",
      "families": [
        "value_refs",
        "time_and_events"
      ],
      "incompatibilities": [
        {
          "incompatible_with": {
            "strategy.symbol": "asset with no trading session (24h)"
          },
          "reason": "Session-relative time fields resolve only on session-aware (equity) symbols. On a 24h asset they would silently be NaN, so the compiler rejects them instead of producing a never-firing condition.",
          "when": {
            "field": [
              "minutes_to_close",
              "minutes_since_open"
            ]
          }
        }
      ],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "time",
      "output_units": [
        {
          "note": null,
          "range": {
            "max": 23.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "calendar_index",
          "when": {
            "field": "hour"
          }
        },
        {
          "note": null,
          "range": {
            "max": 59.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "calendar_index",
          "when": {
            "field": "minute"
          }
        },
        {
          "note": "0 is Monday",
          "range": {
            "max": 6.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "calendar_index",
          "when": {
            "field": "day_of_week"
          }
        },
        {
          "note": null,
          "range": {
            "max": 31.0,
            "min": 1.0
          },
          "reason": null,
          "unit": "calendar_index",
          "when": {
            "field": "day_of_month"
          }
        },
        {
          "note": "1 is January",
          "range": {
            "max": 12.0,
            "min": 1.0
          },
          "reason": null,
          "unit": "calendar_index",
          "when": {
            "field": "month"
          }
        },
        {
          "note": null,
          "range": {
            "max": 1439.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "minutes",
          "when": {
            "field": "minutes_since_midnight"
          }
        },
        {
          "note": "session-aware; absent on 24h assets",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "minutes",
          "when": {
            "field": "minutes_to_close"
          }
        },
        {
          "note": "session-aware; absent on 24h assets",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "minutes",
          "when": {
            "field": "minutes_since_open"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:time",
      "requires_state": [],
      "schema_etag": "sha256:f5913f2bab9b078757bb79da9a085120cd3b98a2a2acfe36e3b3594609c9da3a",
      "unit_scales": {
        "calendar_index": "calendar ordinal; see range",
        "minutes": "a number of minutes"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "dynamic_level",
        "stateful"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Running highest or lowest value of ``source`` since the start of the run or since entry.\n\n``extreme`` chooses the maximum or the minimum and ``since`` the starting point.\nWith ``since: \"start\"`` (the default) it updates at the end of every bar, warm-up\nincluded, so a rule deciding at the close of bar t sees the extreme through bar t-1; a\nscheduled rule sees its frame bar included. With ``since: \"entry\"`` it is unset while\nflat, resets when a position opens from flat (not on a scale-in or a partial exit; a\nreversal opens from flat) and updates before decisions on each bar while invested, so a\nrule sees the extreme through the current bar. Absent values of ``source`` are skipped,\nand an unset value makes a comparison over it unknown. It keeps its state across a\npaper session's restarts. ``since: \"entry\"`` is refused in a signal scan, as every\noperation on the open position is.\n\nKnown gaps it inherits: a raw trailing ratchet built from it does not reset after it\nfires, ``since: \"entry\"`` folds in the whole bar of a mid-bar scheduled fill, and the\nreset runs only for the entry rule that filled. A ``since: \"entry\"`` value is refused\nanywhere inside a gate: a gate is evaluated while flat as well as invested, so a value\nthat resets at entry cannot be kept correct there. Use ``since: \"start\"``, or put the\ncondition on an exit. It returns the unit of ``source``.\n\nExample, the highest high since entry, to place a trailing exit under:\n  {\"kind\": \"tracked\", \"source\": {\"kind\": \"price\", \"field\": \"high\"}, \"extreme\": \"max\",\n   \"since\": \"entry\"}\ncompared with ``close`` using ``<``.",
      "discriminator_value": "tracked",
      "families": [
        "value_refs",
        "price_levels"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "tracked",
      "output_units": [
        {
          "note": "the running extreme of source; unset (comparison unknown) until a value arrives",
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:tracked",
      "requires_state": [],
      "schema_etag": "sha256:598caa260930e21ae2771ba7f0e76b8b3ba832f64511c47983eb8d085c0124d1",
      "unit_scales": {
        "same_as_source": "same unit and scale as the source operand"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "stateful"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "A statistic computed from the strategy's own closed-trade history.\n\n``field`` selects the metric: ``trade_count`` (closed trades so far),\n``consecutive_wins`` / ``consecutive_losses`` (current streak length),\n``last_pnl`` / ``last_pnl_pct`` (the most recently closed trade's PnL),\n``rolling_win_rate`` / ``rolling_avg_pnl_pct`` (win rate / average PnL%\nover the last ``lookback_bars`` closed trades \u2014 ``lookback_bars`` is REQUIRED for these\ntwo and forbidden for every other field, since it counts TRADES, not\nbars), or ``bars_since_last_exit``.\n\nBefore the first trade closes: ``trade_count``, ``consecutive_wins`` and\n``consecutive_losses`` are all-time counters and read ``0``. The other\nfive have no value yet -- a typed absence (``no_position``), not a number\n-- so a condition reading one is UNKNOWN and takes no action (neither\ntrue nor false), and a ``formula`` sizing over one is refused at compile\nbecause it could never size the first entry.\n\nVIB-1367 phase 4 / VIB-1319: the sub-metric selector is named ``field``\nacross every ValueRef-style type. The legacy name ``trade_metric`` was\nremoved.",
      "discriminator_value": "trade_history",
      "families": [
        "value_refs",
        "risk_management"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "trade_history",
      "output_units": [
        {
          "note": "closed trades; reads 0 before the first",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "count",
          "when": {
            "field": "trade_count"
          }
        },
        {
          "note": "current streak; reads 0 before the first trade",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "count",
          "when": {
            "field": "consecutive_wins"
          }
        },
        {
          "note": "current streak; reads 0 before the first trade",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "count",
          "when": {
            "field": "consecutive_losses"
          }
        },
        {
          "note": "absent before the first closed trade",
          "range": null,
          "reason": null,
          "unit": "currency_amount",
          "when": {
            "field": "last_pnl"
          }
        },
        {
          "note": "absent before the first closed trade",
          "range": null,
          "reason": null,
          "unit": "percent",
          "when": {
            "field": "last_pnl_pct"
          }
        },
        {
          "note": "of the last `lookback_bars` closed trades; 50 means half won",
          "range": {
            "max": 100.0,
            "min": 0.0
          },
          "reason": null,
          "unit": "percent",
          "when": {
            "field": "rolling_win_rate"
          }
        },
        {
          "note": "average over the last `lookback_bars` closed trades",
          "range": null,
          "reason": null,
          "unit": "percent",
          "when": {
            "field": "rolling_avg_pnl_pct"
          }
        },
        {
          "note": "absent before the first closed trade",
          "range": null,
          "reason": null,
          "unit": "bar_count",
          "when": {
            "field": "bars_since_last_exit"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:trade_history",
      "requires_state": [
        "trade_history"
      ],
      "schema_etag": "sha256:c0ddd8f3a94c03bf6dc86f1a1ac52b54b391e7a4c28ac2e150f60394ebcddc1d",
      "unit_scales": {
        "bar_count": "a number of bars",
        "count": "a plain count",
        "currency_amount": "account-currency amount",
        "percent": "percent: 2 means 2%"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "dynamic_level",
        "stateful"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition",
        "execution"
      ],
      "description": "Reference to the zone that fired the entry's ZoneCondition (VIB-591).\n\nResolves to a level of the *triggering* zone \u2014 the zone selected by the\nentry's ZoneCondition on the signal bar. An immutable snapshot is captured\ninto ``TradeContext`` so post-entry references (e.g. a standing stop-loss\nbound to the FVG's lower wick) keep resolving to the same zone for the\ntrade's lifetime. The id is retained for persisted-state compatibility.\n\nReturns NaN when no triggering zone is bound (no entry condition with a\nrequired ZoneCondition fired) and no compatibility lookup is available.",
      "discriminator_value": "triggering_zone",
      "families": [
        "value_refs",
        "price_levels",
        "custom_structures"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "triggering_zone",
      "output_units": [
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "level": "upper"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "level": "lower"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "price",
          "when": {
            "level": "mid"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:triggering_zone",
      "requires_state": [
        "triggering_zone"
      ],
      "schema_etag": "sha256:561c3938013e036787417f198d8242bcc8f7a6a2eae3e00aca5d9ea63c125868",
      "unit_scales": {
        "price": "quote-currency price level (a difference of prices is also in price units)"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "value_expression"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition",
        "sizing"
      ],
      "description": "Unary expression over another ValueRef.\n\nWraps a single operand with an op from {abs, neg, log, log10, sqrt, pct_change}.\nCompiles to a unary IRExpression.",
      "discriminator_value": "unary_expr",
      "families": [
        "value_refs"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [
        {
          "filters": {
            "altitudes": [],
            "authorities": [],
            "capabilities": [],
            "families": [],
            "kinds": [
              "value_ref"
            ],
            "recommended_roles": [],
            "requires_state": []
          },
          "kind": "query",
          "reason": "Each operand accepts a nested value reference or a plain number."
        }
      ],
      "name": "unary_expr",
      "output_units": [
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "op": "abs"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "op": "neg"
          }
        },
        {
          "note": "natural logarithm of the source",
          "range": null,
          "reason": null,
          "unit": "dimensionless",
          "when": {
            "op": "log"
          }
        },
        {
          "note": "base-10 logarithm of the source",
          "range": null,
          "reason": null,
          "unit": "dimensionless",
          "when": {
            "op": "log10"
          }
        },
        {
          "note": null,
          "range": null,
          "reason": "the unit is the square root of the source's unit",
          "unit": "not_determined",
          "when": {
            "op": "sqrt"
          }
        },
        {
          "note": "(current - prior) / prior * 100 over one bar",
          "range": null,
          "reason": null,
          "unit": "percent",
          "when": {
            "op": "pct_change"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:unary_expr",
      "requires_state": [],
      "schema_etag": "sha256:0ab5b260beb89e320f9bd079fc49d1a7332a84ca871e1dd440cb38c030b5904a",
      "unit_scales": {
        "dimensionless": "unitless number",
        "not_determined": "not confirmed; see reason",
        "percent": "percent: 2 means 2%",
        "same_as_source": "same unit and scale as the source operand"
      }
    },
    {
      "altitude": "symbol",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Traded volume of the current bar, or of a bar `offset` bars back.\n\nVolume is in **base-asset units** (shares, or coins for crypto) unless the\nrun is configured for quote units, in which case it is multiplied by that\nbar's close. Reading past the start of loaded history returns NaN.",
      "discriminator_value": "volume",
      "families": [
        "value_refs",
        "volume"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "volume",
      "output_units": [
        {
          "note": null,
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "volume",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:volume",
      "requires_state": [],
      "schema_etag": "sha256:94690dc319c25c29bf3cc05c82838fcedecbd7537836f4ddef9444f73cacf294",
      "unit_scales": {
        "volume": "traded volume units (shares, or coins for crypto)"
      }
    },
    {
      "altitude": "cross_section",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "cross_sectional"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Spread of ``source`` across the WHOLE universe on the current bar.\n\nUnlike ``rank`` and ``xs_zscore`` it does not say where this symbol sits; every\nsymbol reads the same number, so it does not degrade while this symbol's own\nvalue is still warming up. ``stat`` chooses the standard deviation or the range.\n``source`` is evaluated once per symbol; it cannot carry a ``symbol`` and cannot\ncontain another cross-sectional operand. Requires a universe or portfolio strategy\nwith two or more symbols.\n\nExample, how widely 20-bar returns are spread across the universe:\n  {\"kind\": \"xs_dispersion\", \"stat\": \"stdev\",\n   \"source\": {\"kind\": \"indicator\", \"indicator\": \"roc\", \"period\": 20}}",
      "discriminator_value": "xs_dispersion",
      "families": [
        "value_refs",
        "cross_sectional"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "xs_dispersion",
      "output_units": [
        {
          "note": "sample standard deviation (ddof=1)",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "stat": "stdev"
          }
        },
        {
          "note": "highest value minus lowest value",
          "range": {
            "max": null,
            "min": 0.0
          },
          "reason": null,
          "unit": "same_as_source",
          "when": {
            "stat": "range"
          }
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:xs_dispersion",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:ac91f6f56835d9fd1ffa582c12c95fb1045a15013212419682928fed51e65aa5",
      "unit_scales": {
        "same_as_source": "same unit and scale as the source operand"
      }
    },
    {
      "altitude": "cross_section",
      "attachable_roles": [],
      "authority": "signal",
      "capabilities": [
        "cross_sectional"
      ],
      "construct_with": null,
      "consumer_contexts": [
        "condition"
      ],
      "description": "Cross-sectional z-score of ``source`` among the universe's symbols on the current bar.\n\nHow many sample standard deviations this symbol's value sits from the universe\nmean. With fewer than 2 values, or when every symbol sits on the mean, there is no\nz-score: it is absent (not 0). ``source`` is evaluated once per symbol; it cannot\ncarry a ``symbol`` and cannot contain another cross-sectional operand. Requires a\nuniverse or portfolio strategy with two or more symbols.\n\nExample, how far this symbol's RSI is from the universe average:\n  {\"kind\": \"xs_zscore\", \"source\": {\"kind\": \"indicator\", \"indicator\": \"rsi\", \"period\": 14}}",
      "discriminator_value": "xs_zscore",
      "families": [
        "value_refs",
        "cross_sectional"
      ],
      "incompatibilities": [],
      "kind": "value_ref",
      "legacy_refs": [],
      "links": [],
      "name": "xs_zscore",
      "output_units": [
        {
          "note": "standard deviations from the universe mean; absent with fewer than 2 values or zero spread",
          "range": null,
          "reason": null,
          "unit": "dimensionless",
          "when": {}
        }
      ],
      "recommended_roles": [],
      "ref": "value_ref:xs_zscore",
      "requires_state": [
        "portfolio_universe"
      ],
      "schema_etag": "sha256:cff4916d36ffa0b2eeb163640611965bc70ceb1f0338cddb59bd8f53a7226676",
      "unit_scales": {
        "dimensionless": "unitless number"
      }
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "resource",
      "capabilities": [
        "dynamic_level",
        "resource_definition"
      ],
      "construct_with": null,
      "description": "Capture a bar and use one of its OHLC fields directly in a condition.",
      "families": [
        "custom_structures"
      ],
      "incompatibilities": [],
      "kind": "workflow",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this workflow dependency.",
          "ref": "resource:anchor"
        },
        {
          "kind": "detail",
          "reason": "Inspect this workflow dependency.",
          "ref": "value_ref:anchor"
        }
      ],
      "name": "anchor_signal_ref",
      "recommended_roles": [],
      "ref": "workflow:anchor_signal_ref",
      "requires_state": [
        "anchor"
      ],
      "schema_etag": "sha256:fded520fa9a42d6b4bb829686823b99a80fe4184c8312b81066cbd0687cadd81",
      "steps": [
        {
          "description": "Capture the source bar.",
          "detail_ref": "resource:anchor",
          "order": 1,
          "tool": "builder_save_anchor"
        },
        {
          "description": "Attach an entry/gate/exit using value_ref:anchor in compare or cross.",
          "detail_ref": "condition:compare",
          "order": 2,
          "tool": "add_rule"
        }
      ]
    },
    {
      "altitude": "strategy",
      "attachable_roles": [],
      "authority": "resource",
      "capabilities": [
        "dynamic_level",
        "resource_definition"
      ],
      "construct_with": null,
      "description": "Capture a bar, define a named price zone from it, then consume that zone in a condition.",
      "families": [
        "custom_structures"
      ],
      "incompatibilities": [],
      "kind": "workflow",
      "legacy_refs": [],
      "links": [
        {
          "kind": "detail",
          "reason": "Inspect this workflow dependency.",
          "ref": "resource:anchor"
        },
        {
          "kind": "detail",
          "reason": "Inspect this workflow dependency.",
          "ref": "resource:zone"
        },
        {
          "kind": "detail",
          "reason": "Inspect this workflow dependency.",
          "ref": "value_ref:named_zone"
        }
      ],
      "name": "named_anchor_zone",
      "recommended_roles": [],
      "ref": "workflow:named_anchor_zone",
      "requires_state": [
        "anchor"
      ],
      "schema_etag": "sha256:6da8ef2994b05cf6976dbd7eaa7860554562e42b661234cb8d4de59d9c62fe2c",
      "steps": [
        {
          "description": "Capture the source bar.",
          "detail_ref": "resource:anchor",
          "order": 1,
          "tool": "builder_save_anchor"
        },
        {
          "description": "Define upper and lower zone boundaries.",
          "detail_ref": "resource:zone",
          "order": 2,
          "tool": "builder_save_zone"
        },
        {
          "description": "Attach an entry/gate/exit using the saved zone in compare or cross.",
          "detail_ref": "condition:compare",
          "order": 3,
          "tool": "add_rule"
        }
      ]
    }
  ],
  "collection_examples": {
    "basket_equal_weight": [
      {
        "arguments": {
          "allocation": {
            "construction": {
              "kind": "equal_weight"
            }
          },
          "strategy_id": "<strategy_id>"
        },
        "description": "Use a multi-instrument strategy. Its rules trade independently; allocation is static.",
        "order": 1,
        "tool": "builder_set_allocation"
      }
    ],
    "basket_manual": [
      {
        "arguments": {
          "allocation": {
            "capital_model": "partitioned",
            "construction": {
              "kind": "manual",
              "weights": {
                "QQQ": 0.4,
                "SPY": 0.6
              }
            }
          },
          "strategy_id": "<strategy_id>"
        },
        "description": "Use a SPY/QQQ basket with independent trading rules. Weights cover instrument symbols exactly; static manual allocation requires partitioned capital.",
        "order": 1,
        "tool": "builder_set_allocation"
      }
    ],
    "basket_rank_based": [
      {
        "arguments": {
          "allocation": {
            "construction": {
              "kind": "rank_based",
              "score_ref": {
                "indicator": "roc",
                "kind": "indicator",
                "period": 20
              },
              "top_n": 2
            },
            "rebalance": {
              "kind": "calendar",
              "schedule": "weekly"
            }
          },
          "strategy_id": "<strategy_id>"
        },
        "description": "Use a multi-instrument position-hold strategy without entry/gate/exit/protective rules; construction owns positions.",
        "order": 1,
        "tool": "builder_set_allocation"
      }
    ],
    "basket_signal_proportional": [
      {
        "arguments": {
          "allocation": {
            "construction": {
              "kind": "signal_proportional",
              "score_ref": {
                "indicator": "roc",
                "kind": "indicator",
                "period": 20
              }
            },
            "rebalance": {
              "kind": "calendar",
              "schedule": "weekly"
            }
          },
          "strategy_id": "<strategy_id>"
        },
        "description": "Use a multi-instrument position-hold strategy; construction weights nonnegative scores and owns positions.",
        "order": 1,
        "tool": "builder_set_allocation"
      }
    ],
    "portfolio_equal_weight": [
      {
        "arguments": {
          "allocation": {
            "construction": {
              "kind": "equal_weight"
            }
          },
          "members": [
            {
              "strategy_id": "<member_a>"
            },
            {
              "strategy_id": "<member_b>"
            }
          ],
          "name": "Equal allocation",
          "project_id": "<project_id>"
        },
        "description": "Use owned member strategies in one project, asset class and timeframe. Member rules trade; equal allocation is static.",
        "order": 1,
        "tool": "create_portfolio"
      }
    ],
    "portfolio_manual": [
      {
        "arguments": {
          "allocation": {
            "capital_model": "partitioned",
            "construction": {
              "kind": "manual",
              "weights": {
                "<member_a>": 0.6,
                "<member_b>": 0.4
              }
            }
          },
          "members": [
            {
              "strategy_id": "<member_a>"
            },
            {
              "strategy_id": "<member_b>"
            }
          ],
          "name": "Manual allocation",
          "project_id": "<project_id>"
        },
        "description": "Weights cover member strategy IDs exactly, only in construction. Static manual allocation requires partitioned capital.",
        "order": 1,
        "tool": "create_portfolio"
      }
    ],
    "portfolio_member_signal_rotation": [
      {
        "arguments": {
          "allocation": {
            "capital_model": "partitioned",
            "construction": {
              "kind": "member_signal_rotation",
              "score_signal": "momentum",
              "top_n": 1
            },
            "rebalance": {
              "kind": "calendar",
              "schedule": "weekly"
            }
          },
          "members": [
            {
              "strategy_id": "<member_a>"
            },
            {
              "strategy_id": "<member_b>"
            }
          ],
          "name": "Member signal rotation",
          "project_id": "<project_id>",
          "shared_signals": [
            {
              "name": "momentum",
              "source": {
                "indicator": "roc",
                "kind": "indicator",
                "period": 20
              }
            }
          ]
        },
        "description": "Use long-only single-instrument members with unique symbols. Member entries still decide when flat members enter; rotation controls trims and top-ups.",
        "order": 1,
        "tool": "create_portfolio"
      }
    ],
    "portfolio_rank_based": [
      {
        "arguments": {
          "allocation": {
            "construction": {
              "kind": "rank_based",
              "score_signal": "momentum",
              "top_n": 1
            },
            "rebalance": {
              "kind": "calendar",
              "schedule": "weekly"
            }
          },
          "members": [
            {
              "strategy_id": "<member_a>"
            },
            {
              "strategy_id": "<member_b>"
            }
          ],
          "name": "Position-hold member ranking",
          "project_id": "<project_id>",
          "shared_signals": [
            {
              "name": "momentum",
              "source": {
                "indicator": "roc",
                "kind": "indicator",
                "period": 20
              }
            }
          ]
        },
        "description": "Use position-hold members without entry/gate/exit/protective rules. The declared shared signal feeds construction-managed ranking.",
        "order": 1,
        "tool": "create_portfolio"
      }
    ],
    "portfolio_trailing_return": [
      {
        "arguments": {
          "allocation": {
            "capital_model": "partitioned",
            "construction": {
              "kind": "trailing_return",
              "lookback_bars": 30,
              "top_n": 1
            },
            "rebalance": {
              "kind": "calendar",
              "schedule": "weekly"
            }
          },
          "members": [
            {
              "strategy_id": "<member_a>"
            },
            {
              "strategy_id": "<member_b>"
            }
          ],
          "name": "Member performance rotation",
          "project_id": "<project_id>"
        },
        "description": "Use long-only single-instrument members with unique symbols. Member rules trade; rotation trims benched members and tops up held positions.",
        "order": 1,
        "tool": "create_portfolio"
      }
    ],
    "portfolio_update": [
      {
        "arguments": {
          "patch": {
            "name": "Renamed research"
          },
          "portfolio_id": "<portfolio_id>"
        },
        "description": "A rename preserves membership, allocation and shared signals. Omission preserves; allocation null clears subject to portfolio cardinality; shared_signals [] clears subject to named-score validation.",
        "order": 1,
        "tool": "update_portfolio"
      }
    ]
  },
  "condition_classes": {
    "all_of": "predicate",
    "always_true": "predicate",
    "any_of": "predicate",
    "at_least": "predicate",
    "at_session": "schedule",
    "at_time": "schedule",
    "breakout_retest": "predicate",
    "calendar_schedule": "schedule",
    "candle_pattern": "predicate",
    "compare": "predicate",
    "condition_ref": "reference",
    "consecutive": "predicate",
    "cross": "predicate",
    "eod_flatten": "exit_policy",
    "fixed_targets": "exit_policy",
    "flag_pattern": "predicate",
    "fvg": "predicate",
    "in_set": "predicate",
    "latch": "predicate",
    "liquidity_sweep": "predicate",
    "not": "predicate",
    "order_block": "predicate",
    "ote": "predicate",
    "pennant_pattern": "predicate",
    "range": "predicate",
    "sequence": "predicate",
    "spread": "predicate",
    "trailing_stop": "exit_policy",
    "transition": "predicate"
  },
  "entry_semantics": {
    "accumulate": {
      "conflict_policy": "skip",
      "explanation": "position_policy.mode='accumulate': a SAME-direction entry signal while invested opens another lot rather than being blocked, until position_policy.max_positions lots are open. An opposite entry signal never reverses an open position. Even when an exit fills on that bar, the opposite entry is not placed; its complete entry group must fire again on a later bar while the strategy is flat.",
      "group_selection": "long_or_short",
      "opposite_signal_while_invested": "observed_only",
      "position_requirement": "flat_or_invested_below_max_positions",
      "post_exit_entry": "opposite_signal_must_fire_again_on_a_later_bar",
      "same_bar_reversal": "disabled",
      "same_direction_combination": "all_of"
    },
    "reverse": {
      "conflict_policy": "skip",
      "explanation": "position_policy.mode='reverse': an opposite entry signal while invested flips the position. The current side is closed with a reduce-only market order (fills next bar) and the opposite side is opened once flat (fills the bar after) WITHOUT its entry condition having to fire again. There is no same-bar cross-zero fill. A fresh signal for the side just left supersedes the pending flip, and both directions firing at once holds the position.",
      "group_selection": "long_or_short",
      "opposite_signal_while_invested": "flips_position",
      "position_requirement": "flat",
      "post_exit_entry": "opposite_signal_flips_the_position_at_the_next_bar_open",
      "reverse_on_opposite_signal": "next_bar_open",
      "same_bar_reversal": "disabled",
      "same_direction_combination": "all_of"
    },
    "scale_in": {
      "conflict_policy": "skip",
      "explanation": "position_policy.mode='scale_in': a SAME-direction entry signal while invested opens another lot rather than being blocked, until position_policy.max_positions lots are open. An opposite entry signal never reverses an open position. Even when an exit fills on that bar, the opposite entry is not placed; its complete entry group must fire again on a later bar while the strategy is flat.",
      "group_selection": "long_or_short",
      "opposite_signal_while_invested": "observed_only",
      "position_requirement": "flat_or_invested_below_max_positions",
      "post_exit_entry": "opposite_signal_must_fire_again_on_a_later_bar",
      "same_bar_reversal": "disabled",
      "same_direction_combination": "all_of"
    },
    "single": {
      "conflict_policy": "skip",
      "explanation": "An opposite entry signal never reverses an open position. Even when an exit fills on that bar, the opposite entry is not placed; its complete entry group must fire again on a later bar while the strategy is flat.",
      "group_selection": "long_or_short",
      "opposite_signal_while_invested": "observed_only",
      "position_requirement": "flat",
      "post_exit_entry": "opposite_signal_must_fire_again_on_a_later_bar",
      "same_bar_reversal": "disabled",
      "same_direction_combination": "all_of"
    }
  },
  "format_version": 2,
  "operation_scope": "registered_surface_not_authorization",
  "operations": [
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Add Rule",
        "toolGroup": "builder"
      },
      "description": "Save a condition and attach it as a rule in one call.\n\n        Does what builder_add_condition followed by builder_attach_rule does, and\n        checks everything both would check before saving anything: a refused call\n        leaves no definition and no rule behind. Use builder_add_condition,\n        builder_compose and builder_attach_rule instead to reuse one saved\n        definition in several rules or to combine saved definitions.\n\n        Roles: entry (requires direction 'long' or 'short'), exit (optional\n        direction and size_frac), gate (blocks entries while false). A stop,\n        target or trailing stop belongs in an exit rule, not an entry or gate.\n\n        Entry rules on the SAME side are ANDed on the same bar. Express\n        alternatives inside one any_of condition. Long/short groups are\n        alternatives; simultaneous signals place no entry. Position policy\n        controls repeated entries and reversal while invested.\n\n        Start with builder_discover(action='quickstart') for a complete example.\n        overview lists the complete grammar and units; get supplies exact primitive detail.\n        Inline sequence/Boolean children need no separate save/compose calls.\n        The complete machine-readable schema is action='specification'.\n\n        Returns definition_id, rule_id, name, source, source_version and description.\n        Use rule_id for builder_detach_rule.\n        ",
      "input_schema": {
        "$defs": {
          "Direction": {
            "description": "Trade direction.",
            "enum": [
              "long",
              "short"
            ],
            "title": "Direction",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "properties": {
          "condition": {
            "additionalProperties": true,
            "description": "Typed condition source with a \"kind\" discriminator. Read builder_discover(action='overview') once for the complete language; use action='get' for exact detail. Combinators may hold inline conditions or condition_ref children.",
            "title": "Condition",
            "type": "object"
          },
          "direction": {
            "anyOf": [
              {
                "$ref": "#/$defs/Direction"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Entry role: required ('long' or 'short'). Exit role: optionally scope the exit to that position direction; None means BOTH long and short. Not used for gates."
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional strategy-scoped definition name (snake_case, at most 48 chars, leading letter, unique within the strategy). Auto-generated if omitted.",
            "title": "Name"
          },
          "remainder_unprotected": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Exit role: explicit consent to leave a partial stop's remainder unprotected. Otherwise another exit must cover the remainder.",
            "title": "Remainder Unprotected"
          },
          "role": {
            "description": "Rule role: entry, exit, or gate (block entries)",
            "enum": [
              "entry",
              "exit",
              "gate"
            ],
            "title": "Role",
            "type": "string"
          },
          "scan_run_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional ID of the signal scan run that validated this condition.",
            "title": "Scan Run Id"
          },
          "size_frac": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "maximum": 1.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Exit role: fraction to close, greater than 0 through 1. None = full close.",
            "title": "Size Frac"
          },
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id",
          "role",
          "condition"
        ],
        "title": "add_ruleArguments",
        "type": "object"
      },
      "name": "add_rule"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Assess Overfitting Risk",
        "toolGroup": "backtest"
      },
      "description": "Use after iterating on a strategy (multiple backtests, sweeps, walk-forward) to gauge overfitting risk.\n\n        Looks at the strategy's full backtest history to score: iteration\n        trajectory (did Sharpe climb suspiciously across tweaks?), parameter\n        sensitivity (does perf collapse with small changes?), and trade\n        clustering (is edge concentrated in a few trades?). Returns a structured\n        risk assessment with a recommended next action (e.g. \"run walk_forward\",\n        \"drop, performance is regime-specific\").\n\n        Requires at least one prior backtest on `strategy_id`. Pairs with\n        walk_forward for out-of-sample validation.\n\n        Record the risk verdict and next action with project_write_scratchpad so\n        the assessment carries into your next session.\n\n        Args:\n            strategy_id: Strategy identifier.\n\n        Returns:\n            OverfittingAssessment with overall_risk, summary, and recommended_action.\n\n        Raises:\n            StructuredToolError: If strategy has no backtests.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "strategy_id": {
            "description": "Strategy identifier",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "assess_overfitting_riskArguments",
        "type": "object"
      },
      "name": "assess_overfitting_risk"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Add Condition Definition",
        "toolGroup": "builder"
      },
      "description": "Save a typed condition definition. Returns definition_id, source_version and name.\n\n        Multi-timeframe: set 'resolution' inside left/right value refs, e.g.:\n          {\"kind\": \"compare\", \"left\": {\"kind\": \"indicator\", \"indicator\": \"ema\",\n           \"period\": 14, \"resolution\": \"4h\"}, \"op\": \">\", \"right\": 50}\n        For a known value ref, use builder_discover(action='get', ref='value_ref:indicator') for the\n        direct schema; otherwise use builder_discover to find its typed ref first.\n\n        Cross-instrument market gate (e.g. \"only long when SPY is in uptrend\"):\n          {\"kind\": \"compare\", \"left\": {\"kind\": \"price\", \"field\": \"close\", \"symbol\": \"SPY\"},\n           \"op\": \">\", \"right\": {\"kind\": \"indicator\", \"indicator\": \"ema\",\n           \"period\": 200, \"symbol\": \"SPY\"}}\n\n        Cross-symbol arithmetic: set 'symbol' inside a price/indicator value ref\n        to read that field from ANOTHER instrument, then combine with binary_expr.\n        Relative strength vs a benchmark (this name's RSI minus SPY's RSI):\n          {\"kind\": \"compare\", \"left\": {\"kind\": \"binary_expr\", \"op\": \"-\",\n             \"left\": {\"kind\": \"indicator\", \"indicator\": \"rsi\", \"period\": 14},\n             \"right\": {\"kind\": \"indicator\", \"indicator\": \"rsi\", \"period\": 14,\n                       \"symbol\": \"SPY\"}},\n           \"op\": \">\", \"right\": 0}\n        Prefer normalized operands (rsi, percentile, xs_zscore) when the two\n        instruments trade at different price scales: a raw close-minus-close\n        difference between, say, a $100 stock and $60,000 BTC is dominated by\n        the larger quote and is effectively a constant. 'symbol' cannot be\n        combined with 'resolution' on the same ref, and is rejected inside the\n        per-sibling source of rank/xs_zscore/xs_dispersion operands\n        (an absolute symbol there makes every sibling resolve the same value).\n\n        Event payload fields: event_type_id identifies the feed; event_field is\n        the scalar value ref used in compare/cross conditions. Do NOT use\n        {\"kind\": \"event_type\"} as left/right \u2014 event_type is not a value-ref\n        discriminator. For a caller's own custom event types, pass the bare\n        slug you registered (e.g. 'my-signal'), not the full internal\n        custom.{uid}.{slug} storage id.\n\n        Compare a macro/event payload field against a constant:\n          {\"kind\": \"compare\",\n           \"left\": {\"kind\": \"event_field\",\n                   \"event_type_id\": \"macro.fed_balance_sheet\",\n                   \"event_field\": \"ratio\"},\n           \"op\": \">\", \"right\": 1.0}\n\n        event_field is valid on right too, for event-provided thresholds:\n          {\"kind\": \"compare\",\n           \"left\": {\"kind\": \"price\", \"field\": \"close\"},\n           \"op\": \">\",\n           \"right\": {\"kind\": \"event_field\",\n                   \"event_type_id\": \"macro.fed_balance_sheet\",\n                   \"event_field\": \"threshold\"}}\n\n        Bidirectional event entries: add one event_field compare definition and attach\n        it as entry direction=\"long\"; add another event_field compare definition and\n        attach it as entry direction=\"short\". Long and short entry groups are\n        alternatives; same-bar reversal remains disabled.\n        builder_add_condition only creates a definition; it is inert until\n        builder_attach_rule wires it into entry/exit/gate. After adding event definitions,\n        call builder_get_strategy and confirm they appear in builder.rules and\n        entry_groups, not unattached_definitions. Directional exits must also be\n        attached to their side, e.g. role=\"exit\", direction=\"long\" and\n        role=\"exit\", direction=\"short\".\n\n        Cross-sectional conditions (multi-sleeve / universe strategies only \u2014\n        single-symbol strategies reject these at compile time). Each compares\n        this sleeve's value against portfolio siblings on the current bar.\n        builder_discover(action='list', filters={'families': ['cross_sectional']})\n        lists every cross-sectional condition and value ref. The same measures are\n        also value refs (\"rank\", \"xs_zscore\", \"xs_dispersion\", \"sibling\") that go\n        wherever a compare, cross, range, in_set or transition accepts a value;\n        they are refused in a sizing formula, a fixed_targets stop_loss_price_ref,\n        a shared signal and an allocation score, which are evaluated for one\n        symbol at a time.\n\n        Top-decile momentum (rank in the upper 10% of the universe):\n          {\"kind\": \"compare\",\n           \"left\": {\"kind\": \"rank\", \"source\": {\n             \"kind\": \"indicator\", \"indicator\": \"roc\", \"period\": 20}},\n           \"op\": \">\", \"right\": 0.9}\n\n        Pairs trade leg (long this sleeve when its close < QQQ's close):\n          {\"kind\": \"compare\", \"left\": {\"kind\": \"price\", \"field\": \"close\"},\n           \"op\": \"<\", \"right\": {\"kind\": \"sibling\", \"symbol\": \"QQQ\",\n             \"source\": {\"kind\": \"price\", \"field\": \"close\"}}}\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "condition": {
            "additionalProperties": true,
            "description": "Typed condition source with a consistent \"kind\" discriminator. Use builder_discover(action='get', ref=<ref>) for a known kind's direct schema. Otherwise start with builder_discover(action='facets'), then list exact filters and get a returned ref. For saved named zones, create the zone with builder_save_zone, then use compare/cross with value_ref:named_zone on left/right. Inspect 'pattern:named_zone_compare', 'pattern:named_zone_cross', and 'value_ref:named_zone' for examples.",
            "title": "Condition",
            "type": "object"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional strategy-scoped agent-facing identifier (snake_case, \u226448 chars, leading letter, unique within strategy, cannot be 'entry'/'exit'/'gate'/'overlay' or match the auto-ID shape 'c_<8 hex chars>'). If omitted, a deterministic name is auto-generated from the condition spec (e.g. 'close_gt_ema20'). Use this name when addressing the definition in sweep override labels: {\"label\": \"entry.<name>\", ...}. Rename later via builder_rename_definition.",
            "title": "Name"
          },
          "scan_run_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional ID of the signal scan run that validated this condition. Pass this when adding a condition that was validated by signal_scan to link the evidence back to the definition.",
            "title": "Scan Run Id"
          },
          "strategy_id": {
            "description": "Strategy ID from create_strategy",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id",
          "condition"
        ],
        "title": "builder_add_conditionArguments",
        "type": "object"
      },
      "name": "builder_add_condition"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Attach Rule",
        "toolGroup": "builder"
      },
      "description": "Use after saving a definition with builder_add_condition or builder_compose.\n\n        Creates a rule that uses a definition so the engine evaluates it during\n        backtests. Each strategy needs at least one entry rule to trade.\n\n        Roles:\n          - entry: open a position when the condition fires (requires direction='long' or 'short')\n          - exit: close the position when the condition fires (size_frac controls partial\n            exits). Set direction='long' or 'short' to scope the exit; omit direction\n            to apply it to BOTH sides.\n          - gate: block all entries when the condition is false (executed first)\n\n        Example: builder_attach_rule(strategy_id, definition_id, role=\"entry\", direction=\"long\").\n\n        Combining multiple rules in one role:\n          - Entry rules with the SAME direction are ANDed: every rule in that\n            direction's group must fire on the same bar.\n          - Long and short entry groups are alternatives. If only the long group\n            fires the strategy enters long; if only the short group fires it enters\n            short. If both groups fire on one bar, the signal is a conflict and no\n            entry order is placed.\n          - Attaching 2+ gate rules ANDs them: ALL must be true to allow entries.\n          - Attaching 2+ exit rules keeps them independent: ANY firing closes.\n            Complementary partial stops form a complete ladder. A partial stop\n            requires another exit covering the remainder unless remainder_unprotected\n            is explicitly true. Duplicate target or trail producers are refused.\n          An opposite-direction signal while invested depends on\n          position_policy.mode. Under single/accumulate/scale_in it is recorded but\n          not acted on: even if an exit fills on that bar, no opposite entry is\n          placed, and the complete opposite entry group must fire again on a later\n          bar while flat. Under 'reverse' it flips the position: the current side\n          closes at the next bar's open and the opposite side opens the bar after,\n          without its entry group firing again. No mode fills a same-bar reversal.\n          Exits with no direction and sizing are shared by both sides.\n          To express OR / NOT / sequence WITHIN one direction or for gates, do NOT attach several\n          definitions \u2014 combine them into one definition with builder_compose (kind=\"any_of\" / \"not\" /\n          \"sequence\") and attach that definition. Attaching twice never means OR.\n\n        Exit precedence: fixed_targets TP/SL and trailing_stop do NOT compile to\n        ranked exit rules at all \u2014 they become broker standing orders that fill\n        intrabar at their own trigger price, so they are not ordered against\n        condition exits. The condition exits that remain (including a\n        fixed_targets time_stop_bars) all carry the same priority, so when\n        several could fire on the same bar the engine exits via the first one in\n        rule order.\n\n        Returns the persisted rule_id plus definition_id. Use rule_id for builder_detach_rule.\n        ",
      "input_schema": {
        "$defs": {
          "Direction": {
            "description": "Trade direction.",
            "enum": [
              "long",
              "short"
            ],
            "title": "Direction",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "properties": {
          "definition_id": {
            "description": "ConditionDefinition ID to attach",
            "title": "Definition Id",
            "type": "string"
          },
          "direction": {
            "anyOf": [
              {
                "$ref": "#/$defs/Direction"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Entry role: required ('long' or 'short'). Exit role: optionally scope the exit to that position direction; None means BOTH long and short. Not used for gates."
          },
          "remainder_unprotected": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Explicit permission to leave a partial stop remainder unprotected (exit only)",
            "title": "Remainder Unprotected"
          },
          "role": {
            "description": "ConditionDefinition role: entry, exit, or gate (block entries)",
            "enum": [
              "entry",
              "exit",
              "gate"
            ],
            "title": "Role",
            "type": "string"
          },
          "size_frac": {
            "anyOf": [
              {
                "exclusiveMinimum": 0.0,
                "maximum": 1.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Exit role: fraction to close, greater than 0 through 1. None = full close.",
            "title": "Size Frac"
          },
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id",
          "definition_id",
          "role"
        ],
        "title": "builder_attach_ruleArguments",
        "type": "object"
      },
      "name": "builder_attach_rule"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Clone Strategy",
        "toolGroup": "builder"
      },
      "description": "Deep-copy a strategy into a new draft, duplicating all definitions and rules.\n\n        Useful for iterating on a variant without modifying the original. The clone\n        starts in 'draft' status and inherits symbol, timeframe, all condition definitions,\n        and the sizing / position_policy / execution / risk_policy / allocation config.\n        Saved anchors and zones are NOT copied \u2014 re-create them on the clone with\n        builder_save_anchor / builder_save_zone.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Name for the cloned strategy; defaults to the source name",
            "title": "Name"
          },
          "strategy_id": {
            "description": "ID of the strategy to clone",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "builder_clone_strategyArguments",
        "type": "object"
      },
      "name": "builder_clone_strategy"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Compile Strategy",
        "toolGroup": "builder"
      },
      "description": "Use when ready to backtest: validate, compile, then freeze the strategy.\n\n        Validates completeness first (entries attached, bidirectional strategies\n        use market orders, reverse mode has both entry directions, directional exit scopes match\n        an entry group, standing-order IDs do not collide, risk policy is consistent,\n        etc.), then runs the same strategy compiler a backtest runs. Anything\n        either step refuses (e.g. a sizing formula that can never size the first\n        entry) raises a VALIDATION_ERROR naming the problem and does NOT create\n        a revision \u2014 fix it and call again. Warnings do not block compilation\n        and are returned in the result's warnings list: both completeness\n        warnings (e.g. no exit attached) and compiler advisories (e.g. a\n        not(...) that fires on bars where its reference has no value).\n\n        Call after all entries/exits/gates have been attached via builder_attach_rule\n        and sizing/risk are configured. Returns blueprint + revision_id;\n        next call is run_backtest(strategy_id=...) which uses the latest revision.\n\n        Safe to call repeatedly, but not idempotent: each call snapshots\n        current state into a NEW revision_id, even if nothing changed since\n        the last call.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "strategy_id": {
            "description": "Strategy ID to compile",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "builder_compileArguments",
        "type": "object"
      },
      "name": "builder_compile"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Compose Conditions",
        "toolGroup": "builder"
      },
      "description": "Create a reusable definition with ordinary typed references or inline sequence steps.\n\n        Use kind=all_of/any_of/not/at_least/consecutive with definition_ids.\n        For kind=sequence use steps=[{condition: {kind: condition_ref, definition_id: ...}, within_bars: 6}].\n        Each step accepts condition, optional id, within_bars and hold_bars.\n        builder_discover(ref=\"condition:sequence\") documents the canonical step grammar.\n        The standard source parser validates inline predicates and references.\n        Policy exits are attached as separate exit rules.\n        ",
      "input_schema": {
        "$defs": {
          "CombinatorMode": {
            "description": "The ways ``builder_compose`` can combine saved condition definitions.\n\nOne declaration for a vocabulary that was written out four times: this set,\nand ``builder_compose`` parameters.\n\nNot to be confused with ``signal_sweep.COMBINATOR_TYPES``, which is a\nDIFFERENT four-member set (``allOf``/``anyOf``/``not``/``sequence``) naming\nthe combinators a condition sweep knows how to expand through.",
            "enum": [
              "all_of",
              "any_of",
              "not",
              "sequence",
              "consecutive",
              "at_least"
            ],
            "title": "CombinatorMode",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "properties": {
          "definition_ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Definition Ids"
          },
          "kind": {
            "$ref": "#/$defs/CombinatorMode"
          },
          "min_true": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Min True"
          },
          "sequence_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Sequence Id"
          },
          "steps": {
            "anyOf": [
              {
                "items": {
                  "additionalProperties": true,
                  "type": "object"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Steps"
          },
          "strategy_id": {
            "title": "Strategy Id",
            "type": "string"
          },
          "strict": {
            "default": true,
            "title": "Strict",
            "type": "boolean"
          },
          "window_bars": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Window Bars"
          }
        },
        "required": [
          "strategy_id",
          "kind"
        ],
        "title": "builder_composeArguments",
        "type": "object"
      },
      "name": "builder_compose"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Delete Price Anchor",
        "toolGroup": "builder"
      },
      "description": "Delete a named anchor. Returns NOT_FOUND if `anchor_id` does not exist.\n\n        A condition or zone boundary that still references the anchor fails at\n        compile time. Deleting moves a ready strategy back to draft.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "anchor_id": {
            "description": "Anchor ID to delete",
            "title": "Anchor Id",
            "type": "string"
          },
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id",
          "anchor_id"
        ],
        "title": "builder_delete_anchorArguments",
        "type": "object"
      },
      "name": "builder_delete_anchor"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Delete Condition ConditionDefinition",
        "toolGroup": "builder"
      },
      "description": "Delete a condition definition and its rules. Refuse deletion while another definition or resource references it.",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "definition_id": {
            "description": "ConditionDefinition ID to delete",
            "title": "Definition Id",
            "type": "string"
          },
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id",
          "definition_id"
        ],
        "title": "builder_delete_conditionArguments",
        "type": "object"
      },
      "name": "builder_delete_condition"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Delete Strategy",
        "toolGroup": "builder"
      },
      "description": "Permanently delete a strategy and all its definitions.\n\n        Refused while any live paper trading session references the strategy \u2014 stop\n        paper trading first. All condition definitions are cascade-deleted along with the strategy.\n        Works on a strategy whose stored document predates the current shape\n        (one listed in ``unreadable_strategies``).\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "strategy_id": {
            "description": "ID of the strategy to permanently delete",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "builder_delete_strategyArguments",
        "type": "object"
      },
      "name": "builder_delete_strategy"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Delete Price Zone",
        "toolGroup": "builder"
      },
      "description": "Delete a named zone. Returns NOT_FOUND if `zone_id` does not exist.\n\n        A condition that still references the zone fails at compile time.\n        Deleting moves a ready strategy back to draft.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          },
          "zone_id": {
            "description": "Zone ID to delete",
            "title": "Zone Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id",
          "zone_id"
        ],
        "title": "builder_delete_zoneArguments",
        "type": "object"
      },
      "name": "builder_delete_zone"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Detach ConditionDefinition From Role",
        "toolGroup": "builder"
      },
      "description": "Remove exactly one rule. Its definition is kept; use builder_delete_condition to delete it.\n\n        Requires the persistent rule_id returned by builder_attach_rule or\n        displayed by builder_get_strategy. A reusable definition may have multiple\n        rules, so definition_id is intentionally not accepted here.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "rule_id": {
            "description": "Persisted rule ID returned by builder_attach_rule",
            "pattern": "^att_[0-9a-f]{32}$",
            "title": "Rule Id",
            "type": "string"
          },
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id",
          "rule_id"
        ],
        "title": "builder_detach_ruleArguments",
        "type": "object"
      },
      "name": "builder_detach_rule"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Discover Builder Capabilities",
        "toolGroup": "builder"
      },
      "description": "Discover builder capabilities through hard types and exact filters.\n\n        Start with action='quickstart' for the mental model and a complete incremental\n        example. action='overview' lists the complete language and current entry\n        semantics. action='specification' publishes the full machine-readable\n        schema graph, units, context metadata, and registered operation contracts.\n        These actions do not imply authorization to invoke every registered operation.\n        No filters or ref are accepted by quickstart/overview/specification.\n\n        When the exact ref is known, call ``action='get'`` directly and skip\n        facets/list. When the relevant object kind or family is unknown, call\n        ``action='list'`` with no filters to enumerate every record, or\n        ``action='facets'`` for the legal filter values and their counts; then\n        ``action='get'`` with a returned ref. An empty ``list`` result carries\n        ``empty_result_guidance`` naming which requested facet values do not\n        co-occur. Results are deterministic, sorted by ref, never semantically\n        ranked, and never silently truncated.\n        ",
      "input_schema": {
        "$defs": {
          "DiscoveryFilters": {
            "additionalProperties": false,
            "properties": {
              "altitudes": {
                "default": [],
                "items": {
                  "enum": [
                    "symbol",
                    "pair",
                    "sleeve",
                    "cross_section",
                    "strategy",
                    "portfolio"
                  ],
                  "type": "string"
                },
                "title": "Altitudes",
                "type": "array"
              },
              "authorities": {
                "default": [],
                "items": {
                  "enum": [
                    "signal",
                    "position_policy",
                    "sizing",
                    "execution",
                    "risk",
                    "construction",
                    "resource",
                    "documentation"
                  ],
                  "type": "string"
                },
                "title": "Authorities",
                "type": "array"
              },
              "capabilities": {
                "default": [],
                "items": {
                  "enum": [
                    "level_state",
                    "edge_trigger",
                    "discrete_transition",
                    "reentry",
                    "breakout",
                    "composition",
                    "sequence",
                    "recurring_schedule",
                    "time_window",
                    "event_payload",
                    "stateful",
                    "dynamic_level",
                    "relative_value",
                    "cross_sectional",
                    "portfolio_construction",
                    "execution",
                    "exit_management",
                    "value_expression",
                    "resource_definition"
                  ],
                  "type": "string"
                },
                "title": "Capabilities",
                "type": "array"
              },
              "families": {
                "default": [],
                "items": {
                  "enum": [
                    "bands",
                    "combinators",
                    "cross_sectional",
                    "custom_structures",
                    "execution",
                    "indicators",
                    "momentum",
                    "patterns",
                    "price_levels",
                    "price_signals",
                    "risk_management",
                    "strategy_config",
                    "temporal",
                    "time_and_events",
                    "trend",
                    "value_refs",
                    "volatility",
                    "volume"
                  ],
                  "type": "string"
                },
                "title": "Families",
                "type": "array"
              },
              "kinds": {
                "default": [],
                "items": {
                  "enum": [
                    "condition",
                    "combinator",
                    "value_ref",
                    "indicator_shape",
                    "execution_price",
                    "config",
                    "resource",
                    "workflow",
                    "recipe"
                  ],
                  "type": "string"
                },
                "title": "Kinds",
                "type": "array"
              },
              "recommended_roles": {
                "default": [],
                "items": {
                  "enum": [
                    "entry",
                    "exit",
                    "gate"
                  ],
                  "type": "string"
                },
                "title": "Recommended Roles",
                "type": "array"
              },
              "requires_state": {
                "default": [],
                "items": {
                  "enum": [
                    "previous_bar",
                    "entry_bar",
                    "live_position",
                    "trade_history",
                    "strategy_equity",
                    "portfolio_universe",
                    "event_data",
                    "anchor",
                    "named_zone",
                    "triggering_zone"
                  ],
                  "type": "string"
                },
                "title": "Requires State",
                "type": "array"
              }
            },
            "title": "DiscoveryFilters",
            "type": "object"
          }
        },
        "additionalProperties": false,
        "properties": {
          "action": {
            "description": "quickstart teaches incremental authoring with a complete example; overview lists the complete language; specification returns its machine-readable schema graph and operation contracts. get fetches a known exact ref in one call; list returns compact matching records; facets lists exact filter values when the domain is unknown.",
            "enum": [
              "quickstart",
              "overview",
              "specification",
              "facets",
              "list",
              "get"
            ],
            "title": "Action",
            "type": "string"
          },
          "detail": {
            "default": "compact",
            "description": "For overview, compact shows all typed signatures; full adds defaults and bounds. Projection for action='list': 'compact' returns only canonical ref, kind, and condition discriminator; 'full' returns all filtering metadata. Ignored by quickstart/facets/get/specification because those actions have one fixed projection.",
            "enum": [
              "compact",
              "full"
            ],
            "title": "Detail",
            "type": "string"
          },
          "filters": {
            "anyOf": [
              {
                "$ref": "#/$defs/DiscoveryFilters"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Exact filters for action='list'. AND across fields, OR within each array. Omit or leave empty to enumerate the whole registry."
          },
          "ref": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Canonical or documented alias for action='get'. If the exact type is known, call get directly (for example condition:trailing_stop).",
            "title": "Ref"
          }
        },
        "required": [
          "action"
        ],
        "title": "builder_discoverArguments",
        "type": "object"
      },
      "name": "builder_discover"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Edit Strategy",
        "toolGroup": "builder"
      },
      "description": "Update strategy metadata. Changing symbols/timeframe resets to draft.",
      "input_schema": {
        "$defs": {
          "Timeframe": {
            "description": "Bar duration. These seven are the only granularities the data layer serves.",
            "enum": [
              "1m",
              "5m",
              "15m",
              "30m",
              "1h",
              "4h",
              "1d"
            ],
            "title": "Timeframe",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "properties": {
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "New strategy name; shortened to 5 words / 48 chars and versioned on collision.",
            "title": "Name"
          },
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          },
          "symbols": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "minItems": 1,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "New list of trading symbols. Single-instrument: ['ETH-USD']. Basket: ['AAPL', 'MSFT', 'GOOG']. Replaces the existing Strategy.instruments entirely; resets status to draft. 13 tickers name both an equity and a crypto pair (LTC, DASH, LINK, ...); those are rejected as ambiguous \u2014 say 'LTC-USD' for the crypto pair or 'EQ:LTC' for the equity.",
            "title": "Symbols"
          },
          "timeframe": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "New timeframe. Resets to draft."
          },
          "volume_units": {
            "anyOf": [
              {
                "enum": [
                  "base",
                  "quote"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "'base' (exchange-native) or 'quote' (volume * close). Default: base.",
            "title": "Volume Units"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "builder_edit_strategyArguments",
        "type": "object"
      },
      "name": "builder_edit_strategy"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Get Strategy",
        "toolGroup": "builder"
      },
      "description": "Get strategy details including definitions, rules, and compilation status.\n\n        Entry rules include their long/short direction. ``builder.entry_groups``\n        shows the rules ANDed within each direction, and ``entry_behavior``\n        describes cross-direction selection, conflict, and reversal behavior for\n        the strategy's ``position_policy.mode``: the default modes never reverse an\n        open position (the opposite group must fire again while flat), while\n        ``reverse`` flips to the opposite side on an opposite signal (the close\n        fills at the next bar's open and the opposite side opens the bar after).\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "builder_get_strategyArguments",
        "type": "object"
      },
      "name": "builder_get_strategy"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "List Strategies",
        "toolGroup": "builder"
      },
      "description": "List strategies with optional filters.\n\n        When the user asks about strategies \"in this project\" or scopes the\n        request to a project, you MUST pass ``project_id``. Calls without\n        ``project_id`` return the caller's recent strategies across all of\n        their projects and must not be presented as a project-scoped answer\n        (VIB-1483).\n\n        A strategy saved by an earlier version of the platform that no longer\n        matches the current shape is returned in ``unreadable_strategies`` (id\n        and reason) instead of ``strategies``; tell the user it exists and\n        cannot be opened rather than omitting it.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "limit": {
            "default": 20,
            "description": "Max results (default 20, max 100)",
            "maximum": 100,
            "minimum": 1,
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "default": 0,
            "description": "Skip N results for pagination",
            "maximum": 10000,
            "minimum": 0,
            "title": "Offset",
            "type": "integer"
          },
          "project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Filter to strategies in a specific research project. REQUIRED when scoping results to a project \u2014 without this, results are a global recent list and MUST NOT be narrated to the user as project-scoped.",
            "title": "Project Id"
          },
          "status": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Filter by status: \"ready\" or \"draft\"",
            "title": "Status"
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Filter by symbol (e.g. \"SPY\")",
            "title": "Symbol"
          }
        },
        "title": "builder_list_strategiesArguments",
        "type": "object"
      },
      "name": "builder_list_strategies"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Rename Condition ConditionDefinition",
        "toolGroup": "builder"
      },
      "description": "Rename a condition definition to a new agent-facing identifier.\n\n        The definition_id stays the same; only the canonical agent-facing name\n        changes. New sweep calls must use the new name. Past sweep results\n        recorded under the old name still reference the same definition_id.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "definition_id": {
            "description": "ConditionDefinition ID to rename",
            "title": "Definition Id",
            "type": "string"
          },
          "new_name": {
            "description": "New strategy-scoped agent-facing identifier. snake_case, 1\u201348 chars, leading letter, unique within the strategy. Cannot be one of {entry, exit, gate, overlay} or match the auto-ID shape 'c_<8 hex chars>'.",
            "title": "New Name",
            "type": "string"
          },
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id",
          "definition_id",
          "new_name"
        ],
        "title": "builder_rename_definitionArguments",
        "type": "object"
      },
      "name": "builder_rename_definition"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Save Price Anchor",
        "toolGroup": "builder"
      },
      "description": "Create or update (by `id`) a named anchor: one bar captured during the run, then held.\n\n        `source` picks the bar: `timestamp` (the first bar at or after an ISO 8601\n        time), `bar_index` (a zero-based bar index), or `condition_trigger` (a\n        false-to-true transition of an embedded condition). Conditions read it\n        through {\"kind\": \"anchor\", \"anchor_id\": <id>, \"anchor_field\":\n        \"open\"|\"high\"|\"low\"|\"close\"|\"mid\"|\"range\"}; that ref has no value until\n        the anchor captures, so conditions reading it do not fire before then.\n        Anchor fields can also bound a zone (builder_save_zone). `id` starts\n        with a letter and uses letters, digits, '_' or '-' (max 64 chars).\n        Saving moves a ready strategy back to draft.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "anchor": {
            "additionalProperties": true,
            "description": "Anchor definition. Example: {'id':'swing_low','source':{'kind':'bar_index','bar_index':5}} or {'id':'breakout_ref','source':{'kind':'condition_trigger','condition':{...}}}",
            "title": "Anchor",
            "type": "object"
          },
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id",
          "anchor"
        ],
        "title": "builder_save_anchorArguments",
        "type": "object"
      },
      "name": "builder_save_anchor"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Save Price Zone",
        "toolGroup": "builder"
      },
      "description": "Create or update (by `id`) a named price zone bounded by `upper` and `lower`.\n\n        Each boundary is a static price, a constant ref, or an anchor ref\n        ({\"kind\": \"anchor\", \"anchor_id\": ..., \"anchor_field\": ...}; save the\n        anchor first with builder_save_anchor). Conditions read the zone through\n        {\"kind\": \"named_zone\", \"zone_id\": <id>, \"zone_field\": \"upper\"|\"lower\"|\"mid\"};\n        mid is (upper + lower) / 2 and cannot be set. When both boundaries are\n        constants, lower must not exceed upper. Saving moves a ready strategy\n        back to draft. builder_discover(action='get', ref='workflow:named_anchor_zone')\n        returns the anchor -> zone -> condition sequence.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          },
          "zone": {
            "additionalProperties": true,
            "description": "Named zone definition. Example: {'id':'pullback_zone','upper':{'kind':'anchor','anchor_id':'session_open','anchor_field':'high'},'lower':{'kind':'anchor','anchor_id':'session_open','anchor_field':'low'}}",
            "title": "Zone",
            "type": "object"
          }
        },
        "required": [
          "strategy_id",
          "zone"
        ],
        "title": "builder_save_zoneArguments",
        "type": "object"
      },
      "name": "builder_save_zone"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Set Basket Allocation",
        "toolGroup": "builder"
      },
      "description": "Set cross-instrument basket allocation using one collection policy.\n\n        Equal weight and manual weights use no rebalance. Manual construction\n        supplies weights keyed by every basket symbol, summing to 1, and requires\n        partitioned capital. Rank based holds top_n instruments by\n        construction.score_ref, with optional exit_top_n hysteresis. Signal\n        proportional weights every instrument by construction.score_ref. Both\n        rotations require a calendar rebalance and a raw indicator score, such\n        as {'kind': 'indicator', 'indicator': 'roc', 'period': 20}.\n\n        A basket needs two or more instruments. Rotation owns position lifecycle\n        and cannot coexist with standing entry/exit rules. Within-instrument\n        sizing remains builder_set_strategy_config(patch={'sizing': ...}).\n        Returns the persisted allocation and its description.\n        ",
      "input_schema": {
        "$defs": {
          "ADXIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "adx_di",
                "default": "adx_di",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "output": {
                "default": "adx",
                "enum": [
                  "adx",
                  "plus_di",
                  "minus_di"
                ],
                "type": "string"
              },
              "period": {
                "default": 14,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "AVWAPIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "anchor": {
                "default": "session",
                "enum": [
                  "session",
                  "session_open",
                  "week",
                  "week_open",
                  "month",
                  "month_open",
                  "month_start",
                  "ytd",
                  "custom"
                ],
                "type": "string"
              },
              "anchor_datetime": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "indicator": {
                "const": "avwap",
                "default": "avwap",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "output": {
                "default": "value",
                "enum": [
                  "value",
                  "std_dev"
                ],
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "AdIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "ad",
                "default": "ad",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "AnchorPeriod": {
            "enum": [
              "session",
              "week",
              "month"
            ],
            "type": "string"
          },
          "AroonIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "aroon",
                "default": "aroon",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "line": {
                "enum": [
                  "up",
                  "down"
                ],
                "type": "string"
              },
              "period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "period",
              "line"
            ],
            "type": "object"
          },
          "BandOutput": {
            "enum": [
              "upper",
              "middle",
              "lower"
            ],
            "type": "string"
          },
          "BasketAllocationAuthoring": {
            "additionalProperties": false,
            "properties": {
              "capital_model": {
                "default": "partitioned",
                "enum": [
                  "partitioned",
                  "shared_pool"
                ],
                "type": "string"
              },
              "collection_risk": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CollectionRiskPolicy"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "constraints": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CollectionAuthoringConstraints"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "construction": {
                "discriminator": {
                  "mapping": {
                    "equal_weight": "#/$defs/EqualWeight",
                    "manual": "#/$defs/ManualWeights",
                    "rank_based": "#/$defs/BasketRankConstruction",
                    "signal_proportional": "#/$defs/SignalProportional_IndicatorValueRef_"
                  },
                  "propertyName": "kind"
                },
                "oneOf": [
                  {
                    "$ref": "#/$defs/EqualWeight"
                  },
                  {
                    "$ref": "#/$defs/ManualWeights"
                  },
                  {
                    "$ref": "#/$defs/BasketRankConstruction"
                  },
                  {
                    "$ref": "#/$defs/SignalProportional_IndicatorValueRef_"
                  }
                ],
                "required": [
                  "kind"
                ]
              },
              "rebalance": {
                "anyOf": [
                  {
                    "discriminator": {
                      "mapping": {
                        "calendar": "#/$defs/CalendarRebalance",
                        "none": "#/$defs/NoRebalance"
                      },
                      "propertyName": "kind"
                    },
                    "oneOf": [
                      {
                        "$ref": "#/$defs/NoRebalance"
                      },
                      {
                        "$ref": "#/$defs/CalendarRebalance"
                      }
                    ],
                    "required": [
                      "kind"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "construction"
            ],
            "type": "object"
          },
          "BasketRankConstruction": {
            "additionalProperties": false,
            "properties": {
              "exit_top_n": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "kind": {
                "const": "rank_based",
                "type": "string"
              },
              "score_ref": {
                "$ref": "#/$defs/IndicatorValueRef"
              },
              "top_n": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "kind",
              "score_ref",
              "top_n"
            ],
            "type": "object"
          },
          "BollingerValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "bollinger",
                "default": "bollinger",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 2.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "enum": [
                  "upper",
                  "middle",
                  "lower",
                  "bandwidth",
                  "stddev"
                ],
                "type": "string"
              },
              "period": {
                "default": 20,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "CalendarRebalance": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "calendar",
                "default": "calendar",
                "type": "string"
              },
              "min_interval_bars": {
                "default": 0,
                "minimum": 0,
                "type": "integer"
              },
              "schedule": {
                "$ref": "#/$defs/Rebalance"
              }
            },
            "required": [
              "schedule"
            ],
            "type": "object"
          },
          "CandlestickValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "candlestick",
                "default": "candlestick",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "pattern": {
                "$ref": "#/$defs/PatternName"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "pattern"
            ],
            "type": "object"
          },
          "CollectionAuthoringConstraints": {
            "additionalProperties": false,
            "properties": {
              "asset_class_caps": {
                "anyOf": [
                  {
                    "additionalProperties": {
                      "type": "number"
                    },
                    "type": "object"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_active_sleeves": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_position_pct": {
                "anyOf": [
                  {
                    "exclusiveMinimum": 0,
                    "maximum": 1,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "min_position_pct": {
                "anyOf": [
                  {
                    "exclusiveMaximum": 1,
                    "minimum": 0,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "CollectionRiskPolicy": {
            "additionalProperties": false,
            "properties": {
              "cooldown_bars": {
                "default": 0,
                "minimum": 0,
                "type": "integer"
              },
              "day_basis": {
                "const": "utc_calendar",
                "default": "utc_calendar",
                "type": "string"
              },
              "halt_behavior": {
                "default": "soft",
                "enum": [
                  "soft",
                  "hard"
                ],
                "type": "string"
              },
              "max_daily_loss_pct": {
                "anyOf": [
                  {
                    "maximum": 50.0,
                    "minimum": 0.1,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_entries_per_day": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_total_entries": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "min_cash_pct": {
                "anyOf": [
                  {
                    "exclusiveMaximum": 1,
                    "minimum": 0,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "DonchianValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "donchian",
                "default": "donchian",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "output": {
                "$ref": "#/$defs/BandOutput"
              },
              "period": {
                "default": 20,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "EqualWeight": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "equal_weight",
                "default": "equal_weight",
                "type": "string"
              }
            },
            "type": "object"
          },
          "GapIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "gap",
                "default": "gap",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "session": {
                "anyOf": [
                  {
                    "enum": [
                      "us",
                      "eu",
                      "asia"
                    ],
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "IndicatorValueRef": {
            "discriminator": {
              "mapping": {
                "ad": "#/$defs/AdIndicatorValueRef",
                "adx_di": "#/$defs/ADXIndicatorValueRef",
                "aroon": "#/$defs/AroonIndicatorValueRef",
                "atr": "#/$defs/PeriodIndicatorValueRef",
                "avwap": "#/$defs/AVWAPIndicatorValueRef",
                "bollinger": "#/$defs/BollingerValueRef",
                "candlestick": "#/$defs/CandlestickValueRef",
                "cci": "#/$defs/PeriodIndicatorValueRef",
                "cmf": "#/$defs/PeriodIndicatorValueRef",
                "donchian": "#/$defs/DonchianValueRef",
                "ema": "#/$defs/MovingAverageValueRef",
                "gap": "#/$defs/GapIndicatorValueRef",
                "keltner": "#/$defs/KeltnerValueRef",
                "macd": "#/$defs/MacdIndicatorValueRef",
                "macd_histogram": "#/$defs/MacdIndicatorValueRef",
                "macd_signal": "#/$defs/MacdIndicatorValueRef",
                "median": "#/$defs/PeriodIndicatorValueRef",
                "mfi": "#/$defs/PeriodIndicatorValueRef",
                "obv": "#/$defs/OBVIndicatorValueRef",
                "pivot_p": "#/$defs/PivotIndicatorValueRef",
                "pivot_r1": "#/$defs/PivotIndicatorValueRef",
                "pivot_r2": "#/$defs/PivotIndicatorValueRef",
                "pivot_r3": "#/$defs/PivotIndicatorValueRef",
                "pivot_s1": "#/$defs/PivotIndicatorValueRef",
                "pivot_s2": "#/$defs/PivotIndicatorValueRef",
                "pivot_s3": "#/$defs/PivotIndicatorValueRef",
                "roc": "#/$defs/PeriodIndicatorValueRef",
                "rsi": "#/$defs/PeriodIndicatorValueRef",
                "sma": "#/$defs/MovingAverageValueRef",
                "srsi_d": "#/$defs/SrsiIndicatorValueRef",
                "srsi_k": "#/$defs/SrsiIndicatorValueRef",
                "std": "#/$defs/PeriodIndicatorValueRef",
                "stochastic_d": "#/$defs/StochasticIndicatorValueRef",
                "stochastic_k": "#/$defs/StochasticIndicatorValueRef",
                "supertrend": "#/$defs/SupertrendIndicatorValueRef",
                "var": "#/$defs/PeriodIndicatorValueRef",
                "volume_sma": "#/$defs/PeriodIndicatorValueRef",
                "vwap": "#/$defs/VWAPIndicatorValueRef",
                "vwap_bands": "#/$defs/VWAPBandsValueRef",
                "vwma": "#/$defs/MovingAverageValueRef",
                "wma": "#/$defs/MovingAverageValueRef"
              },
              "propertyName": "indicator"
            },
            "oneOf": [
              {
                "$ref": "#/$defs/MovingAverageValueRef"
              },
              {
                "$ref": "#/$defs/PeriodIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/MacdIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/StochasticIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/SrsiIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/AdIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/OBVIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/AroonIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/SupertrendIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/BollingerValueRef"
              },
              {
                "$ref": "#/$defs/DonchianValueRef"
              },
              {
                "$ref": "#/$defs/KeltnerValueRef"
              },
              {
                "$ref": "#/$defs/VWAPBandsValueRef"
              },
              {
                "$ref": "#/$defs/VWAPIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/AVWAPIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/ADXIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/PivotIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/CandlestickValueRef"
              },
              {
                "$ref": "#/$defs/GapIndicatorValueRef"
              }
            ],
            "required": [
              "indicator"
            ]
          },
          "KeltnerValueRef": {
            "additionalProperties": false,
            "properties": {
              "atr_period": {
                "anyOf": [
                  {
                    "maximum": 500,
                    "minimum": 2,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "indicator": {
                "const": "keltner",
                "default": "keltner",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 2.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "$ref": "#/$defs/BandOutput"
              },
              "period": {
                "default": 20,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "MacdIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "fast_period": {
                "maximum": 500,
                "minimum": 1,
                "type": "integer"
              },
              "indicator": {
                "enum": [
                  "macd",
                  "macd_signal",
                  "macd_histogram"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "signal_period": {
                "maximum": 500,
                "minimum": 1,
                "type": "integer"
              },
              "slow_period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "fast_period",
              "slow_period",
              "signal_period"
            ],
            "type": "object"
          },
          "ManualWeights": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "manual",
                "default": "manual",
                "type": "string"
              },
              "weights": {
                "additionalProperties": {
                  "type": "number"
                },
                "minProperties": 1,
                "type": "object"
              }
            },
            "required": [
              "weights"
            ],
            "type": "object"
          },
          "MovingAverageValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "enum": [
                  "ema",
                  "sma",
                  "wma",
                  "vwma"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "offset": {
                "default": 0,
                "maximum": 500,
                "minimum": 0,
                "type": "integer"
              },
              "period": {
                "maximum": 800,
                "minimum": 1,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "period"
            ],
            "type": "object"
          },
          "NoRebalance": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "none",
                "default": "none",
                "type": "string"
              },
              "min_interval_bars": {
                "default": 0,
                "minimum": 0,
                "type": "integer"
              }
            },
            "type": "object"
          },
          "OBVIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "obv",
                "default": "obv",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "PatternName": {
            "enum": [
              "hammer",
              "inverted_hammer",
              "shooting_star",
              "doji",
              "dragonfly_doji",
              "gravestone_doji",
              "spinning_top",
              "marubozu",
              "bullish_engulfing",
              "bearish_engulfing",
              "harami",
              "harami_cross",
              "inside_bar",
              "morning_star",
              "evening_star",
              "piercing_line",
              "dark_cloud_cover",
              "three_white_soldiers",
              "three_black_crows"
            ],
            "type": "string"
          },
          "PeriodIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "enum": [
                  "rsi",
                  "atr",
                  "roc",
                  "cci",
                  "volume_sma",
                  "mfi",
                  "cmf",
                  "std",
                  "var",
                  "median"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "offset": {
                "default": 0,
                "maximum": 500,
                "minimum": 0,
                "type": "integer"
              },
              "period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "period"
            ],
            "type": "object"
          },
          "PivotIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "enum": [
                  "pivot_p",
                  "pivot_s1",
                  "pivot_s2",
                  "pivot_s3",
                  "pivot_r1",
                  "pivot_r2",
                  "pivot_r3"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator"
            ],
            "type": "object"
          },
          "Rebalance": {
            "enum": [
              "daily",
              "weekly",
              "monthly"
            ],
            "type": "string"
          },
          "SignalProportional_IndicatorValueRef_": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "signal_proportional",
                "default": "signal_proportional",
                "type": "string"
              },
              "score_ref": {
                "$ref": "#/$defs/IndicatorValueRef"
              }
            },
            "required": [
              "score_ref"
            ],
            "type": "object"
          },
          "SrsiIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "d_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "indicator": {
                "enum": [
                  "srsi_k",
                  "srsi_d"
                ],
                "type": "string"
              },
              "k_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "period"
            ],
            "type": "object"
          },
          "StochasticIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "d_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "indicator": {
                "enum": [
                  "stochastic_k",
                  "stochastic_d"
                ],
                "type": "string"
              },
              "k_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "period": {
                "default": 14,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator"
            ],
            "type": "object"
          },
          "SupertrendIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "supertrend",
                "default": "supertrend",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 3.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "default": "value",
                "enum": [
                  "value",
                  "direction"
                ],
                "type": "string"
              },
              "period": {
                "default": 10,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "Timeframe": {
            "enum": [
              "1m",
              "5m",
              "15m",
              "30m",
              "1h",
              "4h",
              "1d"
            ],
            "type": "string"
          },
          "VWAPBandOutput": {
            "enum": [
              "upper",
              "middle",
              "lower",
              "std_dev"
            ],
            "type": "string"
          },
          "VWAPBandsValueRef": {
            "additionalProperties": false,
            "properties": {
              "anchor": {
                "$ref": "#/$defs/AnchorPeriod",
                "default": "session"
              },
              "indicator": {
                "const": "vwap_bands",
                "default": "vwap_bands",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 2.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "$ref": "#/$defs/VWAPBandOutput"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "VWAPIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "anchor": {
                "$ref": "#/$defs/AnchorPeriod",
                "default": "session"
              },
              "indicator": {
                "const": "vwap",
                "default": "vwap",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          }
        },
        "additionalProperties": false,
        "properties": {
          "allocation": {
            "$ref": "#/$defs/BasketAllocationAuthoring",
            "description": "Canonical basket construction, rebalance, capital, constraints and collection risk."
          },
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id",
          "allocation"
        ],
        "title": "builder_set_allocationArguments",
        "type": "object"
      },
      "name": "builder_set_allocation"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Set Strategy Config",
        "toolGroup": "builder"
      },
      "description": "Set strategy-level config (sizing, position_policy, execution, risk) in one patch.\n\n        Basket capital governance (capital_model, construction, rebalance) is set\n        separately via builder_set_allocation.\n        Pass only the keys you want to update; omitted keys are left unchanged on the strategy.\n\n        Returns the patched sections (only the keys that were actually updated). To read\n        the full current config snapshot, call builder_get_strategy.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "patch": {
            "additionalProperties": true,
            "description": "Partial-patch dict. Only the keys present are applied; missing keys leave existing config unchanged. Sizing fields merge into the stored section; use replace_sizing=true to replace it. Valid keys: 'sizing', 'position_policy', 'execution', 'risk'. Each value is validated against the matching pydantic config type (SizingConfig, PositionPolicyConfig, ExecutionConfig, RiskPolicy). The 'execution' section also carries alert mode: pass {'execution': {'mode': 'alert', 'alert_cooldown_minutes': 30}} to turn the strategy into a notify-only monitor \u2014 entry signals emit alert notifications instead of placing orders (no fills, no positions); omit mode (or use 'trade') for normal order placement. Pass None for 'position_policy', 'execution', or 'risk' to clear that section (sizing is required and cannot be cleared). Basket capital governance (capital_model, construction, rebalance) is set separately via builder_set_allocation. Example: {'sizing': {'mode': 'pct_equity', 'allocation': 0.5}, 'risk': {'max_daily_loss_pct': 5}}. sizing also accepts 'headroom_pct' (0-100): buying power held back to absorb price drift between the bar an entry is SIZED on and the bar it FILLS on. This is what makes allocation 1.0 safe -- without headroom a full-equity entry is reduced to fit in backtest and REJECTED at a live broker whenever the next bar opens higher. Prefer {'allocation': 1.0, 'headroom_pct': 2} over silently picking allocation 0.95: it states the intent and the reserve is spent on the gap when the gap happens. Omit to use the platform default (0.25%, matching QuantConnect/LEAN); it only binds near full deployment, so it costs nothing at low allocation. Refused combinations (validated at builder_compile with the alternative named): pct_equity allocation above 1.0 (spot only, no leverage); a non-market order_type on a strategy with both a long and a short entry group; position_policy.mode='reverse' with only one entry direction; fixed_risk_pct without a fixed_targets(stop_loss_pct) or trailing_stop exit. Every other sizing x policy x order-type x direction x asset-class combination is implemented \u2014 including accumulate/scale_in with both entry groups, where the engine SKIPS an opposite-side entry while the sleeve is still invested (policy:opposite_side_while_invested) rather than mixing sides.",
            "title": "Patch",
            "type": "object"
          },
          "replace_sizing": {
            "default": false,
            "description": "Replace the whole sizing section instead of merging its named fields.",
            "title": "Replace Sizing",
            "type": "boolean"
          },
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id",
          "patch"
        ],
        "title": "builder_set_strategy_configArguments",
        "type": "object"
      },
      "name": "builder_set_strategy_config"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Update Condition Definition",
        "toolGroup": "builder"
      },
      "description": "Update selected source fields and validate the complete resulting condition.\n\n        Every definition uses the same typed source language. For a comparison,\n        pass {\"right\": 40, \"op\": \">=\"}; for a trailing stop, pass\n        {\"atr_multiplier\": 2.5}. Update a referenced child by its definition_id.\n        Invalid source or reference graphs are refused before saving.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "definition_id": {
            "description": "ConditionDefinition ID to update",
            "title": "Definition Id",
            "type": "string"
          },
          "expected_source_version": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The source_version you read before editing. If the definition has changed since, the update is refused instead of merged.",
            "title": "Expected Source Version"
          },
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          },
          "updates": {
            "additionalProperties": true,
            "description": "Source fields to update. Nested objects of the same kind merge; changing kind replaces the object.",
            "title": "Updates",
            "type": "object"
          }
        },
        "required": [
          "strategy_id",
          "definition_id",
          "updates"
        ],
        "title": "builder_update_conditionArguments",
        "type": "object"
      },
      "name": "builder_update_condition"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "requires_capability": "compare_backtests",
        "title": "Compare Backtests",
        "toolGroup": "backtest"
      },
      "description": "\n        Compare statistics across multiple backtests.\n\n        Useful for evaluating parameter sweeps or different strategy configurations.\n        Consider writing a scratchpad entry summarizing each variant's metrics.\n\n        Args:\n            backtest_ids: List of backtest IDs to compare (2-10 backtests)\n\n        Returns:\n            CompareBacktestsResponse with side-by-side metric comparisons\n\n        Raises:\n            StructuredToolError: With UNAUTHORIZED if caller's tier doesn't include `compare_backtests` (Hobby+ only).\n            StructuredToolError: With VALIDATION_ERROR if invalid number of backtests\n            StructuredToolError: With BACKTEST_NOT_FOUND if any backtest doesn't exist\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "backtest_ids": {
            "items": {
              "type": "string"
            },
            "title": "Backtest Ids",
            "type": "array"
          }
        },
        "required": [
          "backtest_ids"
        ],
        "title": "compare_backtestsArguments",
        "type": "object"
      },
      "name": "compare_backtests"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Correlate Strategies",
        "toolGroup": "backtest"
      },
      "description": "Compute pairwise return correlation between backtests.\n\n        Measures how similarly strategies behave over time. The diversification\n        score is computed on ABSOLUTE correlation, so only a low absolute value\n        means genuine diversification: |corr| >= 0.7 scores low diversification\n        whether the correlation is +0.9 or -0.9, because moving inversely is\n        still dependence. Near-zero correlation is the diversifying case.\n\n        Use after running multiple strategy variants to check if they provide\n        real diversification or are just correlated bets.\n\n        Args:\n            backtest_ids: List of 2-10 backtest IDs to compare\n            method: Correlation method \u2014 'pearson' for linear, 'spearman' for rank\n\n        Returns:\n            CorrelateStrategiesResponse with pairwise correlations and\n            diversification assessment\n\n        Raises:\n            StructuredToolError: With VALIDATION_ERROR if < 2 or > 10 backtests\n            StructuredToolError: With BACKTEST_NOT_FOUND if any backtest missing\n            StructuredToolError: With VALIDATION_ERROR if equity curves too short\n        ",
      "input_schema": {
        "$defs": {
          "CorrelationMethod": {
            "description": "Which correlation estimator ``correlate_strategies`` uses.\n\nThe vocabulary was previously implied by the two implementing functions in\n``vibe_trade_shared.services.result_analysis`` and restated as a Literal in\nthe tool, with a ternary that silently treated every non-``spearman`` value\nas Pearson.",
            "enum": [
              "pearson",
              "spearman"
            ],
            "title": "CorrelationMethod",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "properties": {
          "backtest_ids": {
            "description": "List of 2-10 backtest IDs to correlate",
            "items": {
              "type": "string"
            },
            "title": "Backtest Ids",
            "type": "array"
          },
          "method": {
            "$ref": "#/$defs/CorrelationMethod",
            "default": "pearson",
            "description": "Correlation method: 'pearson' (linear) or 'spearman' (rank)"
          }
        },
        "required": [
          "backtest_ids"
        ],
        "title": "correlate_strategiesArguments",
        "type": "object"
      },
      "name": "correlate_strategies"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "requires_capability": "custom_events",
        "title": "Create Event Type",
        "toolGroup": "event"
      },
      "description": "Create a new custom event type for use in event-driven strategies.\n\n        Only call after `list_event_types(ids=[...])` confirms no existing system\n        or custom event type matches the use case AND has coverage for the\n        symbol(s) you need (see `top_symbols`/`distinct_symbols`/\n        `global_occurrence_count` on each detail entry). Re-using a\n        system event type is always preferred over creating a near-duplicate custom\n        one \u2014 system types are already backfilled and maintained by Quawd. A custom\n        type that is topically similar but scoped to different symbols does NOT\n        count as a match \u2014 reusing it silently produces a condition that never\n        fires for your target symbol. If nothing existing both fits the topic and\n        covers the right symbols, source real data (e.g. web search for a data\n        provider, scrape a feed) and create a new type here \u2014 do not attach an\n        event condition to a symbol the underlying data doesn't actually cover.\n\n        Each user can own at most 50 custom event types. If payload_schema is\n        omitted, the first ingest_events call infers it from the payload.\n\n        After creation, use ingest_events() to add historical occurrences.\n        Reference this event_type_id in strategy conditions either as an event\n        window/trigger condition (condition type=\"event\") or as a payload scalar\n        with a value ref:\n\n          {\"kind\": \"event_field\",\n           \"event_type_id\": \"<this event_type_id>\",\n           \"event_field\": \"<payload field name>\"}\n\n        Do not use {\"kind\": \"event_type\"} as a compare left/right. event_type_id\n        identifies the feed; event_field identifies the numeric/string/boolean\n        payload field to compare.\n\n        After creation, always reference this event by its bare slug (the\n        `event_type_id` you passed here, and the same value returned as `id`\n        in the response). There is no owner-uid-prefixed id to remember \u2014\n        the response's `id` is always the bare slug for custom event types.\n\n        Args:\n            event_type_id: Unique kebab-case identifier (e.g., 'fomc-meeting', 'my-signal')\n            name: Display name (e.g., 'FOMC Meeting')\n            description: What the event represents\n\n        Returns:\n            EventTypeResponse with the created event type details\n\n        Raises:\n            StructuredToolError: UNAUTHORIZED if caller lacks CUSTOM_EVENTS capability\n            StructuredToolError: VALIDATION_ERROR if ID format is invalid\n            StructuredToolError: EVENT_TYPE_DUPLICATE if ID already exists\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "description": {
            "default": "",
            "description": "What this event represents",
            "title": "Description",
            "type": "string"
          },
          "event_type_id": {
            "description": "Unique kebab-case ID for this event type: lowercase letters and digits separated by single hyphens (e.g. 'my-sentiment-score', 'earnings-surprise-flag'). System event types use dotted '<category>.<name>' ids such as 'macro.cpi', so a custom id cannot collide with one.",
            "title": "Event Type Id",
            "type": "string"
          },
          "name": {
            "description": "Human-readable name",
            "title": "Name",
            "type": "string"
          },
          "payload_schema": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional schema for event payloads: {fields:{<name>:<number|boolean|string>}, required:[...]}.",
            "title": "Payload Schema"
          }
        },
        "required": [
          "event_type_id",
          "name"
        ],
        "title": "create_event_typeArguments",
        "type": "object"
      },
      "name": "create_event_type"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Create Portfolio",
        "toolGroup": "portfolio"
      },
      "description": "Create a new portfolio composed of member strategies.\n\n        USE WHEN a research project has 2+ validated strategies you want to run\n        together as one allocated book: a portfolio holds whole strategies and\n        applies a cross-strategy allocation / rotation policy. (To combine\n        conditions WITHIN a single strategy, use builder_compose instead \u2014 that is\n        a different level.)\n\n        Members contain strategy_id and optional revision_id. Author manual\n        weights only through allocation.construction.weights keyed by strategy_id.\n        An omitted allocation defaults to an equal split for two or more members.\n\n        All member strategies must belong to 'project_id' \u2014 cross-project\n        portfolios are rejected.\n\n        Pass 'allocation' to set a portfolio allocation policy directly.\n        Supports 'trailing_return'\n        member rotation (rank members by their own trailing realized return, hold\n        the top_n, re-rank on a calendar cadence) and 'member_signal_rotation'\n        (rank logic-bearing members by a declared shared_signals value,\n        trimming benched members to zero and topping up held members toward\n        1/top_n of group NAV, while member logic keeps running its own entries\n        and exits).\n\n        Returns the created portfolio_id and full portfolio details.\n        ",
      "input_schema": {
        "$defs": {
          "ADXIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "adx_di",
                "default": "adx_di",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "output": {
                "default": "adx",
                "enum": [
                  "adx",
                  "plus_di",
                  "minus_di"
                ],
                "type": "string"
              },
              "period": {
                "default": 14,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "AVWAPIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "anchor": {
                "default": "session",
                "enum": [
                  "session",
                  "session_open",
                  "week",
                  "week_open",
                  "month",
                  "month_open",
                  "month_start",
                  "ytd",
                  "custom"
                ],
                "type": "string"
              },
              "anchor_datetime": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "indicator": {
                "const": "avwap",
                "default": "avwap",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "output": {
                "default": "value",
                "enum": [
                  "value",
                  "std_dev"
                ],
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "AdIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "ad",
                "default": "ad",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "AnchorPeriod": {
            "enum": [
              "session",
              "week",
              "month"
            ],
            "type": "string"
          },
          "AroonIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "aroon",
                "default": "aroon",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "line": {
                "enum": [
                  "up",
                  "down"
                ],
                "type": "string"
              },
              "period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "period",
              "line"
            ],
            "type": "object"
          },
          "BandOutput": {
            "enum": [
              "upper",
              "middle",
              "lower"
            ],
            "type": "string"
          },
          "BollingerValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "bollinger",
                "default": "bollinger",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 2.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "enum": [
                  "upper",
                  "middle",
                  "lower",
                  "bandwidth",
                  "stddev"
                ],
                "type": "string"
              },
              "period": {
                "default": 20,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "CalendarRebalance": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "calendar",
                "default": "calendar",
                "type": "string"
              },
              "min_interval_bars": {
                "default": 0,
                "minimum": 0,
                "type": "integer"
              },
              "schedule": {
                "$ref": "#/$defs/Rebalance"
              }
            },
            "required": [
              "schedule"
            ],
            "type": "object"
          },
          "CandlestickValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "candlestick",
                "default": "candlestick",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "pattern": {
                "$ref": "#/$defs/PatternName"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "pattern"
            ],
            "type": "object"
          },
          "CollectionAuthoringConstraints": {
            "additionalProperties": false,
            "properties": {
              "asset_class_caps": {
                "anyOf": [
                  {
                    "additionalProperties": {
                      "type": "number"
                    },
                    "type": "object"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_active_sleeves": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_position_pct": {
                "anyOf": [
                  {
                    "exclusiveMinimum": 0,
                    "maximum": 1,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "min_position_pct": {
                "anyOf": [
                  {
                    "exclusiveMaximum": 1,
                    "minimum": 0,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "CollectionRiskPolicy": {
            "additionalProperties": false,
            "properties": {
              "cooldown_bars": {
                "default": 0,
                "minimum": 0,
                "type": "integer"
              },
              "day_basis": {
                "const": "utc_calendar",
                "default": "utc_calendar",
                "type": "string"
              },
              "halt_behavior": {
                "default": "soft",
                "enum": [
                  "soft",
                  "hard"
                ],
                "type": "string"
              },
              "max_daily_loss_pct": {
                "anyOf": [
                  {
                    "maximum": 50.0,
                    "minimum": 0.1,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_entries_per_day": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_total_entries": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "min_cash_pct": {
                "anyOf": [
                  {
                    "exclusiveMaximum": 1,
                    "minimum": 0,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "DonchianValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "donchian",
                "default": "donchian",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "output": {
                "$ref": "#/$defs/BandOutput"
              },
              "period": {
                "default": 20,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "EqualWeight": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "equal_weight",
                "default": "equal_weight",
                "type": "string"
              }
            },
            "type": "object"
          },
          "GapIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "gap",
                "default": "gap",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "session": {
                "anyOf": [
                  {
                    "enum": [
                      "us",
                      "eu",
                      "asia"
                    ],
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "IndicatorValueRef": {
            "discriminator": {
              "mapping": {
                "ad": "#/$defs/AdIndicatorValueRef",
                "adx_di": "#/$defs/ADXIndicatorValueRef",
                "aroon": "#/$defs/AroonIndicatorValueRef",
                "atr": "#/$defs/PeriodIndicatorValueRef",
                "avwap": "#/$defs/AVWAPIndicatorValueRef",
                "bollinger": "#/$defs/BollingerValueRef",
                "candlestick": "#/$defs/CandlestickValueRef",
                "cci": "#/$defs/PeriodIndicatorValueRef",
                "cmf": "#/$defs/PeriodIndicatorValueRef",
                "donchian": "#/$defs/DonchianValueRef",
                "ema": "#/$defs/MovingAverageValueRef",
                "gap": "#/$defs/GapIndicatorValueRef",
                "keltner": "#/$defs/KeltnerValueRef",
                "macd": "#/$defs/MacdIndicatorValueRef",
                "macd_histogram": "#/$defs/MacdIndicatorValueRef",
                "macd_signal": "#/$defs/MacdIndicatorValueRef",
                "median": "#/$defs/PeriodIndicatorValueRef",
                "mfi": "#/$defs/PeriodIndicatorValueRef",
                "obv": "#/$defs/OBVIndicatorValueRef",
                "pivot_p": "#/$defs/PivotIndicatorValueRef",
                "pivot_r1": "#/$defs/PivotIndicatorValueRef",
                "pivot_r2": "#/$defs/PivotIndicatorValueRef",
                "pivot_r3": "#/$defs/PivotIndicatorValueRef",
                "pivot_s1": "#/$defs/PivotIndicatorValueRef",
                "pivot_s2": "#/$defs/PivotIndicatorValueRef",
                "pivot_s3": "#/$defs/PivotIndicatorValueRef",
                "roc": "#/$defs/PeriodIndicatorValueRef",
                "rsi": "#/$defs/PeriodIndicatorValueRef",
                "sma": "#/$defs/MovingAverageValueRef",
                "srsi_d": "#/$defs/SrsiIndicatorValueRef",
                "srsi_k": "#/$defs/SrsiIndicatorValueRef",
                "std": "#/$defs/PeriodIndicatorValueRef",
                "stochastic_d": "#/$defs/StochasticIndicatorValueRef",
                "stochastic_k": "#/$defs/StochasticIndicatorValueRef",
                "supertrend": "#/$defs/SupertrendIndicatorValueRef",
                "var": "#/$defs/PeriodIndicatorValueRef",
                "volume_sma": "#/$defs/PeriodIndicatorValueRef",
                "vwap": "#/$defs/VWAPIndicatorValueRef",
                "vwap_bands": "#/$defs/VWAPBandsValueRef",
                "vwma": "#/$defs/MovingAverageValueRef",
                "wma": "#/$defs/MovingAverageValueRef"
              },
              "propertyName": "indicator"
            },
            "oneOf": [
              {
                "$ref": "#/$defs/MovingAverageValueRef"
              },
              {
                "$ref": "#/$defs/PeriodIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/MacdIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/StochasticIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/SrsiIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/AdIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/OBVIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/AroonIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/SupertrendIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/BollingerValueRef"
              },
              {
                "$ref": "#/$defs/DonchianValueRef"
              },
              {
                "$ref": "#/$defs/KeltnerValueRef"
              },
              {
                "$ref": "#/$defs/VWAPBandsValueRef"
              },
              {
                "$ref": "#/$defs/VWAPIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/AVWAPIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/ADXIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/PivotIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/CandlestickValueRef"
              },
              {
                "$ref": "#/$defs/GapIndicatorValueRef"
              }
            ],
            "required": [
              "indicator"
            ]
          },
          "KeltnerValueRef": {
            "additionalProperties": false,
            "properties": {
              "atr_period": {
                "anyOf": [
                  {
                    "maximum": 500,
                    "minimum": 2,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "indicator": {
                "const": "keltner",
                "default": "keltner",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 2.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "$ref": "#/$defs/BandOutput"
              },
              "period": {
                "default": 20,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "MacdIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "fast_period": {
                "maximum": 500,
                "minimum": 1,
                "type": "integer"
              },
              "indicator": {
                "enum": [
                  "macd",
                  "macd_signal",
                  "macd_histogram"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "signal_period": {
                "maximum": 500,
                "minimum": 1,
                "type": "integer"
              },
              "slow_period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "fast_period",
              "slow_period",
              "signal_period"
            ],
            "type": "object"
          },
          "ManualWeights": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "manual",
                "default": "manual",
                "type": "string"
              },
              "weights": {
                "additionalProperties": {
                  "type": "number"
                },
                "minProperties": 1,
                "type": "object"
              }
            },
            "required": [
              "weights"
            ],
            "type": "object"
          },
          "Member": {
            "additionalProperties": false,
            "properties": {
              "revision_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "strategy_id": {
                "type": "string"
              }
            },
            "required": [
              "strategy_id"
            ],
            "type": "object"
          },
          "MovingAverageValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "enum": [
                  "ema",
                  "sma",
                  "wma",
                  "vwma"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "offset": {
                "default": 0,
                "maximum": 500,
                "minimum": 0,
                "type": "integer"
              },
              "period": {
                "maximum": 800,
                "minimum": 1,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "period"
            ],
            "type": "object"
          },
          "NoRebalance": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "none",
                "default": "none",
                "type": "string"
              },
              "min_interval_bars": {
                "default": 0,
                "minimum": 0,
                "type": "integer"
              }
            },
            "type": "object"
          },
          "OBVIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "obv",
                "default": "obv",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "PatternName": {
            "enum": [
              "hammer",
              "inverted_hammer",
              "shooting_star",
              "doji",
              "dragonfly_doji",
              "gravestone_doji",
              "spinning_top",
              "marubozu",
              "bullish_engulfing",
              "bearish_engulfing",
              "harami",
              "harami_cross",
              "inside_bar",
              "morning_star",
              "evening_star",
              "piercing_line",
              "dark_cloud_cover",
              "three_white_soldiers",
              "three_black_crows"
            ],
            "type": "string"
          },
          "PeriodIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "enum": [
                  "rsi",
                  "atr",
                  "roc",
                  "cci",
                  "volume_sma",
                  "mfi",
                  "cmf",
                  "std",
                  "var",
                  "median"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "offset": {
                "default": 0,
                "maximum": 500,
                "minimum": 0,
                "type": "integer"
              },
              "period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "period"
            ],
            "type": "object"
          },
          "PivotIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "enum": [
                  "pivot_p",
                  "pivot_s1",
                  "pivot_s2",
                  "pivot_s3",
                  "pivot_r1",
                  "pivot_r2",
                  "pivot_r3"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator"
            ],
            "type": "object"
          },
          "PortfolioAllocationAuthoring": {
            "additionalProperties": false,
            "properties": {
              "capital_model": {
                "default": "partitioned",
                "enum": [
                  "partitioned",
                  "shared_pool"
                ],
                "type": "string"
              },
              "collection_risk": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CollectionRiskPolicy"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "constraints": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CollectionAuthoringConstraints"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "construction": {
                "anyOf": [
                  {
                    "discriminator": {
                      "mapping": {
                        "equal_weight": "#/$defs/EqualWeight",
                        "manual": "#/$defs/ManualWeights",
                        "member_signal_rotation": "#/$defs/PortfolioMemberSignalConstruction",
                        "rank_based": "#/$defs/PortfolioRankConstruction",
                        "trailing_return": "#/$defs/TrailingReturnRotation"
                      },
                      "propertyName": "kind"
                    },
                    "oneOf": [
                      {
                        "$ref": "#/$defs/EqualWeight"
                      },
                      {
                        "$ref": "#/$defs/ManualWeights"
                      },
                      {
                        "$ref": "#/$defs/PortfolioRankConstruction"
                      },
                      {
                        "$ref": "#/$defs/TrailingReturnRotation"
                      },
                      {
                        "$ref": "#/$defs/PortfolioMemberSignalConstruction"
                      }
                    ],
                    "required": [
                      "kind"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "rebalance": {
                "anyOf": [
                  {
                    "discriminator": {
                      "mapping": {
                        "calendar": "#/$defs/CalendarRebalance",
                        "none": "#/$defs/NoRebalance"
                      },
                      "propertyName": "kind"
                    },
                    "oneOf": [
                      {
                        "$ref": "#/$defs/NoRebalance"
                      },
                      {
                        "$ref": "#/$defs/CalendarRebalance"
                      }
                    ],
                    "required": [
                      "kind"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "PortfolioMemberSignalConstruction": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "member_signal_rotation",
                "type": "string"
              },
              "score_signal": {
                "minLength": 1,
                "type": "string"
              },
              "top_n": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "kind",
              "score_signal",
              "top_n"
            ],
            "type": "object"
          },
          "PortfolioRankConstruction": {
            "additionalProperties": false,
            "properties": {
              "exit_top_n": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "kind": {
                "const": "rank_based",
                "type": "string"
              },
              "score_signal": {
                "minLength": 1,
                "type": "string"
              },
              "top_n": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "kind",
              "score_signal",
              "top_n"
            ],
            "type": "object"
          },
          "PriceField": {
            "enum": [
              "open",
              "high",
              "low",
              "close"
            ],
            "type": "string"
          },
          "PriceValueRef": {
            "additionalProperties": false,
            "properties": {
              "field": {
                "$ref": "#/$defs/PriceField",
                "default": "close"
              },
              "kind": {
                "const": "price",
                "default": "price",
                "type": "string"
              },
              "offset": {
                "default": 0,
                "maximum": 500,
                "minimum": 0,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "Rebalance": {
            "enum": [
              "daily",
              "weekly",
              "monthly"
            ],
            "type": "string"
          },
          "SharedSignal": {
            "additionalProperties": false,
            "properties": {
              "name": {
                "minLength": 1,
                "type": "string"
              },
              "source": {
                "discriminator": {
                  "mapping": {
                    "indicator": "#/$defs/IndicatorValueRef",
                    "price": "#/$defs/PriceValueRef",
                    "volume": "#/$defs/VolumeValueRef"
                  },
                  "propertyName": "kind"
                },
                "oneOf": [
                  {
                    "$ref": "#/$defs/IndicatorValueRef"
                  },
                  {
                    "$ref": "#/$defs/PriceValueRef"
                  },
                  {
                    "$ref": "#/$defs/VolumeValueRef"
                  }
                ],
                "required": [
                  "kind"
                ]
              }
            },
            "required": [
              "name",
              "source"
            ],
            "type": "object"
          },
          "SrsiIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "d_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "indicator": {
                "enum": [
                  "srsi_k",
                  "srsi_d"
                ],
                "type": "string"
              },
              "k_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "period"
            ],
            "type": "object"
          },
          "StochasticIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "d_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "indicator": {
                "enum": [
                  "stochastic_k",
                  "stochastic_d"
                ],
                "type": "string"
              },
              "k_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "period": {
                "default": 14,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator"
            ],
            "type": "object"
          },
          "SupertrendIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "supertrend",
                "default": "supertrend",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 3.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "default": "value",
                "enum": [
                  "value",
                  "direction"
                ],
                "type": "string"
              },
              "period": {
                "default": 10,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "Timeframe": {
            "enum": [
              "1m",
              "5m",
              "15m",
              "30m",
              "1h",
              "4h",
              "1d"
            ],
            "type": "string"
          },
          "TrailingReturnRotation": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "trailing_return",
                "default": "trailing_return",
                "type": "string"
              },
              "lookback_bars": {
                "exclusiveMinimum": 0,
                "type": "integer"
              },
              "metric": {
                "const": "return",
                "default": "return",
                "type": "string"
              },
              "top_n": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "top_n",
              "lookback_bars"
            ],
            "type": "object"
          },
          "VWAPBandOutput": {
            "enum": [
              "upper",
              "middle",
              "lower",
              "std_dev"
            ],
            "type": "string"
          },
          "VWAPBandsValueRef": {
            "additionalProperties": false,
            "properties": {
              "anchor": {
                "$ref": "#/$defs/AnchorPeriod",
                "default": "session"
              },
              "indicator": {
                "const": "vwap_bands",
                "default": "vwap_bands",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 2.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "$ref": "#/$defs/VWAPBandOutput"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "VWAPIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "anchor": {
                "$ref": "#/$defs/AnchorPeriod",
                "default": "session"
              },
              "indicator": {
                "const": "vwap",
                "default": "vwap",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "VolumeValueRef": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "volume",
                "default": "volume",
                "type": "string"
              },
              "offset": {
                "default": 0,
                "maximum": 500,
                "minimum": 0,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          }
        },
        "additionalProperties": false,
        "properties": {
          "allocation": {
            "anyOf": [
              {
                "$ref": "#/$defs/PortfolioAllocationAuthoring"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional portfolio allocation policy (cross-member weighting + rebalance + capital model). Manual weights belong in construction.weights. 'trailing_return' member rotation ranks members by their OWN trailing realized return and holds the top_n, re-ranking on a calendar cadence. Shape: {'construction': {'kind': 'trailing_return', 'top_n': 2, 'lookback_bars': 30}, 'rebalance': {'kind': 'calendar', 'schedule': 'weekly'}, 'capital_model': 'partitioned'}. 'member_signal_rotation' ranks logic-bearing members by a declared shared_signals value, trimming benched members toward zero, keeping each held member's own entry/exit logic running, e.g. {'kind': 'member_signal_rotation', 'score_signal': 'momentum', 'top_n': 1} \u2014 requires a calendar rebalance and a declared 'shared_signals' entry named 'momentum'. Either rotation deploys like a basket: held members are equal-weighted at 1/top_n of group NAV at each ranking and the book runs ~fully invested \u2014 the member still decides when to enter and exit, and its own sizing affects only its first fill; 'min_cash_pct' is rejected on member rotation. 'construction.kind' may also be 'equal_weight' or 'manual' ({'kind': 'manual', 'weights': {strategy_id: fraction}}), or 'rank_based' with a 'score_signal' (construction-managed rotation \u2014 rejects logic-bearing members, unlike 'member_signal_rotation'). 'rank_based' with a raw 'score_ref' / 'signal_proportional' are universe-only and rejected \u2014 use 'trailing_return' or 'member_signal_rotation' to rotate members. Optional 'constraints' and 'collection_risk' dicts are accepted; fields the engine does not enforce are rejected fail-closed."
          },
          "members": {
            "description": "Member strategy references",
            "items": {
              "$ref": "#/$defs/Member"
            },
            "title": "Members",
            "type": "array"
          },
          "name": {
            "description": "Human-readable portfolio name",
            "title": "Name",
            "type": "string"
          },
          "project_id": {
            "description": "Research project this portfolio belongs to. Every member strategy must already belong to this same project \u2014 a portfolio cannot span multiple research projects.",
            "title": "Project Id",
            "type": "string"
          },
          "shared_signals": {
            "description": "Portfolio-level cross-member shared signals. Each entry is {'name': str, 'source': <market ValueRef>}, e.g. {'name':'mom20','source':{'kind':'indicator','indicator':'ema','period':20}}. Declared once, then referenced inside member entry/exit conditions via {'kind':'shared_signal','name':'mom20'} so a member can gate on its rank / relationship vs sibling members. Source must be a market-derived per-symbol metric (indicator / price / volume); cross-sectional / state / event refs are rejected. Only valid on a 2+ member portfolio. On update_portfolio, omit to preserve the existing shared_signals; pass a list (including []) to replace them.",
            "items": {
              "$ref": "#/$defs/SharedSignal"
            },
            "title": "Shared Signals",
            "type": "array"
          }
        },
        "required": [
          "name",
          "project_id",
          "members"
        ],
        "title": "create_portfolioArguments",
        "type": "object"
      },
      "name": "create_portfolio"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Create Strategy",
        "toolGroup": "builder"
      },
      "description": "Use to start a new strategy WITHIN A PROJECT. Every strategy MUST\n        belong to a research project \u2014 call project_list first to find an\n        existing project, or project_create to start a new one, then pass\n        the project_id here. Strategies group under projects so related work\n        shares a scratchpad and remains discoverable across sessions.\n\n        ``symbols`` becomes the strategy's instruments. Pass a single-element\n        list for a single-instrument leaf, or multiple elements for a basket\n        that runs the same strategy template across each instrument (a basket\n        requires an allocation policy set via builder_set_allocation).\n\n        Returns a strategy_id. Use add_rule for ordinary entry/exit/gate\n        authoring, then set configuration and compile. Read\n        builder_discover(action='quickstart') for the incremental authoring loop.\n\n        Examples:\n            project = project_create(name=\"Mean reversion ideas\")\n            # Single-symbol strategy\n            strategy = create_strategy(name=\"RSI 14 oversold\", symbols=[\"SPY\"],\n                                      timeframe=\"1h\", project_id=project.id)\n            # Basket strategy across 3 instruments\n            strategy = create_strategy(name=\"Mag7 trend\",\n                                      symbols=[\"AAPL\", \"MSFT\", \"GOOG\"],\n                                      timeframe=\"1d\", project_id=project.id)\n        ",
      "input_schema": {
        "$defs": {
          "Timeframe": {
            "description": "Bar duration. These seven are the only granularities the data layer serves.",
            "enum": [
              "1m",
              "5m",
              "15m",
              "30m",
              "1h",
              "4h",
              "1d"
            ],
            "title": "Timeframe",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "properties": {
          "name": {
            "description": "Short strategy name, up to 5 words / 48 chars. Duplicate names in the same project are versioned automatically (e.g. 'RSI dip buy v2').",
            "title": "Name",
            "type": "string"
          },
          "project_id": {
            "description": "Research project ID from project_create or project_list. REQUIRED \u2014 strategies cannot be created outside a project. If no project exists yet, call project_create first.",
            "title": "Project Id",
            "type": "string"
          },
          "symbols": {
            "description": "List of trading symbols persisted as Strategy.instruments. Single-instrument leaf: ['SPY']. Basket: ['AAPL', 'MSFT', 'GOOG'] \u2014 runs the same strategy template across each instrument; a basket (len >= 2) requires an allocation policy set via builder_set_allocation. 13 tickers name both an equity and a crypto pair (LTC, DASH, LINK, ...); those are rejected as ambiguous \u2014 say 'LTC-USD' for the crypto pair or 'EQ:LTC' for the equity. Must contain at least one symbol.",
            "items": {
              "type": "string"
            },
            "minItems": 1,
            "title": "Symbols",
            "type": "array"
          },
          "timeframe": {
            "$ref": "#/$defs/Timeframe",
            "description": "Candle timeframe for strategy bars"
          }
        },
        "required": [
          "name",
          "symbols",
          "timeframe",
          "project_id"
        ],
        "title": "create_strategyArguments",
        "type": "object"
      },
      "name": "create_strategy"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "requires_capability": "custom_events",
        "title": "Delete Event Type",
        "toolGroup": "event"
      },
      "description": "Hard delete \u2014 irreversible. Only call when the user explicitly asks to delete a specific custom event type by id. Never proactively cleanup. System event types cannot be deleted. Custom event types can only be deleted by their owner. Occurrences in BigQuery are NOT removed (they become orphans, recoverable by re-creating the same id).\n\n        Args:\n            event_type_id: The custom event type id to delete.\n\n        Returns:\n            DeleteEventTypeResponse with the deleted id and a true `deleted` flag.\n\n        Raises:\n            StructuredToolError: EVENT_TYPE_NOT_FOUND if the event type does not exist.\n            StructuredToolError: FORBIDDEN if the type is a system type.\n            StructuredToolError: UNAUTHORIZED if the caller targets another user's namespace.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "event_type_id": {
            "description": "ID of the custom event type to hard-delete.",
            "title": "Event Type Id",
            "type": "string"
          }
        },
        "required": [
          "event_type_id"
        ],
        "title": "delete_event_typeArguments",
        "type": "object"
      },
      "name": "delete_event_type"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Delete Portfolio",
        "toolGroup": "portfolio"
      },
      "description": "Delete a portfolio. This cannot be undone.",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "portfolio_id": {
            "description": "Portfolio identifier",
            "title": "Portfolio Id",
            "type": "string"
          }
        },
        "required": [
          "portfolio_id"
        ],
        "title": "delete_portfolioArguments",
        "type": "object"
      },
      "name": "delete_portfolio"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Describe Basket Allocation",
        "toolGroup": "builder"
      },
      "description": "Resolve the basket-allocation decision for THIS strategy (progressive disclosure).\n\n        A basket (``len(instruments) >= 2``) must declare how its capital splits\n        across instruments before it compiles. This thin, strategy-scoped tool\n        reports where the strategy stands and what to do next:\n\n        - ``not_applicable``: a single-instrument leaf has no siblings to split.\n        - ``required_unset``: a basket with no explicit allocation yet \u2014 returns\n          the recommended call (equal_weight) and the alternatives.\n        - ``set``: a basket whose allocation is already chosen \u2014 echoes it.\n\n        For the full set-allocation surface (score, top_n, rebalance rules) call\n        builder_set_allocation.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "describe_allocationArguments",
        "type": "object"
      },
      "name": "describe_allocation"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "toolGroup": "paper"
      },
      "description": "\n        Evaluate a paper trading session against its benchmark and RECORD the result.\n        This is a mutation, not a cheap read \u2014 it computes and persists validation metrics.\n\n        Returns readiness status, observed/required progress for trades, bars, and days,\n        and a metrics dict comparing paper performance to the backtest benchmark:\n\n        - paper_win_rate, paper_total_return, paper_trades, paper_bars\n        - benchmark_win_rate, benchmark_total_return, benchmark_max_drawdown,\n          benchmark_sharpe, benchmark_trade_count\n        - overfitting_context.iteration_count (number of backtests at promotion time)\n\n        No verdict is returned. Compare the paper and benchmark numbers and decide whether\n        the strategy is ready for live promotion.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "session_id": {
            "description": "Paper trading session ID to evaluate. Get this from start_paper_trading() or list_paper_trading_sessions().",
            "title": "Session Id",
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "evaluate_paper_sessionArguments",
        "type": "object"
      },
      "name": "evaluate_paper_session"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "requires_capability": "explain_entry",
        "title": "Explain Bar",
        "toolGroup": "backtest"
      },
      "description": "Explain what happened on a single bar \u2014 entry fired or not.\n\n        Returns `had_entry: True` if an entry trade fired on this bar, with the\n        full entry-explanation payload (trade index, signal/entry bars, prices,\n        PnL, exit reason, per-condition state snapshot at the signal bar).\n        Otherwise returns `had_entry: False` with the per-condition state\n        showing which entry conditions failed and how close they were to firing.\n\n        When `context_bars > 0`, the response also includes `context: [...]` \u2014\n        a \u00b1N-bar window of condition states (all groups: entry/exit/gate) and\n        position info, clamped to the backtest's bar range. If the context\n        slice is unavailable, `context_error` is set instead.\n\n        Use this whenever you want to know what happened (or didn't happen) on a\n        specific bar. Pair with get_condition_timeline (proximity over a range).\n\n        Per-condition state needs a run recorded with per-bar diagnostics, and\n        run_backtest defaults collect_diagnostics to false. On a run without\n        them, a bar with no entry returns an `error` whose `hint` names\n        rerun_backtest(backtest_id, collect_diagnostics=true); a bar with an\n        entry still returns the trade facts, with `condition_states_error` in\n        place of `condition_states`.\n\n        Args:\n            backtest_id: Backtest document ID from run_backtest or list_runs.\n            bar_id: Zero-based bar index. Exactly one of bar_id or timestamp required.\n            timestamp: ISO timestamp; resolved to bar_id via bar_times. Exactly one required.\n            context_bars: Optional \u00b1N-bar window (default 0). When >0, attaches\n                a `context: [...]` field with surrounding condition states and\n                position info. Max 200.\n            sleeve_id: Sleeve to inspect on portfolio/universe (per_sleeve) runs.\n                Required for per_sleeve runs; omit on single-symbol runs. Omit on\n                a per_sleeve run to get the list of available sleeve_ids.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "backtest_id": {
            "description": "Backtest document ID",
            "title": "Backtest Id",
            "type": "string"
          },
          "bar_id": {
            "anyOf": [
              {
                "minimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Zero-based bar index. Exactly one of bar_id or timestamp is required.",
            "title": "Bar Id"
          },
          "context_bars": {
            "default": 0,
            "description": "Optional \u00b1N-bar window. When >0, response includes `context: [...]` \u2014 per-bar condition states (all groups: entry/exit/gate) and position info, clamped to [0, n_bars). Default 0 returns the single-bar payload. Max 200.",
            "maximum": 200,
            "minimum": 0,
            "title": "Context Bars",
            "type": "integer"
          },
          "sleeve_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Sleeve to inspect on portfolio/universe (per_sleeve) backtests. REQUIRED for per_sleeve runs; omit on single-symbol runs. Omit on a per_sleeve run to receive the list of available sleeve_ids.",
            "title": "Sleeve Id"
          },
          "timestamp": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "ISO timestamp of the bar to inspect. Resolved to bar_id via the backtest's bar_times index. Exactly one of bar_id or timestamp is required.",
            "title": "Timestamp"
          }
        },
        "required": [
          "backtest_id"
        ],
        "title": "explain_barArguments",
        "type": "object"
      },
      "name": "explain_bar"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Get Backtest",
        "toolGroup": "backtest"
      },
      "description": "Get details and results of a backtest.\n\n        Default returns the summary (statistics, capped trades, warnings, etc).\n        Use `include=[\"trades\"]` to also receive a paginated full trade list\n        under the top-level ``trades`` key.\n\n        Trade list location in the default summary: `results.trades` (NOT\n        top-level `trades`). When trades are capped in summary mode (20) or\n        full mode (500), `results.trade_count` and `results.trades_truncated`\n        flag the truncation. Use `include=[\"trades\"]` with `trades_offset` /\n        `trades_limit` to page through every trade.\n\n        Always check the `warnings` field before telling the user the backtest\n        succeeded \u2014 it carries the engine's own disclosures (open positions at\n        the end, NaN-inert conditions, event types with no occurrences or\n        look-ahead risk, data coverage gaps, a shared pool over 100%) and\n        flags result-reliability issues such as entries rejected for\n        insufficient capital, low trade counts, and missing entry conditions.\n        ",
      "input_schema": {
        "$defs": {
          "BacktestDetail": {
            "description": "How much of a persisted run a read returns.\n\n``status``/``none`` exist for polling: they return run metadata and skip\nthe results payload entirely.",
            "enum": [
              "summary",
              "full",
              "status",
              "none"
            ],
            "title": "BacktestDetail",
            "type": "string"
          },
          "BacktestInclude": {
            "description": "Optional payload sections a read may opt into.",
            "enum": [
              "trades"
            ],
            "title": "BacktestInclude",
            "type": "string"
          },
          "IndicatorDetail": {
            "description": "Whether a read carries indicator data, and in what form.",
            "enum": [
              "none",
              "summary"
            ],
            "title": "IndicatorDetail",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "properties": {
          "backtest_id": {
            "description": "Backtest identifier",
            "title": "Backtest Id",
            "type": "string"
          },
          "detail": {
            "anyOf": [
              {
                "$ref": "#/$defs/BacktestDetail"
              },
              {
                "type": "null"
              }
            ],
            "default": "summary",
            "description": "Result detail: 'summary' (default, no blueprints, trades capped at 20), 'full' (includes blueprints, trades capped at 500), 'status' (metadata only, for polling), 'none' (same as status, legacy)."
          },
          "include": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/$defs/BacktestInclude"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional add-ons. 'trades' appends a paginated full trade list under the top-level 'trades' key (see trades_offset/trades_limit). Omit for the summary-only response.",
            "title": "Include"
          },
          "include_indicators": {
            "anyOf": [
              {
                "$ref": "#/$defs/IndicatorDetail"
              },
              {
                "type": "null"
              }
            ],
            "default": "none",
            "description": "Indicator data: 'none' (default) or 'summary' (statistical summary)."
          },
          "trades_limit": {
            "default": 50,
            "description": "Max trades to return per page (1-500, default 50). Used when include contains 'trades'.",
            "maximum": 500,
            "minimum": 1,
            "title": "Trades Limit",
            "type": "integer"
          },
          "trades_offset": {
            "default": 0,
            "description": "Trade index to start from (0-based). Used when include contains 'trades'.",
            "minimum": 0,
            "title": "Trades Offset",
            "type": "integer"
          }
        },
        "required": [
          "backtest_id"
        ],
        "title": "get_backtestArguments",
        "type": "object"
      },
      "name": "get_backtest"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Get Condition Timeline",
        "toolGroup": "backtest"
      },
      "description": "Get condition proximity evolution over a bar range.\n\n        Returns how close each condition was to firing at each bar in the range.\n        Use this to spot patterns like 'RSI was consistently near threshold'.\n\n        Needs a run recorded with per-bar diagnostics (collect_diagnostics=true);\n        on any other run it returns an `error` whose `hint` names rerun_backtest\n        instead of proximity data.\n\n        Args:\n            backtest_id: Backtest document ID\n            start_bar: First bar index (inclusive, 0-based)\n            end_bar: Last bar index (inclusive, 0-based)\n            sleeve_id: Sleeve to inspect on portfolio/universe (per_sleeve) runs.\n                Required for per_sleeve runs; omit on single-symbol runs. Omit on\n                a per_sleeve run to get the list of available sleeve_ids.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "backtest_id": {
            "description": "Backtest document ID",
            "title": "Backtest Id",
            "type": "string"
          },
          "end_bar": {
            "description": "Last bar index (inclusive, 0-based)",
            "minimum": 0,
            "title": "End Bar",
            "type": "integer"
          },
          "max_bars": {
            "default": 50,
            "description": "Max bars to return (default 50, max 100 to bound response size)",
            "maximum": 100,
            "minimum": 1,
            "title": "Max Bars",
            "type": "integer"
          },
          "sleeve_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Sleeve to inspect on portfolio/universe (per_sleeve) backtests. REQUIRED for per_sleeve runs; omit on single-symbol runs. Omit on a per_sleeve run to receive the list of available sleeve_ids.",
            "title": "Sleeve Id"
          },
          "start_bar": {
            "description": "First bar index (inclusive, 0-based)",
            "minimum": 0,
            "title": "Start Bar",
            "type": "integer"
          }
        },
        "required": [
          "backtest_id",
          "start_bar",
          "end_bar"
        ],
        "title": "get_condition_timelineArguments",
        "type": "object"
      },
      "name": "get_condition_timeline"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Get Current Signal State",
        "toolGroup": "backtest"
      },
      "description": "Evaluate a strategy's entry/exit conditions against the most recent available market data.\n\n        Shows whether entry or exit conditions are firing right now. Resolved\n        indicator values are deliberately omitted from the MCP response because\n        some indicator sequences can reconstruct licensed market prices. Useful\n        for assessing signal state before promoting to paper trading.\n\n        Returns:\n            symbol, resolution, last_bar_time, warmup_bars, ready (bool),\n            entry_firing (bool), entry_firings (list of\n            {rule_id, direction, name, firing}),\n            entry_conflict (bool),\n            exits (list of {id, firing, not_evaluable}), warnings (list).\n            An exit's `not_evaluable` is null when that rule was evaluated and\n            `firing` is its answer. Otherwise it is the reason the rule could\n            not be evaluated here, naming the value ref and what it needs \u2014\n            this probe holds no position, so a time stop, a trailing stop or an\n            unrealised-PnL exit lands there as a matter of course, and its\n            `firing` is false because nothing was computed, not because the\n            rule is quiet. Run a backtest to see those exits decide.\n\n        Args:\n            strategy_id: Strategy ID to evaluate\n            lookback_bars: Number of history bars beyond warmup (default: 500)\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "lookback_bars": {
            "default": 500,
            "description": "How many bars of history to evaluate on, IN ADDITION to the strategy's computed indicator warmup. Total bars fetched = warmup_bars + lookback_bars.",
            "maximum": 2000,
            "minimum": 50,
            "title": "Lookback Bars",
            "type": "integer"
          },
          "strategy_id": {
            "description": "Strategy ID to evaluate",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "get_current_signal_stateArguments",
        "type": "object"
      },
      "name": "get_current_signal_state"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "toolGroup": "paper"
      },
      "description": "\n        Get details of a paper trading session.\n\n        Reads session data directly from Firestore, including current equity,\n        PnL, trade count, and processing status.\n\n        Args:\n            session_id: Session identifier\n\n        Returns:\n            SessionResponse with full session details\n\n        Raises:\n            StructuredToolError: With SESSION_NOT_FOUND if session doesn't exist\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "session_id": {
            "description": "Paper trading session identifier",
            "title": "Session Id",
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "get_paper_trading_sessionArguments",
        "type": "object"
      },
      "name": "get_paper_trading_session"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Get Portfolio",
        "toolGroup": "portfolio"
      },
      "description": "Fetch a portfolio by ID.\n\n        Returns the portfolio details including all members and the allocation policy.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "portfolio_id": {
            "description": "Portfolio identifier",
            "title": "Portfolio Id",
            "type": "string"
          }
        },
        "required": [
          "portfolio_id"
        ],
        "title": "get_portfolioArguments",
        "type": "object"
      },
      "name": "get_portfolio"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Get Scan Batch",
        "toolGroup": "signal"
      },
      "description": "Get results of a scan batch (signal_scan).\n\n        Returns completed/pending/failed counts and results grouped by\n        long_signal/short_signal/no_signal/condition_never_fired. Poll this until\n        all scans complete. ``condition_never_fired`` lists symbols whose\n        condition is valid but never evaluated true on the scanned bars.\n\n        **Compact by default:** each completed run in\n        ``results`` is a COMPACT summary -- ``scan_run_id``, ``symbol``,\n        ``sweep_params``, ``condition_label``, ``occurrences``, ``fire_rate``,\n        ``verdict``, ``reliable``, ``horizons_tested``, plus two horizon views.\n        Each horizon carries ``horizon``, ``sharpe``, ``win_rate``, ``p_value``,\n        ``adjusted_p_value``, ``family_q_value``, ``significant`` and\n        ``significance_basis``. The full per-run blob (all horizons, excursion,\n        consistency, diagnostics, warnings) is omitted to stay under the\n        tool-output token limit. Pass ``detail=\"full\"`` for the complete\n        per-run ScanResult instead.\n\n        ``significant_horizons`` lists EVERY horizon clearing 0.05 on its\n        corrected p-value, best-first \u2014 read it with ``horizons_tested`` as the\n        denominator. Shape matters: significant at 5, 10 AND 20 with a rising\n        Sharpe is structural evidence, whereas significant at 1 alone is usually\n        microstructure, and a single horizon cannot tell those apart. It is\n        empty when nothing clears. ``best_horizon`` is always the strongest\n        horizon whether or not it is significant, so a near miss (say q=0.06)\n        stays visible instead of collapsing into the same shape as a run that\n        fired 200 times to no effect \u2014 that row is often the most actionable in\n        a batch, because it is the one that says \"widen the window\".\n\n        SCOPE WARNING for ``detail=\"full\"``: each horizon there carries the\n        persisted ``significant`` flag, which is scan-scoped (BH across that\n        run's own horizons) and predates ``family_q_value``. Summary mode's\n        ``best_horizon.significant`` prefers the search-wide ``family_q_value``.\n        So the SAME horizon can read ``significant: true`` in full mode and\n        ``significant: false`` in summary mode \u2014 that is a difference of scope,\n        not a contradiction. Judge on ``family_q_value``, which full mode also\n        attaches per horizon.\n\n        ``best_horizon`` is ORDERED on the raw ``p_value`` (Benjamini-Hochberg\n        is monotone in raw-p rank, so this agrees with either correction while\n        avoiding BH's ties) and JUDGED on the strongest correction the horizon\n        carries: ``family_q_value`` (BH across the whole search family) ahead of\n        ``adjusted_p_value`` (BH across this scan's own horizons).\n        ``significance_basis`` names which one backed the verdict. When it is\n        null, no correction was available and ``significant`` is false \u2014\n        read that as \"corrected significance not established\", NOT as evidence\n        of no effect. ``multiplicity.family_complete`` is true because project\n        families are fully enumerated before q-values are attached. ``results``\n        is ordered by each run's best horizon, so the leading rows are the ones\n        to drill into if the payload is truncated.\n\n        **Pooled summary:** the response always includes a\n        ``pooled_summary`` (present in both detail modes) \u2014 a universe-level\n        meta-analysis that combines the per-symbol scan results into one\n        statistical verdict per horizon using Stouffer's weighted Z method\n        (weighted by ``sqrt(sample_size)``, signed by each symbol's t-stat),\n        with Benjamini-Hochberg FDR correction across horizons. It reports\n        ``pooled_verdict`` (long_signal/short_signal/no_signal/insufficient_universe),\n        per-horizon pooled stats, included/excluded symbols, and a caveat about\n        the cross-symbol independence assumption. The pool is computed over\n        every completed result in the batch before ``min_occurrences`` and\n        ``significant_only`` presentation filters are applied.\n\n        **Multiplicity (family_q_value):** the response also includes a\n        top-level ``multiplicity`` block plus a per-horizon ``family_q_value``\n        alongside ``adjusted_p_value`` (which stays the within-scan horizon\n        correction, unchanged). ``family_q_value`` is the Benjamini-Hochberg\n        q-value across every (condition x symbol x horizon) test in scope \u2014\n        every COMPLETED run in this batch, plus every completed scan in the\n        project when ``project_id`` is set (``family_scope=\"project\"``),\n        computed at READ time and never persisted. ``multiplicity`` states\n        ``method``, ``dependence_assumption``\n        (\"positive_regression_dependency\", with a ``dependence_note`` \u2014 BH is\n        anti-conservative if that assumption fails), ``family_scope``,\n        ``family_size``, ``family_complete`` (true because the project family\n        is fully enumerated), and ``computed_at``. It is a reported\n        number, not a verdict \u2014 it changes nothing else in this response.\n\n        **significance:** the response also includes a top-level\n        ``significance`` block (present in both detail modes, same as\n        ``multiplicity``/``pooled_summary``) reporting ``method`` and\n        ``iterations`` for the circular-shift randomization test behind\n        ``shift_p_value``/``adjusted_shift_p_value``. Omitted entirely when\n        every run in this batch is a legacy scan that predates the shift\n        test. See ``signal_scan``'s docstring for the test's null hypothesis,\n        its eligible-bar baseline, and its caveats (wrap-around adjacency,\n        the p >= 1/(m+1) floor, and the scan-vs-backtest entry-convention\n        gap) \u2014 those are constant across every scan and are not repeated\n        here.\n\n        Args:\n            batch_id: Batch ID returned by signal_scan.\n            min_occurrences: Exclude completed results with fewer than this many fires (moved to filtered_out).\n            significant_only: Return only symbols where at least one horizon has adjusted_p_value < 0.05 (Benjamini-Hochberg across that scan's own horizons). Reduces token usage by omitting non-significant results. NOTE: this filter is scan-scoped, while best_horizon.significant prefers the search-wide family_q_value \u2014 so a row can pass this filter and still report significant=false, which means it survived within its own scan but not across the whole search.\n            detail: \"summary\" (default) returns a compact per-run summary; \"full\" returns the complete per-run ScanResult.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "batch_id": {
            "title": "Batch Id",
            "type": "string"
          },
          "detail": {
            "default": "summary",
            "title": "Detail",
            "type": "string"
          },
          "min_occurrences": {
            "default": 0,
            "title": "Min Occurrences",
            "type": "integer"
          },
          "significant_only": {
            "default": false,
            "title": "Significant Only",
            "type": "boolean"
          }
        },
        "required": [
          "batch_id"
        ],
        "title": "get_scan_batchArguments",
        "type": "object"
      },
      "name": "get_scan_batch"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Get Strategy Patch Schemas",
        "toolGroup": "builder"
      },
      "description": "Return patchable condition targets grouped by role for a strategy.\n\n        Call before a parameter sweep to discover sweepable fields, current values,\n        and valid ranges. Returns one RoleGroup per blueprint item. A\n        bidirectional strategy returns separate entry groups with\n        direction=\"long\" and direction=\"short\". An exit scoped to one side also\n        reports its direction; exits applying to both sides and gates omit it.\n        Each group contains patchable leaf conditions with label, type, current\n        values, and JSON schema.\n\n        Labels are stable within a strategy version. Re-fetch after editing.\n        Use condition labels in run_backtest sweep overrides to vary parameters.\n\n        **Composite roots (all_of/any_of/sequence)**: the returned label list is\n        authoritative. The bare ``role.<definition_name>`` form is only a valid sweep\n        target when the rule uses a single non-composite definition; leaves inside a\n        composite must be targeted by their full path\n        ``role.<composite>.<leaf_name>`` (or ``role.<composite>.<type>[_n]`` for\n        unnamed children). Submitting a bare leaf name that lives inside a\n        composite returns ``InvalidOverrideError`` with a \"did you mean\" hint.\n\n        Example \u2014 patching an RSI leaf nested in an all_of composite:\n            label: ``\"entry.entry_combo.rsi_lt_30\"`` (not the bare\n            ``\"entry.rsi_lt_30\"``, which is rejected when ``entry_combo`` is the\n            composite root attached to the entry role).\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "strategy_id": {
            "description": "Strategy ID",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "get_strategy_patch_schemasArguments",
        "type": "object"
      },
      "name": "get_strategy_patch_schemas"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Get Walk-Forward Result",
        "toolGroup": "backtest"
      },
      "description": "\n        Get the status and results of a walk-forward analysis run.\n\n        Poll this tool after walk_forward() returns until status=\"completed\" or \"failed\".\n\n        Fields returned:\n\n        Level 1 (no sweep) \u2014 there is no in-sample/out-of-sample split at this\n        level, so despite the oos_ prefix every value below is a WHOLE-WINDOW\n        metric. It is a consistency check, not out-of-sample evidence:\n          - oos_sharpe_mean: mean whole-window Sharpe across windows\n          - oos_sharpe_std: standard deviation of whole-window Sharpe\n          - pct_profitable_windows: fraction of windows with positive return\n          - per_window: per-window breakdown (range, sharpe, total_return, trades)\n\n        Level 2 (with sweep):\n          - wfe_mean: mean Walk-Forward Efficiency (OOS Sharpe / IS Sharpe)\n              across windows; closer to 1.0 means OOS tracked IS\n          - parameter_stability: per param key, the list of selected parameter\n              values \u2014 one entry per in-sample window with valid metrics\n              (excluded windows omitted)\n          - pct_profitable_windows: fraction of OOS windows with positive return\n          - per_window: is_range, oos_range, is_sharpe, oos_sharpe, wfe, selected_params (the params chosen by select_by)\n\n        Args:\n            walk_forward_id: Walk-forward run identifier from walk_forward().\n\n        Returns:\n            GetWalkForwardResponse with status, aggregate metrics, and per-window results.\n\n        Raises:\n            StructuredToolError: With error codes:\n                - NOT_FOUND: If walk-forward run doesn't exist\n                - EXECUTION_SERVICE_ERROR: If API service fails\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "per_window_limit": {
            "default": 50,
            "description": "Max per_window entries to return (default 50, max 200).",
            "maximum": 200,
            "minimum": 1,
            "title": "Per Window Limit",
            "type": "integer"
          },
          "per_window_offset": {
            "default": 0,
            "description": "Number of leading per_window entries to skip for paging.",
            "maximum": 10000,
            "minimum": 0,
            "title": "Per Window Offset",
            "type": "integer"
          },
          "walk_forward_id": {
            "description": "Walk-forward run identifier",
            "title": "Walk Forward Id",
            "type": "string"
          }
        },
        "required": [
          "walk_forward_id"
        ],
        "title": "get_walk_forwardArguments",
        "type": "object"
      },
      "name": "get_walk_forward"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "requires_capability": "custom_events",
        "title": "Ingest Events",
        "toolGroup": "event"
      },
      "description": "Batch-insert event occurrences into BigQuery.\n\n        Validates the event type exists and is active, then writes all events\n        idempotently \u2014 ingesting the same event again updates it in place\n        rather than creating a duplicate, so a corrected re-upload for the\n        same (event_type_id, symbol, event_ts) is safe. Every source persists\n        to BigQuery (`inserted` counts persisted rows, post-dedup) \u2014 a webhook\n        or system event is never delivered live without also being durably\n        stored, so it remains visible to `query_events` and backtestable\n        after the fact. `source='backfill'` is historical/manual\n        entry and persists only; `source='webhook'`/`'system'` additionally\n        publish to Pub/Sub for immediate delivery to running paper sessions \u2014\n        check the response's `published` field to confirm that happened.\n\n        Timestamp format: `event_ts` MUST be ISO 8601 with an explicit timezone\n        offset (e.g. `2025-01-15T14:00:00Z` or `2025-01-15T14:00:00-05:00`).\n        Naive timestamps (no offset) are rejected \u2014 do NOT silently assume UTC;\n        send the offset explicitly so the stored time is unambiguous.\n\n        Example events:\n            [\n                {\n                    \"event_ts\": \"2025-01-15T14:00:00Z\",\n                    \"symbol\": \"SPY\",\n                    \"payload\": {\"direction\": \"bullish\"}\n                },\n                {\"event_ts\": \"2025-03-19T18:00:00-04:00\"}\n            ]\n\n        Args:\n            event_type_id: Must reference an existing event type\n            events: List of event dicts with at least event_ts\n            source: Source label (default: 'backfill')\n\n        Returns:\n            IngestEventsResponse with the count of persisted events (`inserted`)\n            and whether this batch was also published for real-time delivery\n            (`published`)\n\n        Raises:\n            StructuredToolError: UNAUTHORIZED if caller lacks CUSTOM_EVENTS capability\n            StructuredToolError: EVENT_TYPE_NOT_FOUND if event type doesn't exist\n            StructuredToolError: VALIDATION_ERROR if events list is empty or malformed\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "event_type_id": {
            "description": "Event type ID (must exist and be active)",
            "title": "Event Type Id",
            "type": "string"
          },
          "events": {
            "description": "List of events to ingest. Each event: {event_ts: ISO timestamp (required), symbol: str (optional), payload: dict (optional)}",
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Events",
            "type": "array"
          },
          "source": {
            "default": "backfill",
            "description": "Source label: 'backfill' (historical), 'webhook' (real-time), 'system'",
            "title": "Source",
            "type": "string"
          }
        },
        "required": [
          "event_type_id",
          "events"
        ],
        "title": "ingest_eventsArguments",
        "type": "object"
      },
      "name": "ingest_events"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "List Assets",
        "toolGroup": "strategy"
      },
      "description": "List available trading assets with timeframes and data coverage.\n\n        Covers the entire US equity + crypto market \u2014 thousands of symbols.\n        Prefer passing `symbols=[...]` to check specific tickers; pass\n        `fetch_all=True` only when you actually need to enumerate the universe.\n\n        Discover what symbols, timeframes, and date ranges are available for\n        backtesting. Use this before creating strategies to know what data exists.\n\n        Each asset carries a ``status``: ``active`` (fresh registry equity or\n        fresh crypto composite), ``renamed`` (equity traded under an older\n        Polygon ticker before a rename), or ``unknown`` (equity not in the\n        registry, or data >10 calendar days behind the frontier).\n\n        A date range is NOT a promise of continuity. Every asset carries\n        ``daily_bars`` (bars actually present), ``coverage_ratio`` (actual /\n        expected sessions across the reported range, 0.0-1.0 \u2014 expected is the\n        EXACT XNYS session count for equities, not an average rate, and a real\n        gap is floored, never rounded, so it can never read as 1.0),\n        ``missing_trading_days`` (exact count of expected sessions with no\n        bar \u2014 does not dilute over a long history the way coverage_ratio can),\n        and ``largest_gap_days`` / ``largest_gap_range`` (the longest run of\n        calendar days with no bar, and the actual dates it spans \u2014 check the\n        range's ``end`` against today to tell stale history from an active\n        problem). Check them before you trust a span: SPY's raw 2007-2026\n        extent is an island \u2014 94 bars in 2007, none at all across 2010-2015,\n        dense only from 2016-06-27 \u2014 which scores ``coverage_ratio`` 0.61 and\n        ``largest_gap_days`` 2679, while a genuinely dense AAPL scores 1.0,\n        ``missing_trading_days`` 0, and ``largest_gap_days`` 6. A short recent\n        outage on an otherwise-dense symbol still shows up in\n        ``missing_trading_days`` and ``largest_gap_range`` even though it is\n        too small a fraction of 20 years to move the rounded ``coverage_ratio``\n        much. Backtesting across a large gap silently skips it. ``timeframes``\n        lists the granularities the platform derives, not seven independently\n        measured coverages; all of them are built from the same 1m source, so\n        these daily figures bound every one of them.\n\n        The response also carries a top-level ``data_floor_date`` \u2014 the earliest\n        ``first_date`` across the full filtered set (the global data floor,\n        stable across pages). It is ``None`` when no assets match.\n\n        Returns:\n            ListAssetsResponse with available assets grouped by symbol\n\n        Raises:\n            StructuredToolError: With VALIDATION_ERROR if neither `symbols` nor\n                `fetch_all=True` is given, or if both are given; with\n                DATABASE_ERROR if BigQuery is unavailable\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "asset_class": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Filter by asset class: 'equity' or 'crypto'",
            "title": "Asset Class"
          },
          "fetch_all": {
            "default": false,
            "description": "Explicitly page through the full asset universe instead of checking specific symbols. Required when `symbols` is omitted.",
            "title": "Fetch All",
            "type": "boolean"
          },
          "limit": {
            "anyOf": [
              {
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Max number of assets to return. Defaults to 70 when fetching the full universe. Use offset to paginate.",
            "title": "Limit"
          },
          "offset": {
            "default": 0,
            "description": "Number of assets to skip before returning rows. Use with limit to paginate.",
            "title": "Offset",
            "type": "integer"
          },
          "summary": {
            "default": false,
            "description": "Return compact one-row-per-symbol summary (symbol, asset_class, source, first_date, last_date, timeframe_count). Use when you only need to know what assets exist, not their full data profile.",
            "title": "Summary",
            "type": "boolean"
          },
          "symbols": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Filter to these exact symbols (e.g. ['AAPL', 'BTC-USD'])",
            "title": "Symbols"
          }
        },
        "title": "list_assetsArguments",
        "type": "object"
      },
      "name": "list_assets"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "requires_capability": "system_events",
        "title": "List Event Types",
        "toolGroup": "event"
      },
      "description": "Discover the event-type catalog in two steps: list, then read detail.\n\n        Call bare first (optionally with `category`). Returns a COMPACT catalog\n        \u2014 id and occurrence_count only, no name/description/supports_forward_triggers\n        \u2014 grouped into system_event_types (curated by Quawd; reference directly,\n        never call create_event_type for these) and custom_event_types (yours,\n        from create_event_type), plus a top-level `forward_trigger_ids` list\n        naming which ids (from either group) compile with pre_event/in_window.\n        This is compact on purpose: the full catalog with name+description\n        already exceeds the ~4,000-char budget an agent's view of this tool is\n        bounded to, and past that budget results are NOT gracefully paginated \u2014\n        they are structurally truncated to 20 items per list, so a naive full\n        listing goes silently invisible past a handful of types with no error.\n        If the catalog keeps growing, pass `category=...` to stay under that\n        cliff instead of discovering the truncation after the fact.\n\n        Then call again with `ids=[...]` (ids you saw in the compact list) to\n        get the FULL shape \u2014 name, description, payload_schema, symbol\n        coverage, occurrence timestamps, supports_forward_triggers \u2014 for just\n        the ids you actually care about. Do not guess ids; the bare call is\n        what tells you which exist.\n\n        Returns:\n            Bare/category call: dict with `system_event_types`,\n            `custom_event_types` (compact entries), `forward_trigger_ids`,\n            `summary`, `guidance`.\n            `ids` call: dict with `event_types` (full detail, requested order),\n            `not_found` (unmatched requested ids), `summary`.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "category": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Filter the bare-call catalog to one system taxonomy family: corporate, earnings, news, macro, energy, equity, social, or custom. An unrecognized value returns an empty catalog, never the full list. Mutually exclusive with `ids`. This is the escape hatch once the catalog outgrows ~45 system types: results are NOT paginated, and an oversized response gets structurally truncated to 20 items per list (dropping the alphabetical tail) instead of erroring \u2014 narrow with `category` rather than assuming a bare call always returns everything.",
            "title": "Category"
          },
          "ids": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Full-detail lookup for specific event type ids (system or custom, mix freely) \u2014 returns name, description, payload_schema, symbol coverage, and occurrence timestamps for exactly these ids, in the order given. Max 10 ids per call (that much full detail is exactly the payload the bare call avoids). Unknown ids are reported in `not_found`, never silently dropped. Mutually exclusive with `category`.",
            "title": "Ids"
          }
        },
        "title": "list_event_typesArguments",
        "type": "object"
      },
      "name": "list_event_types"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "toolGroup": "paper"
      },
      "description": "\n        List paper trading sessions for a strategy.\n\n        Returns sessions ordered by creation time (most recent first).\n\n        Args:\n            strategy_id: Strategy to list sessions for\n            limit: Maximum results (default: 20)\n            offset: Number of leading sessions to skip for paging (default: 0)\n\n        Returns:\n            ListSessionsResponse with session summaries\n\n        Raises:\n            StructuredToolError: With STRATEGY_NOT_FOUND if strategy doesn't exist\n                or the caller doesn't own it.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "limit": {
            "default": 20,
            "description": "Max sessions to return (default 20, max 100).",
            "maximum": 100,
            "minimum": 1,
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "default": 0,
            "description": "Number of leading sessions to skip for paging.",
            "maximum": 10000,
            "minimum": 0,
            "title": "Offset",
            "type": "integer"
          },
          "strategy_id": {
            "description": "Strategy identifier",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "list_paper_trading_sessionsArguments",
        "type": "object"
      },
      "name": "list_paper_trading_sessions"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "List Portfolios",
        "toolGroup": "portfolio"
      },
      "description": "List portfolios owned by the current user, most-recently-created first.\n\n        Returns compact identities, member counts and construction kinds plus\n        account-wide `total`. Use get_portfolio(portfolio_id) for members,\n        allocation and shared-signal source; those trees are omitted here.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "limit": {
            "default": 20,
            "description": "Max portfolios to return (default 20, max 100)",
            "maximum": 100,
            "minimum": 1,
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "default": 0,
            "description": "Number of portfolios to skip, most-recently-created first",
            "maximum": 10000,
            "minimum": 0,
            "title": "Offset",
            "type": "integer"
          }
        },
        "title": "list_portfoliosArguments",
        "type": "object"
      },
      "name": "list_portfolios"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "List Backtest Runs",
        "toolGroup": "backtest"
      },
      "description": "\n        List strategy or portfolio backtests and walk-forward analyses; strategy sweeps are also supported.\n\n        Provide portfolio_id for portfolio history, strategy_id for a strategy, or\n        batch_id for sweep children. Portfolio selection cannot combine with\n        other selectors. Portfolio history includes backtests and walk-forward\n        analyses; child optimization backtests are excluded.\n\n        Note on type='all': sweep variants appear twice \u2014 once as individual\n        backtest entries and once collapsed under their sweep entry. Use\n        type='sweep' if you want one row per sweep instead of N+1.\n\n        Args:\n            strategy_id: Strategy to list runs for (optional if batch_id given)\n            batch_id: Sweep batch to expand into child backtests\n            type: Filter by run kind (default 'all')\n            limit: Maximum results per page (default: 50)\n            offset: Number of results to skip (default: 0)\n\n        Returns:\n            ListRunsResponse with run summaries and pagination metadata.\n\n        Raises:\n            StructuredToolError:\n                - VALIDATION_ERROR if neither strategy_id nor batch_id is provided\n                - STRATEGY_NOT_FOUND if strategy_id is given but strategy doesn't exist\n        ",
      "input_schema": {
        "$defs": {
          "RunKind": {
            "description": "The kinds of run ``list_runs`` can filter on.\n\n``ALL`` is a filter sentinel, not a kind any run has \u2014 which is why\n:data:`ActualRunKind` narrows it away for the response model. Declaring the\ntwo separately is what let the tool's filter and its own response disagree\nabout the vocabulary before M2.",
            "enum": [
              "backtest",
              "sweep",
              "walk_forward",
              "all"
            ],
            "title": "RunKind",
            "type": "string"
          }
        },
        "additionalProperties": false,
        "properties": {
          "batch_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Sweep batch identifier. When provided, returns the child backtests of that sweep (type is forced to 'backtest').",
            "title": "Batch Id"
          },
          "limit": {
            "default": 50,
            "description": "Maximum number of runs to return per page (default 50, max 100)",
            "maximum": 100,
            "minimum": 1,
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "default": 0,
            "description": "Number of results to skip for pagination",
            "title": "Offset",
            "type": "integer"
          },
          "portfolio_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Portfolio run history; cannot combine with strategy_id or batch_id.",
            "title": "Portfolio Id"
          },
          "strategy_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Strategy identifier. Required unless portfolio_id or batch_id is provided.",
            "title": "Strategy Id"
          },
          "type": {
            "$ref": "#/$defs/RunKind",
            "default": "all",
            "description": "Run kind to list. 'backtest' returns individual backtest runs; 'sweep' collapses backtests by batch_id; 'walk_forward' returns walk-forward analyses; 'all' unions everything sorted by created_at DESC."
          }
        },
        "title": "list_runsArguments",
        "type": "object"
      },
      "name": "list_runs"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "requires_capability": "research_projects",
        "title": "Create Project",
        "toolGroup": "project"
      },
      "description": "Use FIRST when starting a new research effort. Projects group related\n        strategies under one thesis and provide a shared scratchpad \u2014 every\n        ChatGPT session should pick or create a project before any strategy work.\n\n        Pass the returned id as project_id to create_strategy so strategies are linked\n        to the project. Use project_write_scratchpad to record findings as you\n        iterate, and project_get_scratchpad on a future session to resume work.\n\n        Args:\n            name: Short project name, identifiable in a list (e.g. \"RSI mean revert\").\n            description: Optional thesis or research question.\n\n        Returns:\n            ProjectResponse with id you'll pass as project_id to create_strategy.\n\n        Raises:\n            StructuredToolError: UNAUTHORIZED if caller's tier doesn't include `research_projects`.\n            StructuredToolError: VALIDATION_ERROR if not authenticated.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "description": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Thesis description",
            "title": "Description"
          },
          "name": {
            "description": "Project name",
            "title": "Name",
            "type": "string"
          }
        },
        "required": [
          "name"
        ],
        "title": "project_createArguments",
        "type": "object"
      },
      "name": "project_create"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "requires_capability": "research_projects",
        "title": "Delete Project",
        "toolGroup": "project"
      },
      "description": "Permanently delete an EMPTY research project. IRREVERSIBLE \u2014 there is\n        no undo and no archive; the project and all of its scratchpad notes are\n        gone for good.\n\n        Use this only for housekeeping: a project created by mistake, a\n        duplicate, or an abandoned/empty thesis that is cluttering project_list.\n        Do NOT use it to \"finish\" or \"close out\" work \u2014 a completed project is\n        worth keeping for its scratchpad history.\n\n        Safety: this REFUSES to delete a project that still contains strategies.\n        The error reports how many are blocking. No tool moves a strategy to\n        another project, so the only way to unblock the delete is to permanently\n        delete each blocking strategy with builder_delete_strategy(strategy_id=...)\n        and then retry project_delete \u2014 if those strategies are worth keeping,\n        keep the project. Strategies are never cascade-deleted by this tool. A\n        strategy whose stored document predates the current shape (listed in\n        project_get's unreadable_strategies) also blocks the delete;\n        builder_delete_strategy can delete it.\n\n        Args:\n            project_id: From project_list or project_create.\n\n        Returns:\n            ProjectDeleteResponse with deleted=True and the deleted project name.\n\n        Raises:\n            StructuredToolError: PROJECT_NOT_FOUND if missing or owned by another user.\n            StructuredToolError: INVALID_STATUS if the project still contains strategies.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "description": "Project identifier to permanently delete",
            "title": "Project Id",
            "type": "string"
          }
        },
        "required": [
          "project_id"
        ],
        "title": "project_deleteArguments",
        "type": "object"
      },
      "name": "project_delete"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "Get Project",
        "toolGroup": "project"
      },
      "description": "Use to inspect a specific project's full state \u2014 strategy list, pipeline\n        stages, asset coverage, linked event types. Pair with project_get_scratchpad\n        when resuming so you know both what's there (project_get) and what was\n        learned (scratchpad).\n\n        When a project holds 2+ validated strategies, consider composing them into a\n        portfolio (create_portfolio) to run them together as one allocated book.\n\n        Args:\n            project_id: From project_create or project_list.\n\n        Returns:\n            ProjectResponse with strategies_by_stage, assets, event_type_ids.\n\n        Raises:\n            StructuredToolError: PROJECT_NOT_FOUND if missing or owned by another user.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "project_id": {
            "description": "Project identifier",
            "title": "Project Id",
            "type": "string"
          }
        },
        "required": [
          "project_id"
        ],
        "title": "project_getArguments",
        "type": "object"
      },
      "name": "project_get"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "requires_capability": "research_projects",
        "title": "Get Project Scratchpad",
        "toolGroup": "project"
      },
      "description": "Use when RESUMING work to recall what was learned previously. Returns\n        scratchpad entries newest-first.\n\n        Standard resume flow:\n          1. project_list() \u2192 pick the project\n          2. project_get_scratchpad(parent_type=\"project\", parent_id=<id>)\n             \u2192 read the latest 10-20 notes\n          3. Summarize for the user before suggesting next steps.\n\n        Args:\n            parent_type: \"project\" or \"strategy\".\n            parent_id: The project_id or strategy_id.\n            limit: How many entries to return (default 20, newest first).\n\n        Returns:\n            ScratchpadResponse with entries[].\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "limit": {
            "default": 20,
            "description": "Maximum entries to return",
            "title": "Limit",
            "type": "integer"
          },
          "parent_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "ID of the project or strategy",
            "title": "Parent Id"
          },
          "parent_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Parent type: 'project' or 'strategy'",
            "title": "Parent Type"
          },
          "project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Convenience alias: pass project_id instead of parent_type + parent_id",
            "title": "Project Id"
          }
        },
        "title": "project_get_scratchpadArguments",
        "type": "object"
      },
      "name": "project_get_scratchpad"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "requires_capability": "research_projects",
        "title": "List Projects",
        "toolGroup": "project"
      },
      "description": "Use at the START of a session to find existing research projects.\n        If the user is resuming work (\"pick up where I left off\", \"what was I\n        doing on SPY momentum\"), call this first to get the project_id, then\n        call project_get_scratchpad(parent_id=<project_id>) to read prior notes.\n\n        Paginated, newest-activity first. Prefer narrowing with `q` over paging:\n        an account can hold thousands of projects, and the first page is usually\n        the right one. Follow `next_cursor` only when you genuinely need more.\n\n        Returns a light per-project summary. For a project's strategy list and\n        linked event types, call project_get with the id from here.\n\n        If no project matches, call project_create to start a fresh one.\n\n        Args:\n            limit: Projects per page.\n            cursor: `next_cursor` from the previous page.\n            q: Name prefix filter.\n\n        Returns:\n            ProjectListResponse \u2014 `projects` (this page), `count` (items on this\n            page), and `next_cursor` (None when the last page was reached; note a\n            page that is exactly `limit` long still returns a cursor, so the\n            follow-up call can legitimately come back empty).\n\n        Raises:\n            StructuredToolError: VALIDATION_ERROR if `cursor` is malformed.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "cursor": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "`next_cursor` from the previous call. Omit for the first page.",
            "title": "Cursor"
          },
          "limit": {
            "default": 20,
            "description": "Projects per page (default 20, max 100). Pages are ordered most-recently-updated first, so the default page already covers 'what was I working on'.",
            "maximum": 100,
            "minimum": 1,
            "title": "Limit",
            "type": "integer"
          },
          "q": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Case-insensitive name PREFIX filter. 'spy' matches 'SPY momentum' but NOT 'Momentum on SPY' \u2014 this is a prefix match, not a substring search. Reuse a cursor only with the same q it was issued under.",
            "title": "Q"
          }
        },
        "title": "project_listArguments",
        "type": "object"
      },
      "name": "project_list"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "requires_capability": "research_projects",
        "title": "Write Project Scratchpad",
        "toolGroup": "project"
      },
      "description": "Use AFTER analyzing backtest or signal-scan results to capture findings.\n        Persistent across sessions \u2014 future calls to project_get_scratchpad will\n        surface these entries newest-first, letting you resume research where\n        you left off.\n\n        Examples of what to write:\n        - \"RSI<25 entry on SPY: too few trades; widening to RSI<30 next.\"\n        - \"Walk-forward WFE 0.42 \u2014 overfit. Dropping the volume filter.\"\n        - \"Best variant: lookback=60, period=14. Sharpe 1.8 in-sample,\n           1.6 holdout. Promote to paper next session.\"\n\n        Args:\n            parent_type: \"project\" or \"strategy\" \u2014 usually \"project\" for\n                cross-strategy findings, \"strategy\" for variant-specific notes.\n            parent_id: The project_id or strategy_id.\n            label: Short headline (e.g. \"overfit-finding\"); defaults to first\n                60 chars of content if omitted.\n            content: The actual note. Be specific and actionable for future-you.\n\n        Returns:\n            ScratchpadEntryResponse confirming the write.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "content": {
            "description": "The note content",
            "title": "Content",
            "type": "string"
          },
          "label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Short label for this note (shown in UI as a clickable title). Defaults to the first 60 characters of content when omitted.",
            "title": "Label"
          },
          "parent_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "ID of the project or strategy",
            "title": "Parent Id"
          },
          "parent_type": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Parent type: 'project' or 'strategy'",
            "title": "Parent Type"
          },
          "project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Convenience alias: pass project_id instead of parent_type + parent_id",
            "title": "Project Id"
          }
        },
        "required": [
          "content"
        ],
        "title": "project_write_scratchpadArguments",
        "type": "object"
      },
      "name": "project_write_scratchpad"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "requires_capability": "system_events",
        "title": "Query Events",
        "toolGroup": "event"
      },
      "description": "Query event occurrences by type and time range.\n\n        Works for both system and custom event types. For custom event types,\n        only occurrences belonging to the calling user are visible \u2014 you cannot\n        see another user's custom events. System events are global.\n\n        Returns events ordered by event_ts. Use to verify ingested data\n        or explore event patterns.\n\n        Event types backed by licensed market data (the corporate.* family and\n        any other system type not sourced from a public feed) never read stored\n        occurrences. They return the registered payload schema and one\n        deterministic synthetic occurrence with a `sample_notice`. For those\n        types `start_ts` and `end_ts` are accepted but ignored for compatibility\n        with clients whose cached schema still requires them. `symbol` and nonzero\n        `offset` remain rejected because they cannot apply to synthetic data. Use\n        list_event_types(ids=[...]) for their schema and coverage counts.\n\n        Args:\n            event_type_id: Event type to query\n            start_ts: Start of time range (ISO format); required unless the type\n                is licensed, where it is ignored\n            end_ts: End of time range (ISO format); required unless the type is\n                licensed, where it is ignored\n            symbol: Optional symbol filter (includes global events too); rejected\n                for licensed types\n\n        Returns:\n            QueryEventsResponse with matching occurrences\n\n        Raises:\n            StructuredToolError: UNAUTHORIZED if caller lacks SYSTEM_EVENTS capability\n            StructuredToolError: EVENT_TYPE_NOT_FOUND if event type doesn't exist\n            StructuredToolError: VALIDATION_ERROR if timestamps are invalid or a\n                licensed type is called with a filter or paging argument\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "end_ts": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "End timestamp (ISO, inclusive). Required for ordinary event types; ignored for licensed ones, which return a synthetic example.",
            "title": "End Ts"
          },
          "event_type_id": {
            "description": "Event type ID to query",
            "title": "Event Type Id",
            "type": "string"
          },
          "limit": {
            "default": 100,
            "description": "Max occurrences to return (default 100, max 200).",
            "maximum": 200,
            "minimum": 1,
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "default": 0,
            "description": "Number of leading occurrences to skip for paging.",
            "maximum": 10000,
            "minimum": 0,
            "title": "Offset",
            "type": "integer"
          },
          "start_ts": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Start timestamp (ISO, inclusive). Required for ordinary event types; ignored for licensed ones, which return a synthetic example.",
            "title": "Start Ts"
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional symbol filter. Not accepted for licensed event types.",
            "title": "Symbol"
          }
        },
        "required": [
          "event_type_id"
        ],
        "title": "query_eventsArguments",
        "type": "object"
      },
      "name": "query_events"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Release Holdout",
        "toolGroup": "backtest"
      },
      "description": "Discard a project's reserved holdout window (escape hatch).\n\n        Clears ``holdout_start``, ``holdout_end`` and resets\n        ``holdout_validation_count``. The window is reserved once, at project\n        creation, so releasing it is **permanent** \u2014 nothing re-allocates one.\n        Use this to unblock research when a backtest range falls entirely inside\n        the reserved holdout (the `run_backtest` error points here) and you\n        accept giving up out-of-sample validation for this project.\n\n        This throws away out-of-sample-integrity state (any prior holdout\n        validations no longer correspond to the reserved window), so it requires\n        ``confirm=true``. With ``confirm=false`` it is a no-op that reports the\n        current holdout window without mutating anything.\n\n        Args:\n            project_id: Project whose holdout window to release.\n            confirm: Must be true to perform the release.\n\n        Returns:\n            A dict describing the action taken (``released`` bool), the cleared\n            window (if any), and a next-step hint.\n\n        Raises:\n            StructuredToolError: If the project repository is unavailable or the\n                project does not exist / is not owned by the caller.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "confirm": {
            "default": false,
            "description": "Must be true to actually release the holdout. This discards research-integrity state, so it is a no-op unless confirm=true.",
            "title": "Confirm",
            "type": "boolean"
          },
          "project_id": {
            "description": "Research project identifier",
            "title": "Project Id",
            "type": "string"
          }
        },
        "required": [
          "project_id"
        ],
        "title": "release_holdoutArguments",
        "type": "object"
      },
      "name": "release_holdout"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Rerun Backtest",
        "toolGroup": "backtest"
      },
      "description": "Re-run an existing backtest, by default WITH per-bar diagnostics.\n\n        Copies the original run's strategy revision, date range, initial cash,\n        fee and slippage, then queues a new run. It does NOT carry over per-run\n        overrides, benchmark_symbol, or a sweep's combo_params \u2014 pass those again\n        via run_backtest if you need them. This is the recovery path when\n        explain_bar or get_condition_timeline reports that diagnostics were not\n        recorded.\n\n        `storage_profile` is retention; `collect_diagnostics` is capture. A\n        profile cannot persist condition data the engine never computed, so\n        re-running with the diagnostic profile alone would NOT restore\n        explain_bar -- that is why capture defaults to true here.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "backtest_id": {
            "description": "ID of the backtest to re-run",
            "title": "Backtest Id",
            "type": "string"
          },
          "collect_diagnostics": {
            "default": true,
            "description": "Capture per-bar condition diagnostics on the re-run. Defaults to true because this is the recovery path for a run that lacked them -- explain_bar and get_condition_timeline need it. Refused on runs above the diagnostics size ceiling; narrow the date range instead.",
            "title": "Collect Diagnostics",
            "type": "boolean"
          },
          "storage_profile": {
            "default": "backtest_diagnostic",
            "description": "Storage profile for the re-run. 'backtest_diagnostic' retains indicators, condition data and bar events; 'backtest_minimal' retains none of them.",
            "title": "Storage Profile",
            "type": "string"
          }
        },
        "required": [
          "backtest_id"
        ],
        "title": "rerun_backtestArguments",
        "type": "object"
      },
      "name": "rerun_backtest"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "requires_capability": "custom_events",
        "title": "Reset Event Type Schema",
        "toolGroup": "event"
      },
      "description": "Clear an inferred payload_schema so the next ingest re-infers from scratch.\n\n        Use this to recover when the first ingested payload locked in wrong field\n        types (e.g. a numeric value sent as a string). After clearing, the next\n        ingest_events call will infer a fresh schema from the new payload.\n\n        Constraints (matches the API's reset-schema route):\n        * Only the owner of a custom event type may reset its schema.\n        * System event type schemas cannot be reset.\n        * Only inferred schemas (those with ``inferred_at`` set) may be cleared.\n          User-declared schemas are intentional contracts \u2014 delete the event type\n          and recreate it if you need to change a declared schema.\n        * If the schema is already None, returns VALIDATION_ERROR \u2014 there is\n          nothing to reset.\n\n        Args:\n            event_type_id: The custom event type id whose schema should be cleared.\n\n        Returns:\n            ResetEventTypeSchemaResponse with the event type id and ``cleared=True``.\n\n        Raises:\n            StructuredToolError: EVENT_TYPE_NOT_FOUND if the event type does not exist.\n            StructuredToolError: FORBIDDEN if the type is a system type.\n            StructuredToolError: UNAUTHORIZED if the caller targets another user's namespace.\n            StructuredToolError: VALIDATION_ERROR if there is no schema to reset, or\n                if the schema is user-declared.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "event_type_id": {
            "description": "ID of the custom event type whose inferred payload_schema should be cleared.",
            "title": "Event Type Id",
            "type": "string"
          }
        },
        "required": [
          "event_type_id"
        ],
        "title": "reset_event_type_schemaArguments",
        "type": "object"
      },
      "name": "reset_event_type_schema"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Run Backtest",
        "toolGroup": "backtest"
      },
      "description": "\n        Run a backtest of a strategy, or of a portfolio via portfolio_id.\n\n        COMPARING MORE THAN ONE VERSION? Pass `sweep` instead of calling this once per\n        version. Variants run in parallel in a single call, so five thresholds cost one\n        round trip rather than five, and the call waits for them rather than handing back\n        ids to poll. See the `sweep` parameter; get_strategy_patch_schemas(strategy_id)\n        lists the labels and patch shapes this strategy accepts.\n\n        After reviewing the results, save key findings with project_write_scratchpad\n        so they carry into your next session.\n\n        Trade list location: `results.trades`. When trades are capped,\n        `results.trade_count` is the full pre-cap count, `results.trade_count_returned`\n        is what was actually included, and `results.trade_pagination_hint` names\n        the follow-up tool. Default `detail=\"summary\"` caps trades at 20;\n        `detail=\"full\"` caps at 500. For full pagination use\n        `get_backtest(backtest_id, include=[\"trades\"], trades_offset, trades_limit)`.\n\n        The date range is either `lookback` (relative to today, \"3mo\" when no\n        range is given) or an explicit `start_date`/`end_date`. The backtest is\n        queued; a single run waits up to 60s for completion (ChatGPT clients get\n        an immediate response and their widget polls), and a sweep waits 60s plus\n        10s per variant, capped at 300s. If the wait expires the run keeps going\n        and the response `message` says how to follow it: get_backtest(backtest_id),\n        or list_runs(batch_id=...) for a sweep.\n\n        A sweep returns batch_id, count, and backtests[] with per-variant\n        status/statistics/trade_summary inline. zip_by_index pairs lists by\n        position (count = list length); cartesian runs every combination\n        (count = product of list lengths).\n\n        Condition labels are ``role.<definition_name>``; definition names are set with\n        add_rule(name=...) or builder_add_condition(name=...), or auto-derived (e.g. 'rsi_lt_30').\n        Positional (type-based) labels apply only to unnamed conditions, such as\n        the unnamed children of a composite (see below). A patch varies only\n        Patchable values \u2014 authoring fields (left/op/conditions and similar)\n        cannot be swept. get_strategy_patch_schemas(strategy_id) returns the\n        exact labels and patch shapes this strategy accepts.\n\n        Composite roots (all_of/any_of/sequence): the bare ``role.<definition_name>`` form is\n        only valid when the rule uses a single non-composite definition. Leaves inside a\n        composite must be addressed with the full path\n        ``role.<composite_name>.<leaf_name>`` (or ``role.<composite>.<type>[_n]`` for\n        unnamed children). Submitting a bare leaf name that lives inside a composite\n        will return ``InvalidOverrideError`` with a \"did you mean\" hint pointing at\n        the full composite path.\n\n        After analyzing results, capture key findings via project_write_scratchpad\n        (parent_type=\"project\", parent_id=<the strategy's project_id>) so future\n        sessions can pick up where you left off. Don't skip this \u2014 scratchpad\n        entries are the primary mechanism for cross-session continuity.\n\n        Always check the `warnings` field before declaring the run successful \u2014\n        it carries the engine's own disclosures (open positions at the end,\n        NaN-inert conditions, event types with no occurrences or look-ahead\n        risk, data coverage gaps, a shared pool over 100%) and flags\n        result-reliability issues such as entries rejected for insufficient\n        capital, low trade counts, and missing entry conditions.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "benchmark_symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional secondary market-index benchmark symbol (e.g. 'SPY' for a US equities strategy). When set, results include market_benchmark_return and market_benchmark_max_drawdown alongside the per-symbol buy-and-hold benchmark \u2014 useful for judging strategy alpha vs. the broad market, not just vs. buy-and-hold of the traded asset.",
            "title": "Benchmark Symbol"
          },
          "collect_diagnostics": {
            "default": false,
            "description": "Capture per-bar condition diagnostics so explain_bar and get_condition_timeline can explain this run bar by bar. Defaults to false: on a realistic multi-condition strategy capture costs 40-70% more CPU and ~5x the memory, and most runs are never inspected. Leave it off while sweeping or screening; turn it on for the one run you intend to investigate, or recover afterwards with rerun_backtest. Refused on runs above the diagnostics size ceiling -- narrow the date range or use a coarser resolution instead.",
            "title": "Collect Diagnostics",
            "type": "boolean"
          },
          "detail": {
            "default": "summary",
            "description": "Result detail: 'summary' (default, trades capped at 20, per-trade fields slimmed to id/symbol/direction/entry+exit time+price+bar/pnl/exit_reason/exit_card_name/is_win/is_open, bar_times dropped, equity_curve returned as parallel arrays) or 'full' (trades capped at 500, full diagnostic shape). Statistics, trade_summary, signal_summary, and equity_summary are unchanged. For the dropped per-trade fields use get_backtest(detail='full'); for paginated access to all trades use get_backtest(include=[\"trades\"], trades_offset, trades_limit).",
            "enum": [
              "summary",
              "full"
            ],
            "title": "Detail",
            "type": "string"
          },
          "end_date": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "End date (YYYY-MM-DD). Mutually exclusive with lookback.",
            "title": "End Date"
          },
          "fee_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Trading fee as percentage (0.1 = 0.1%). None=auto-detect (equities=0.00%; crypto/mixed=0.50%). Set 0 for zero fees.",
            "title": "Fee Pct"
          },
          "initial_cash": {
            "default": 100000.0,
            "description": "Initial cash amount",
            "exclusiveMinimum": 0,
            "title": "Initial Cash",
            "type": "number"
          },
          "lookback": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Lookback period from today: '3mo' (3 months), '6mo', '1yr' (year), '2wk' (weeks), '30d' (days). Default: 3mo. Mutually exclusive with start_date/end_date.",
            "title": "Lookback"
          },
          "overrides": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional per-run strategy override patch. Overridable sections: sizing, position_policy, execution, risk_policy, conditions, and allocation (universe/basket runs only). Example: {\"sizing\":{\"mode\":\"fixed_usd\",\"fixed_usd\":5000},\"execution\":{\"order_type\":\"market\"}}. NOTE the key-name difference: builder_set_strategy_config takes patch={'risk': ...}, but here the section is named 'risk_policy' (same name builder_get_strategy reads it back under as config.risk_policy) \u2014 'risk' is rejected as an extra input. To disable the short-equity liquidation floor for one research run: {\"risk_policy\":{\"short_equity_floor_pct\":null}}",
            "title": "Overrides"
          },
          "portfolio_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Run a portfolio backtest (exercises member rotation / allocation). Mutually exclusive with strategy_id. Portfolio backtests do not support overrides or sweep.",
            "title": "Portfolio Id"
          },
          "slippage_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Slippage as percentage (0.05 = 0.05%). None=auto-detect (equities=0.01%; crypto/mixed=0.05%). Equity runs ALSO pay a per-symbol typical half-spread (0.5-2bp) on top of this; it is only waived when fee_pct and slippage_pct are BOTH set to 0, so setting slippage alone to 0 is not a frictionless run.",
            "title": "Slippage Pct"
          },
          "start_date": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Start date (YYYY-MM-DD). Mutually exclusive with lookback.",
            "title": "Start Date"
          },
          "storage_profile": {
            "default": "backtest_diagnostic",
            "description": "Storage profile: 'backtest_diagnostic' (default, retains indicators, condition data and bar events) or 'backtest_minimal' (retains none of them). This is RETENTION only -- it cannot persist condition data that was never captured, so explain_bar also needs collect_diagnostics=true.",
            "title": "Storage Profile",
            "type": "string"
          },
          "strategy_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Strategy identifier. Mutually exclusive with portfolio_id.",
            "title": "Strategy Id"
          },
          "sweep": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Run MANY variants in ONE call instead of one backtest per call. Variants execute in parallel and the call waits longer for them, so N variants cost one round trip rather than N. Reach for this whenever you are about to compare more than one version of a strategy.\nSweep the CONDITION that the idea turns on: {\"mode\":\"cartesian\",\"overrides\":{\"conditions\":[{\"label\":\"entry.rsi_lt_30\",\"patch\":{\"kind\":\"compare\",\"right\":[25,30,35]}}]}} \u2014 labels are `role.<definition_name>`; call get_strategy_patch_schemas(strategy_id) first to see the labels and patch shapes this strategy accepts.\nExecution knobs sweep the same way, when THEY are the question: {\"mode\":\"zip_by_index\",\"max_combinations\":20,\"initial_cash\":[50000,100000],\"fee_pct\":[0.0,0.05]}",
            "title": "Sweep"
          },
          "wait_for_completion": {
            "default": true,
            "description": "Wait for inline results. Set false to return a queued run handle promptly; poll get_backtest or rediscover with list_runs.",
            "title": "Wait For Completion",
            "type": "boolean"
          }
        },
        "title": "run_backtestArguments",
        "type": "object"
      },
      "name": "run_backtest"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": true,
        "title": "List Scan Runs",
        "toolGroup": "signal"
      },
      "description": "List a project's saved signal scan runs, newest first.\n\n        signal_scan and signal_compare calls made with a project_id save one run\n        per (condition variant x symbol) under that project; this lists those\n        runs with their stored verdict and results. To poll one batch, use\n        get_scan_batch. Returns `runs`, `count`, and `has_more`; page with\n        `offset`.\n\n        Args:\n            project_id: Project ID to list scan runs for.\n            verdict: Optional exact-match filter: long_signal, short_signal,\n                no_signal, elevated, suppressed, no_difference, needs_more_data,\n                or condition_never_fired.\n            symbol: Optional exact-match filter by symbol.\n            limit: Maximum results (default: 50).\n            offset: Number of leading runs to skip for paging (default: 0).\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "limit": {
            "default": 50,
            "description": "Max runs to return (default 50, max 100).",
            "maximum": 100,
            "minimum": 1,
            "title": "Limit",
            "type": "integer"
          },
          "offset": {
            "default": 0,
            "description": "Number of leading runs to skip for paging.",
            "maximum": 10000,
            "minimum": 0,
            "title": "Offset",
            "type": "integer"
          },
          "project_id": {
            "title": "Project Id",
            "type": "string"
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Symbol"
          },
          "verdict": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Verdict"
          }
        },
        "required": [
          "project_id"
        ],
        "title": "scan_run_listArguments",
        "type": "object"
      },
      "name": "scan_run_list"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Compare Signals",
        "toolGroup": "signal"
      },
      "description": "Compare multiple conditions on the same data.\n\n        Runs each condition independently and compares their statistical\n        significance, Sharpe ratio, and pairwise overlap.\n\n        **Multiplicity (family_q_value):** each condition's ``adjusted_p_value``\n        is Benjamini-Hochberg corrected across only the conditions in THIS\n        call. The response also attaches a per-condition ``family_q_value``\n        and a top-level ``multiplicity`` block \u2014 the same search-wide q-value\n        ``signal_scan``/``get_scan_batch`` report, computed across every\n        (condition x symbol x horizon) test in scope: every completed scan in\n        the project when ``project_id`` is set (``family_scope=\"project\"``,\n        ``family_size`` says how many, and ``family_complete`` is true because\n        the family is fully enumerated), or just this call's own\n        conditions otherwise (``family_scope=\"batch\"``). Judge significance on\n        ``family_q_value``, not the within-call ``adjusted_p_value`` \u2014 the\n        latter is honest only about this one comparison and understates true\n        multiplicity across everything else you've searched.\n\n        Args:\n            conditions: List of condition dicts to compare.\n            symbol: Asset symbol.\n            resolution: Bar resolution.\n            start_date: Start date (YYYY-MM-DD).\n            end_date: End date (YYYY-MM-DD).\n            horizon: Forward horizon in bars (default: 10).\n            labels: Optional labels for each condition.\n            filter_condition: Optional shared filter condition.\n            project_id: Optional project ID to auto-save each result as a ScanRun.\n            hypothesis: Optional hypothesis description (used when project_id is set).\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "conditions": {
            "items": {
              "additionalProperties": true,
              "type": "object"
            },
            "title": "Conditions",
            "type": "array"
          },
          "end_date": {
            "title": "End Date",
            "type": "string"
          },
          "filter_condition": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Filter Condition"
          },
          "horizon": {
            "default": 10,
            "title": "Horizon",
            "type": "integer"
          },
          "hypothesis": {
            "default": "",
            "title": "Hypothesis",
            "type": "string"
          },
          "labels": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Labels"
          },
          "project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Project Id"
          },
          "resolution": {
            "title": "Resolution",
            "type": "string"
          },
          "start_date": {
            "title": "Start Date",
            "type": "string"
          },
          "symbol": {
            "title": "Symbol",
            "type": "string"
          }
        },
        "required": [
          "conditions",
          "symbol",
          "resolution",
          "start_date",
          "end_date"
        ],
        "title": "signal_compareArguments",
        "type": "object"
      },
      "name": "signal_compare"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Run Signal Scan",
        "toolGroup": "signal"
      },
      "description": "Scan a single condition for predictive power across historical data.\n\n        Use this BEFORE building strategies to test whether a condition actually\n        predicts forward price returns. Returns statistical significance (p-value),\n        win rate, Sharpe ratio, and consistency across time periods.\n\n        Each result also includes `occurrence_dates` \u2014 up to the 10 most recent bar\n        timestamps (ISO-8601 UTC) where the condition fired, so you can answer \"when\n        did this happen\" without running a backtest. `occurrence_dates_truncated` is\n        true when `occurrences` exceeds this cap.\n\n        Results include `warnings` list and `reliable` boolean. If reliable=false,\n        the signal has data quality issues and the auto-verdict is 'needs_more_data'.\n        If the only HARD diagnostic is `no_fires` (the condition is valid and the\n        data is sufficient, but the condition never evaluated true), the verdict is\n        `condition_never_fired` \u2014 rethink the condition (e.g. relax thresholds,\n        check internal contradictions like \"trending up AND deeply oversold\")\n        rather than extending the window.\n\n        **`verdict` is a convenience summary of the statistics, not a\n        recommendation \u2014 the caller decides what to do.** A negative verdict\n        (``no_signal`` / ``no_difference``) means \"not demonstrable at this\n        sample size\", NOT \"no edge exists\" \u2014 different claims. Before\n        treating a negative as a reason to abandon a hypothesis, weigh each\n        horizon's ``minimum_detectable_effect`` (the smallest true edge this\n        scan could have detected at ~80% power) against the edge size the\n        hypothesis actually predicts: if the hypothesised edge is smaller,\n        this scan is uninformative about it and says nothing either way. Also\n        weigh ``sample_size``, ``occurrences``, ``fire_rate``, the scanned\n        ``resolution``/``start_date``/``end_date``, ``diagnostics``, and\n        ``reliable`` before acting on any verdict.\n\n        Every scan run is persisted as a ScanRun with auto-computed verdict, so\n        every call has a poll-able handle. Pass ``project_id`` to link runs to a\n        project and emit activity events.\n\n        Response envelope: ``{batch_id, count, status, scan_run_ids, results,\n        top_results, errors, message, multiplicity, significance}`` (``top_results``\n        = top ~10 rows by Sharpe, ranked over the full completed set even when\n        ``results`` is truncated). ``status`` is one of:\n          - ``\"completed\"`` \u2014 every run terminal, no failures; ``results`` inline.\n          - ``\"partial\"`` \u2014 some runs terminal, some still running OR some failed.\n            Use ``get_scan_batch(batch_id)`` to poll the rest.\n          - ``\"pending\"`` \u2014 sync-wait timed out before any run completed.\n\n        **significance** reports how the circular-shift randomization test\n        behind ``shift_p_value``/``adjusted_shift_p_value`` was run: ``method``\n        and the ``iterations`` actually used (the horizon that consumed the\n        most). Emitted ONCE at the top level \u2014 it describes the test\n        methodology, not any one result \u2014 and omitted entirely when every run\n        in this call is a legacy scan that predates the shift test.\n\n        The shift test's null is that the condition's firing TIMES are\n        unrelated to forward returns: it slides the observed fire pattern\n        circularly to random offsets, preserving fire spacing/clustering and\n        the series' own autocorrelation, so market drift sits inside the null\n        rather than being reported as edge. The baseline it's centred on\n        (``baseline_mean_return`` on each horizon) is every eligible\n        post-warmup bar in the scanned window \u2014 NOT the non-firing complement.\n        Four caveats apply to every shift-test p-value, so read them here\n        rather than per-call: (1) the shift wraps the end of the eligible\n        window round to its start, creating one artificial adjacency per\n        shifted draw; (2) only m distinct shifts exist for m eligible bars, so\n        p is bounded below by 1/(m+1) no matter how many iterations are\n        requested; (3) the scan measures the FIRING bar's close to the close H\n        bars later, while the backtester fills market orders at the next\n        bar's open by default (``latency_bars`` defaults to 1) \u2014 expect the\n        backtested edge to differ from the scanned one, especially at short\n        horizons; (4) ``inference_status`` is ``'insufficient_data'`` when too\n        few eligible bars or fires existed for the test to run at all \u2014 in\n        that case the only surviving p-value is a t-test against a zero null,\n        which reports drift as edge, so a directional verdict is never drawn\n        from it (see ``needs_more_data``).\n\n        **Multiplicity (family_q_value):** each horizon's ``adjusted_p_value``\n        is corrected only within THIS scan's own horizons (or, for\n        ``signal_compare``, within one call's conditions) \u2014 it says nothing\n        about the rest of the search an agent runs. ``family_q_value`` is a\n        second, separately-scoped quantity: the Benjamini-Hochberg q-value\n        across every (condition x symbol x horizon) test in scope. The\n        top-level ``multiplicity`` block states that scope explicitly:\n        ``method`` (\"benjamini_hochberg\"), ``dependence_assumption``\n        (\"positive_regression_dependency\" \u2014 overlapping horizons and nested\n        condition thresholds are positively correlated by construction; BH is\n        anti-conservative if that assumption fails) with a ``dependence_note``,\n        ``family_scope`` (\"project\" when ``project_id`` is set \u2014 every\n        completed scan in that project plus this batch \u2014 else \"batch\", this\n        batch only), ``family_size`` (tests counted), ``family_complete``\n        (true because the project family is fully enumerated), and\n        ``computed_at``. ``family_q_value`` is computed at READ\n        time (it rises as the project accumulates more scans) and is never\n        persisted. This is a reported number, not a verdict: it does not gate\n        anything and does not change ``verdict``/``significant``/\n        ``adjusted_p_value``.\n\n        **Sweep mode:** Put a list of values in any scalar condition param to scan\n        multiple variants. E.g. ``{\"indicator\": \"rsi\", \"period\": [10, 14, 20]}``\n        generates 3 scan runs. Use ``sweep_mode=\"zip_by_index\"`` to pair lists\n        element-wise instead of cartesian product.\n\n        **Multi-symbol:** Pass ``symbols=[\"AAPL\", \"TSLA\"]`` to scan across multiple\n        assets. Combines with sweep: 2 symbols x 3 period variants = 6 total runs.\n\n        Batch runs (sweep or multi-symbol) require ``project_id``, publish jobs to\n        Pub/Sub, and wait up to 60s plus 5s per run (capped at 240s) for terminal\n        status before responding. Inline ``results`` when fast; fall back to\n        ``get_scan_batch(batch_id)`` when timeout hits.\n\n        Conditions use the recursive kind-discriminated source language; scan accepts conditions\n        that are valid as **backtest entry conditions** \u2014 the scan loop has no\n        position state, no fills, no trade history, and no equity curve.\n\n        Position/exit conditions (live_position/entry_bar/trade_history refs,\n        fixed_targets/trailing_stop), entry-reset tracked values, and always_true\n        are not scannable and are rejected with a pointed error.\n\n        **Spread conditions are measured on the PAIR.** When the\n        condition IS a ``spread`` (at the root, naming the scanned symbol as one\n        of its two legs), forward returns are the paired return\n        ``r_a - hedge_ratio * r_b`` rather than the scanned leg's own return \u2014\n        so the number you get answers the hypothesis you asked. ``hedge_ratio``\n        defaults to 1.0, matching what the condition itself computes when none is\n        declared. The result reports ``return_basis=\"spread\"`` alongside\n        ``spread_legs`` and ``hedge_ratio_used``; every other scan reports\n        ``return_basis=\"symbol\"``. Two caveats: a spread nested inside\n        ``all_of``/``any_of`` alongside single-symbol conditions has no unambiguous\n        pair and stays on the symbol basis, and MFE/MAE (``excursion``) is\n        ``None`` for the spread basis because a spread's intrabar extreme is not\n        recoverable from the two legs' OHLC.\n        ``pair_contributions`` accounts for each detected fire at every horizon:\n        contributed pair returns, secondary-bar data gaps, invalid zero entry\n        closes, or insufficient primary bars to reach the horizon. A registered\n        secondary series with no bars remains on the pair basis and reports\n        data gaps rather than substituting single-symbol returns.\n\n        Use builder_discover(action='facets'), then list exact condition facets,\n        for available condition types.\n\n        **outcome_mode** selects what statistic each horizon tests.\n        ``\"signed_return\"`` (default) tests mean/median signed forward return \u2014\n        a DIRECTION hypothesis (\"does this condition predict up or down\n        moves\"). It is the wrong tool for a MAGNITUDE, VOLATILITY, or\n        DISPERSION claim: a symmetric effect's signed mean averages to ~0 and\n        wrongly reports ``no_signal``. ``\"realized_vol\"`` instead tests\n        whether forward-return DISPERSION (std) on firing bars differs from\n        the circular-shift test's own null \u2014 use it for claims like\n        \"volatility is elevated/suppressed around this condition\". It reports\n        ``shift_null_std_return`` (the exact circular-shift orbit centre \u2014\n        deterministic, and the actual quantity the shift test is centred on)\n        and ``volatility_ratio`` (``std_return / shift_null_std_return`` \u2014 a\n        scale-free ratio, not a difference, because volatility is\n        multiplicative: \"1.4x the tested centre\" means the same thing on a\n        calm or a volatile symbol). A separate ``baseline_std_return`` (std\n        over every eligible bar \u2014 mirrors ``baseline_mean_return``) is\n        reported too but is descriptive only, NOT the tested centre \u2014 do not\n        use it as ``volatility_ratio``'s denominator. The shift significance\n        test itself switches from studentised (mean/sd) to plain std, because\n        studentising a scale statistic would mean dividing a std by its own\n        std. Verdicts change with the mode: ``\"realized_vol\"``\n        produces ``elevated`` (ratio > 1, significant), ``suppressed`` (ratio\n        < 1, significant), or ``no_difference`` \u2014 never ``long_signal`` /\n        ``short_signal`` / ``no_signal``, because a dispersion result carries\n        no trading direction. ``inference_status``/``significant`` and the\n        BH multiplicity correction work identically in both modes.\n        ``contrast_standard_error``/``minimum_detectable_effect`` are\n        populated only for ``\"signed_return\"`` \u2014 a dispersion hypothesis has\n        no analogous location-contrast SE.\n\n        Args:\n            condition: Condition dict. Scalar params may be lists to trigger sweep.\n            resolution: Bar resolution (\"1m\", \"5m\", \"1h\", \"4h\", \"1d\").\n            start_date: Start date (YYYY-MM-DD).\n            end_date: End date (YYYY-MM-DD).\n            symbol: Single asset symbol (e.g., \"AAPL\"). Mutually exclusive with symbols.\n            symbols: List of asset symbols for multi-symbol scan. Mutually exclusive with symbol.\n            horizons: Forward bar horizons to measure (default: [1, 5, 10, 20]).\n                Bars, not wall-clock \u2014 pick values relative to `resolution` and\n                the hypothesis's expected reaction time (e.g. a same-day reaction\n                is ~7 bars on \"1h\", ~1 bar on \"1d\"). Don't leave this at the\n                default unless the default genuinely fits the hypothesis.\n            filter_condition: Optional filter condition (AND with main condition).\n            project_id: Required for batch scans. Auto-saves results as ScanRuns.\n            hypothesis: Optional hypothesis description (used when project_id is set).\n            sweep_mode: \"cartesian\" (all combinations) or \"zip_by_index\" (paired\n                by index, every swept list the same length). \"random_sample\" is a\n                real sweep mode elsewhere but is refused here: a scan carries no\n                sample_size or seed to draw against.\n            max_combinations: Maximum total scan runs allowed (default: 200).\n            min_occurrences: Minimum fires required for a result to be considered reliable (default: 0 = no filter). Applied ONLY on the inline single-symbol/single-variant path, where a result below the threshold is marked needs_more_data. Batch scans (multi-symbol or a condition sweep) ignore it \u2014 pass min_occurrences to get_scan_batch instead.\n            outcome_mode: \"signed_return\" (default) for a direction hypothesis,\n                or \"realized_vol\" for a magnitude/volatility hypothesis. See\n                above for what each mode reports and how verdicts differ.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "condition": {
            "additionalProperties": true,
            "title": "Condition",
            "type": "object"
          },
          "end_date": {
            "title": "End Date",
            "type": "string"
          },
          "filter_condition": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Filter Condition"
          },
          "horizons": {
            "anyOf": [
              {
                "items": {
                  "type": "integer"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Horizons"
          },
          "hypothesis": {
            "default": "",
            "title": "Hypothesis",
            "type": "string"
          },
          "max_combinations": {
            "default": 200,
            "title": "Max Combinations",
            "type": "integer"
          },
          "min_occurrences": {
            "default": 0,
            "title": "Min Occurrences",
            "type": "integer"
          },
          "outcome_mode": {
            "default": "signed_return",
            "title": "Outcome Mode",
            "type": "string"
          },
          "project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Project Id"
          },
          "resolution": {
            "title": "Resolution",
            "type": "string"
          },
          "start_date": {
            "title": "Start Date",
            "type": "string"
          },
          "sweep_mode": {
            "default": "cartesian",
            "description": "How condition sweep variants are generated. 'cartesian' runs every combination of the swept lists; 'zip_by_index' pairs them positionally and requires every list to be the same length (a single-valued list applies at every index).",
            "enum": [
              "cartesian",
              "zip_by_index"
            ],
            "title": "ScanSweepMode",
            "type": "string"
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Symbol"
          },
          "symbols": {
            "anyOf": [
              {
                "items": {
                  "type": "string"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Symbols"
          }
        },
        "required": [
          "condition",
          "resolution",
          "start_date",
          "end_date"
        ],
        "title": "signal_scanArguments",
        "type": "object"
      },
      "name": "signal_scan"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "toolGroup": "paper"
      },
      "description": "Use after backtest validation to deploy a strategy on live market data without real capital.\n\n        Launches a real-time paper-trading session: the strategy processes live\n        bars, simulates fills with the configured fee/slippage, and tracks PnL\n        as if trading. Prerequisites: the strategy must be compiled\n        (builder_compile) and ideally validated via run_backtest +\n        get_current_signal_state (to confirm it isn't already firing on stale\n        signals). Pairs with get_paper_trading_session to monitor the session.\n\n        Args:\n            strategy_id: Strategy to paper trade (must be compiled).\n            initial_cash: Starting capital (default 100000).\n            fee_pct: Trading fee percentage (e.g. 0.05 = 0.05%). Omit for the\n                asset-aware default (0.00% equities / 0.50% crypto); send 0 to\n                run without fees.\n            slippage_pct: Slippage percentage applied to fills. Omit for the\n                asset-aware default (0.01% equities / 0.05% crypto). Equity\n                sessions also pay a per-symbol typical half-spread (0.5-2bp) on\n                top; that is waived only when fee_pct and slippage_pct are BOTH\n                sent as 0, so sending slippage alone as 0 is not frictionless.\n            alert_mode: Per-run override \u2014 deploy this otherwise-unchanged\n                strategy as a notify-only alert session for this run only.\n            notification_channel: Alert delivery preference for alert-mode sessions.\n\n        Returns:\n            StartSessionResponse with session_id and status.\n\n        Raises:\n            StructuredToolError:\n                - UNAUTHORIZED: caller's email is not verified.\n                - STRATEGY_NOT_FOUND: strategy doesn't exist.\n                - EXECUTION_SERVICE_ERROR: backend service failure.\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "alert_mode": {
            "default": false,
            "description": "Start this session in alert-only mode: notifies on entry fires instead of placing orders. The strategy's own exits/sizing/rebalance are compiled but inactive for this session \u2014 it is not mutated. Requires ALERT_MODE_ENABLED to be set.",
            "title": "Alert Mode",
            "type": "boolean"
          },
          "fee_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Trading fee as percentage (0.1 = 0.1%). Omit to use the asset-aware default for this strategy's symbols; send 0 for a deliberately zero-fee session.",
            "title": "Fee Pct"
          },
          "initial_cash": {
            "default": 100000.0,
            "description": "Initial cash amount",
            "exclusiveMinimum": 0,
            "title": "Initial Cash",
            "type": "number"
          },
          "notification_channel": {
            "default": "all",
            "description": "Alert delivery preference for alert-mode sessions. 'all' sends to every enabled channel; 'email' sends only email; 'push' sends only registered push devices.",
            "enum": [
              "all",
              "email",
              "push"
            ],
            "title": "Notification Channel",
            "type": "string"
          },
          "slippage_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Slippage as percentage (0.05 = 0.05%). Omit to use the asset-aware default; send 0 for zero slippage.",
            "title": "Slippage Pct"
          },
          "strategy_id": {
            "description": "Strategy identifier",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "start_paper_tradingArguments",
        "type": "object"
      },
      "name": "start_paper_trading"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "toolGroup": "paper"
      },
      "description": "\n        Stop a running paper trading session.\n\n        Disables the strategy and cancels only orders durably owned by the\n        session. Existing positions are always left open; this tool has no\n        flatten or liquidation capability. If every cancellation cannot be\n        confirmed, the session returns an actionable error instead of claiming\n        a clean stop.\n\n        Args:\n            session_id: Session identifier to stop\n\n        Returns:\n            StopSessionResponse with the request disposition and current durable status\n\n        Raises:\n            StructuredToolError: With error codes:\n                - SESSION_NOT_FOUND: If session doesn't exist\n                - EXECUTION_SERVICE_ERROR: If API service fails\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "session_id": {
            "description": "Paper trading session identifier",
            "title": "Session Id",
            "type": "string"
          }
        },
        "required": [
          "session_id"
        ],
        "title": "stop_paper_tradingArguments",
        "type": "object"
      },
      "name": "stop_paper_trading"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Update Portfolio",
        "toolGroup": "portfolio"
      },
      "description": "Update a portfolio with a typed patch.\n\n        Omitted fields preserve existing values, including allocation when members\n        change. Manual weights belong only in allocation.construction.weights.\n        All members must belong to the portfolio's research project.\n        ",
      "input_schema": {
        "$defs": {
          "ADXIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "adx_di",
                "default": "adx_di",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "output": {
                "default": "adx",
                "enum": [
                  "adx",
                  "plus_di",
                  "minus_di"
                ],
                "type": "string"
              },
              "period": {
                "default": 14,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "AVWAPIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "anchor": {
                "default": "session",
                "enum": [
                  "session",
                  "session_open",
                  "week",
                  "week_open",
                  "month",
                  "month_open",
                  "month_start",
                  "ytd",
                  "custom"
                ],
                "type": "string"
              },
              "anchor_datetime": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "indicator": {
                "const": "avwap",
                "default": "avwap",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "output": {
                "default": "value",
                "enum": [
                  "value",
                  "std_dev"
                ],
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "AdIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "ad",
                "default": "ad",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "AnchorPeriod": {
            "enum": [
              "session",
              "week",
              "month"
            ],
            "type": "string"
          },
          "AroonIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "aroon",
                "default": "aroon",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "line": {
                "enum": [
                  "up",
                  "down"
                ],
                "type": "string"
              },
              "period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "period",
              "line"
            ],
            "type": "object"
          },
          "BandOutput": {
            "enum": [
              "upper",
              "middle",
              "lower"
            ],
            "type": "string"
          },
          "BollingerValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "bollinger",
                "default": "bollinger",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 2.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "enum": [
                  "upper",
                  "middle",
                  "lower",
                  "bandwidth",
                  "stddev"
                ],
                "type": "string"
              },
              "period": {
                "default": 20,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "CalendarRebalance": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "calendar",
                "default": "calendar",
                "type": "string"
              },
              "min_interval_bars": {
                "default": 0,
                "minimum": 0,
                "type": "integer"
              },
              "schedule": {
                "$ref": "#/$defs/Rebalance"
              }
            },
            "required": [
              "schedule"
            ],
            "type": "object"
          },
          "CandlestickValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "candlestick",
                "default": "candlestick",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "pattern": {
                "$ref": "#/$defs/PatternName"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "pattern"
            ],
            "type": "object"
          },
          "CollectionAuthoringConstraints": {
            "additionalProperties": false,
            "properties": {
              "asset_class_caps": {
                "anyOf": [
                  {
                    "additionalProperties": {
                      "type": "number"
                    },
                    "type": "object"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_active_sleeves": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_position_pct": {
                "anyOf": [
                  {
                    "exclusiveMinimum": 0,
                    "maximum": 1,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "min_position_pct": {
                "anyOf": [
                  {
                    "exclusiveMaximum": 1,
                    "minimum": 0,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "CollectionRiskPolicy": {
            "additionalProperties": false,
            "properties": {
              "cooldown_bars": {
                "default": 0,
                "minimum": 0,
                "type": "integer"
              },
              "day_basis": {
                "const": "utc_calendar",
                "default": "utc_calendar",
                "type": "string"
              },
              "halt_behavior": {
                "default": "soft",
                "enum": [
                  "soft",
                  "hard"
                ],
                "type": "string"
              },
              "max_daily_loss_pct": {
                "anyOf": [
                  {
                    "maximum": 50.0,
                    "minimum": 0.1,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_entries_per_day": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "max_total_entries": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "min_cash_pct": {
                "anyOf": [
                  {
                    "exclusiveMaximum": 1,
                    "minimum": 0,
                    "type": "number"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "DonchianValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "donchian",
                "default": "donchian",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "output": {
                "$ref": "#/$defs/BandOutput"
              },
              "period": {
                "default": 20,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "EqualWeight": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "equal_weight",
                "default": "equal_weight",
                "type": "string"
              }
            },
            "type": "object"
          },
          "GapIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "gap",
                "default": "gap",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "session": {
                "anyOf": [
                  {
                    "enum": [
                      "us",
                      "eu",
                      "asia"
                    ],
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "IndicatorValueRef": {
            "discriminator": {
              "mapping": {
                "ad": "#/$defs/AdIndicatorValueRef",
                "adx_di": "#/$defs/ADXIndicatorValueRef",
                "aroon": "#/$defs/AroonIndicatorValueRef",
                "atr": "#/$defs/PeriodIndicatorValueRef",
                "avwap": "#/$defs/AVWAPIndicatorValueRef",
                "bollinger": "#/$defs/BollingerValueRef",
                "candlestick": "#/$defs/CandlestickValueRef",
                "cci": "#/$defs/PeriodIndicatorValueRef",
                "cmf": "#/$defs/PeriodIndicatorValueRef",
                "donchian": "#/$defs/DonchianValueRef",
                "ema": "#/$defs/MovingAverageValueRef",
                "gap": "#/$defs/GapIndicatorValueRef",
                "keltner": "#/$defs/KeltnerValueRef",
                "macd": "#/$defs/MacdIndicatorValueRef",
                "macd_histogram": "#/$defs/MacdIndicatorValueRef",
                "macd_signal": "#/$defs/MacdIndicatorValueRef",
                "median": "#/$defs/PeriodIndicatorValueRef",
                "mfi": "#/$defs/PeriodIndicatorValueRef",
                "obv": "#/$defs/OBVIndicatorValueRef",
                "pivot_p": "#/$defs/PivotIndicatorValueRef",
                "pivot_r1": "#/$defs/PivotIndicatorValueRef",
                "pivot_r2": "#/$defs/PivotIndicatorValueRef",
                "pivot_r3": "#/$defs/PivotIndicatorValueRef",
                "pivot_s1": "#/$defs/PivotIndicatorValueRef",
                "pivot_s2": "#/$defs/PivotIndicatorValueRef",
                "pivot_s3": "#/$defs/PivotIndicatorValueRef",
                "roc": "#/$defs/PeriodIndicatorValueRef",
                "rsi": "#/$defs/PeriodIndicatorValueRef",
                "sma": "#/$defs/MovingAverageValueRef",
                "srsi_d": "#/$defs/SrsiIndicatorValueRef",
                "srsi_k": "#/$defs/SrsiIndicatorValueRef",
                "std": "#/$defs/PeriodIndicatorValueRef",
                "stochastic_d": "#/$defs/StochasticIndicatorValueRef",
                "stochastic_k": "#/$defs/StochasticIndicatorValueRef",
                "supertrend": "#/$defs/SupertrendIndicatorValueRef",
                "var": "#/$defs/PeriodIndicatorValueRef",
                "volume_sma": "#/$defs/PeriodIndicatorValueRef",
                "vwap": "#/$defs/VWAPIndicatorValueRef",
                "vwap_bands": "#/$defs/VWAPBandsValueRef",
                "vwma": "#/$defs/MovingAverageValueRef",
                "wma": "#/$defs/MovingAverageValueRef"
              },
              "propertyName": "indicator"
            },
            "oneOf": [
              {
                "$ref": "#/$defs/MovingAverageValueRef"
              },
              {
                "$ref": "#/$defs/PeriodIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/MacdIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/StochasticIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/SrsiIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/AdIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/OBVIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/AroonIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/SupertrendIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/BollingerValueRef"
              },
              {
                "$ref": "#/$defs/DonchianValueRef"
              },
              {
                "$ref": "#/$defs/KeltnerValueRef"
              },
              {
                "$ref": "#/$defs/VWAPBandsValueRef"
              },
              {
                "$ref": "#/$defs/VWAPIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/AVWAPIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/ADXIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/PivotIndicatorValueRef"
              },
              {
                "$ref": "#/$defs/CandlestickValueRef"
              },
              {
                "$ref": "#/$defs/GapIndicatorValueRef"
              }
            ],
            "required": [
              "indicator"
            ]
          },
          "KeltnerValueRef": {
            "additionalProperties": false,
            "properties": {
              "atr_period": {
                "anyOf": [
                  {
                    "maximum": 500,
                    "minimum": 2,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "indicator": {
                "const": "keltner",
                "default": "keltner",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 2.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "$ref": "#/$defs/BandOutput"
              },
              "period": {
                "default": 20,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "MacdIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "fast_period": {
                "maximum": 500,
                "minimum": 1,
                "type": "integer"
              },
              "indicator": {
                "enum": [
                  "macd",
                  "macd_signal",
                  "macd_histogram"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "signal_period": {
                "maximum": 500,
                "minimum": 1,
                "type": "integer"
              },
              "slow_period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "fast_period",
              "slow_period",
              "signal_period"
            ],
            "type": "object"
          },
          "ManualWeights": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "manual",
                "default": "manual",
                "type": "string"
              },
              "weights": {
                "additionalProperties": {
                  "type": "number"
                },
                "minProperties": 1,
                "type": "object"
              }
            },
            "required": [
              "weights"
            ],
            "type": "object"
          },
          "Member": {
            "additionalProperties": false,
            "properties": {
              "revision_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "strategy_id": {
                "type": "string"
              }
            },
            "required": [
              "strategy_id"
            ],
            "type": "object"
          },
          "MovingAverageValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "enum": [
                  "ema",
                  "sma",
                  "wma",
                  "vwma"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "offset": {
                "default": 0,
                "maximum": 500,
                "minimum": 0,
                "type": "integer"
              },
              "period": {
                "maximum": 800,
                "minimum": 1,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "period"
            ],
            "type": "object"
          },
          "NoRebalance": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "none",
                "default": "none",
                "type": "string"
              },
              "min_interval_bars": {
                "default": 0,
                "minimum": 0,
                "type": "integer"
              }
            },
            "type": "object"
          },
          "OBVIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "obv",
                "default": "obv",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "PatternName": {
            "enum": [
              "hammer",
              "inverted_hammer",
              "shooting_star",
              "doji",
              "dragonfly_doji",
              "gravestone_doji",
              "spinning_top",
              "marubozu",
              "bullish_engulfing",
              "bearish_engulfing",
              "harami",
              "harami_cross",
              "inside_bar",
              "morning_star",
              "evening_star",
              "piercing_line",
              "dark_cloud_cover",
              "three_white_soldiers",
              "three_black_crows"
            ],
            "type": "string"
          },
          "PeriodIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "enum": [
                  "rsi",
                  "atr",
                  "roc",
                  "cci",
                  "volume_sma",
                  "mfi",
                  "cmf",
                  "std",
                  "var",
                  "median"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "offset": {
                "default": 0,
                "maximum": 500,
                "minimum": 0,
                "type": "integer"
              },
              "period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "period"
            ],
            "type": "object"
          },
          "PivotIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "enum": [
                  "pivot_p",
                  "pivot_s1",
                  "pivot_s2",
                  "pivot_s3",
                  "pivot_r1",
                  "pivot_r2",
                  "pivot_r3"
                ],
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator"
            ],
            "type": "object"
          },
          "PortfolioAllocationAuthoring": {
            "additionalProperties": false,
            "properties": {
              "capital_model": {
                "default": "partitioned",
                "enum": [
                  "partitioned",
                  "shared_pool"
                ],
                "type": "string"
              },
              "collection_risk": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CollectionRiskPolicy"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "constraints": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/CollectionAuthoringConstraints"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "construction": {
                "anyOf": [
                  {
                    "discriminator": {
                      "mapping": {
                        "equal_weight": "#/$defs/EqualWeight",
                        "manual": "#/$defs/ManualWeights",
                        "member_signal_rotation": "#/$defs/PortfolioMemberSignalConstruction",
                        "rank_based": "#/$defs/PortfolioRankConstruction",
                        "trailing_return": "#/$defs/TrailingReturnRotation"
                      },
                      "propertyName": "kind"
                    },
                    "oneOf": [
                      {
                        "$ref": "#/$defs/EqualWeight"
                      },
                      {
                        "$ref": "#/$defs/ManualWeights"
                      },
                      {
                        "$ref": "#/$defs/PortfolioRankConstruction"
                      },
                      {
                        "$ref": "#/$defs/TrailingReturnRotation"
                      },
                      {
                        "$ref": "#/$defs/PortfolioMemberSignalConstruction"
                      }
                    ],
                    "required": [
                      "kind"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "rebalance": {
                "anyOf": [
                  {
                    "discriminator": {
                      "mapping": {
                        "calendar": "#/$defs/CalendarRebalance",
                        "none": "#/$defs/NoRebalance"
                      },
                      "propertyName": "kind"
                    },
                    "oneOf": [
                      {
                        "$ref": "#/$defs/NoRebalance"
                      },
                      {
                        "$ref": "#/$defs/CalendarRebalance"
                      }
                    ],
                    "required": [
                      "kind"
                    ]
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "PortfolioMemberSignalConstruction": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "member_signal_rotation",
                "type": "string"
              },
              "score_signal": {
                "minLength": 1,
                "type": "string"
              },
              "top_n": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "kind",
              "score_signal",
              "top_n"
            ],
            "type": "object"
          },
          "PortfolioRankConstruction": {
            "additionalProperties": false,
            "properties": {
              "exit_top_n": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "kind": {
                "const": "rank_based",
                "type": "string"
              },
              "score_signal": {
                "minLength": 1,
                "type": "string"
              },
              "top_n": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "kind",
              "score_signal",
              "top_n"
            ],
            "type": "object"
          },
          "PortfolioUpdateAuthoring": {
            "additionalProperties": false,
            "properties": {
              "allocation": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/PortfolioAllocationAuthoring"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "members": {
                "anyOf": [
                  {
                    "items": {
                      "$ref": "#/$defs/Member"
                    },
                    "minItems": 1,
                    "type": "array"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "name": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "project_id": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "shared_signals": {
                "anyOf": [
                  {
                    "items": {
                      "$ref": "#/$defs/SharedSignal"
                    },
                    "type": "array"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "PriceField": {
            "enum": [
              "open",
              "high",
              "low",
              "close"
            ],
            "type": "string"
          },
          "PriceValueRef": {
            "additionalProperties": false,
            "properties": {
              "field": {
                "$ref": "#/$defs/PriceField",
                "default": "close"
              },
              "kind": {
                "const": "price",
                "default": "price",
                "type": "string"
              },
              "offset": {
                "default": 0,
                "maximum": 500,
                "minimum": 0,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "Rebalance": {
            "enum": [
              "daily",
              "weekly",
              "monthly"
            ],
            "type": "string"
          },
          "SharedSignal": {
            "additionalProperties": false,
            "properties": {
              "name": {
                "minLength": 1,
                "type": "string"
              },
              "source": {
                "discriminator": {
                  "mapping": {
                    "indicator": "#/$defs/IndicatorValueRef",
                    "price": "#/$defs/PriceValueRef",
                    "volume": "#/$defs/VolumeValueRef"
                  },
                  "propertyName": "kind"
                },
                "oneOf": [
                  {
                    "$ref": "#/$defs/IndicatorValueRef"
                  },
                  {
                    "$ref": "#/$defs/PriceValueRef"
                  },
                  {
                    "$ref": "#/$defs/VolumeValueRef"
                  }
                ],
                "required": [
                  "kind"
                ]
              }
            },
            "required": [
              "name",
              "source"
            ],
            "type": "object"
          },
          "SrsiIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "d_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "indicator": {
                "enum": [
                  "srsi_k",
                  "srsi_d"
                ],
                "type": "string"
              },
              "k_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "period": {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator",
              "period"
            ],
            "type": "object"
          },
          "StochasticIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "d_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "indicator": {
                "enum": [
                  "stochastic_k",
                  "stochastic_d"
                ],
                "type": "string"
              },
              "k_period": {
                "default": 3,
                "maximum": 100,
                "minimum": 1,
                "type": "integer"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "period": {
                "default": 14,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "indicator"
            ],
            "type": "object"
          },
          "SupertrendIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "indicator": {
                "const": "supertrend",
                "default": "supertrend",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 3.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "default": "value",
                "enum": [
                  "value",
                  "direction"
                ],
                "type": "string"
              },
              "period": {
                "default": 10,
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "Timeframe": {
            "enum": [
              "1m",
              "5m",
              "15m",
              "30m",
              "1h",
              "4h",
              "1d"
            ],
            "type": "string"
          },
          "TrailingReturnRotation": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "trailing_return",
                "default": "trailing_return",
                "type": "string"
              },
              "lookback_bars": {
                "exclusiveMinimum": 0,
                "type": "integer"
              },
              "metric": {
                "const": "return",
                "default": "return",
                "type": "string"
              },
              "top_n": {
                "minimum": 1,
                "type": "integer"
              }
            },
            "required": [
              "top_n",
              "lookback_bars"
            ],
            "type": "object"
          },
          "VWAPBandOutput": {
            "enum": [
              "upper",
              "middle",
              "lower",
              "std_dev"
            ],
            "type": "string"
          },
          "VWAPBandsValueRef": {
            "additionalProperties": false,
            "properties": {
              "anchor": {
                "$ref": "#/$defs/AnchorPeriod",
                "default": "session"
              },
              "indicator": {
                "const": "vwap_bands",
                "default": "vwap_bands",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "multiplier": {
                "default": 2.0,
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              "output": {
                "$ref": "#/$defs/VWAPBandOutput"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "required": [
              "output"
            ],
            "type": "object"
          },
          "VWAPIndicatorValueRef": {
            "additionalProperties": false,
            "properties": {
              "anchor": {
                "$ref": "#/$defs/AnchorPeriod",
                "default": "session"
              },
              "indicator": {
                "const": "vwap",
                "default": "vwap",
                "type": "string"
              },
              "kind": {
                "const": "indicator",
                "default": "indicator",
                "type": "string"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          },
          "VolumeValueRef": {
            "additionalProperties": false,
            "properties": {
              "kind": {
                "const": "volume",
                "default": "volume",
                "type": "string"
              },
              "offset": {
                "default": 0,
                "maximum": 500,
                "minimum": 0,
                "type": "integer"
              },
              "resolution": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/Timeframe"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "symbol": {
                "anyOf": [
                  {
                    "type": "string"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              }
            },
            "type": "object"
          }
        },
        "additionalProperties": false,
        "properties": {
          "patch": {
            "$ref": "#/$defs/PortfolioUpdateAuthoring",
            "description": "Fields to replace. Omit fields to preserve their values; null clears allocation; [] clears shared_signals."
          },
          "portfolio_id": {
            "description": "Portfolio identifier",
            "title": "Portfolio Id",
            "type": "string"
          }
        },
        "required": [
          "portfolio_id",
          "patch"
        ],
        "title": "update_portfolioArguments",
        "type": "object"
      },
      "name": "update_portfolio"
    },
    {
      "annotations": {
        "destructiveHint": true,
        "idempotentHint": true,
        "openWorldHint": false,
        "readOnlyHint": false,
        "title": "Validate On Holdout",
        "toolGroup": "backtest"
      },
      "description": "Run the current strategy on its project's reserved holdout window (spend-once).\n\n        The holdout is consumed by the first strategy in the project that calls\n        this. Calling again from that strategy returns the recorded result; any\n        other strategy in the project is refused. release_holdout discards the\n        window permanently; only a new project reserves a new one.\n\n        Training metrics come from the strategy's latest completed development\n        backtest (at least one is required). Returns raw in-sample and\n        out-of-sample metrics, the per-strategy validation_count, degradation_pct,\n        and degradation_bucket: \"improved\" (holdout outperformed training,\n        negative degradation_pct), \"low\", \"medium\", \"high\",\n        \"insufficient_holdout_data\" (too few holdout trades to judge),\n        \"both_unprofitable\", or \"undefined\" (training Sharpe and return both\n        zero, so degradation_pct is null). The caller decides what to do with\n        the numbers.\n\n        The window ends at the project's creation time and is fixed then, so\n        each project has its own window.\n\n        Args:\n            strategy_id: Strategy to validate on holdout data\n\n        Returns:\n            HoldoutComparison dict with training vs holdout metrics, degradation_pct,\n            degradation_bucket, holdout_trade_count, validation_count, summary.\n            Drawdowns are reported for both the strategy (training_max_drawdown,\n            holdout_max_drawdown) and its benchmark (training_buy_and_hold_max_drawdown,\n            holdout_buy_and_hold_max_drawdown) \u2014 do not read one for the other.\n\n        Raises:\n            StructuredToolError: If strategy not found, no project, no holdout\n                window, or no completed development backtests\n        ",
      "input_schema": {
        "additionalProperties": false,
        "properties": {
          "strategy_id": {
            "description": "Strategy identifier",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "validate_on_holdoutArguments",
        "type": "object"
      },
      "name": "validate_on_holdout"
    },
    {
      "annotations": {
        "destructiveHint": false,
        "idempotentHint": false,
        "openWorldHint": false,
        "readOnlyHint": false,
        "requires_capability": "walk_forward",
        "title": "Run Walk-Forward Analysis",
        "toolGroup": "backtest"
      },
      "description": "\n        Run a walk-forward analysis to validate strategy robustness out-of-sample.\n\n        Once results are in, save the verdict and WFE with project_write_scratchpad\n        so the finding persists across sessions.\n\n        Walk-forward testing divides a historical period into N sequential windows,\n        running backtests on each to measure consistency across regimes.\n\n        Folds never enter the project's reserved holdout: if `total_lookback`\n        would reach into it, the whole walk-forward window is moved earlier \u2014\n        keeping its full requested length, so the fold count and fold length are\n        unchanged \u2014 and `warnings` carries a `holdout_window_shifted` notice. A\n        `total_lookback` that lands entirely inside the holdout is rejected\n        rather than quietly shortened.\n\n        Portfolios: pass portfolio_id instead of strategy_id. Portfolio walk-forward\n        is Level 1 only \u2014 each window runs one coupled portfolio backtest across all\n        members (with a per-member breakdown). It does not support sweep / overrides /\n        oos_pct / select_by (portfolios have no parameter sweep).\n\n        Two analysis levels:\n\n        Level 1 (consistency check): Tests the same strategy across N time windows.\n          No sweep required \u2014 uses the strategy as-is on each window.\n          Look at Sharpe consistency \u2014 high mean + low std = robust across regimes.\n          pct_profitable_windows > 0.75 is strong, < 0.5 is concerning.\n\n        Level 2 (rolling re-optimization): Re-optimizes on each IS window, tests on OOS.\n          Requires a sweep config to define the parameter space.\n          Walk-Forward Efficiency (WFE) = OOS Sharpe / IS Sharpe.\n            > 0.5 is strong, 0.3-0.5 is acceptable, < 0.3 suggests overfitting.\n          Parameter stability: consistent winning params across windows\n            suggests real signal; params that change every window suggest overfitting.\n\n        Workflow:\n        1. walk_forward(strategy_id, total_lookback=\"1yr\", windows=5) \u2192 returns walk_forward_id\n        2. get_walk_forward(walk_forward_id) \u2192 poll until status=\"completed\"\n        3. Interpret aggregate metrics (wfe_mean, pct_profitable_windows, oos_sharpe_mean)\n\n        Level 1 (no sweep):\n          - Divides total_lookback into N equal windows\n          - Runs one backtest per window with the unchanged strategy\n          - Reports oos_sharpe_mean, oos_sharpe_std, pct_profitable_windows.\n            Despite the oos_ prefix these are WHOLE-WINDOW metrics: Level 1 does\n            no in-sample/out-of-sample split, so they measure consistency across\n            regimes. Never present them as out-of-sample evidence.\n\n        Level 2 (with sweep):\n          - Each window is split into IS (in-sample) and OOS (out-of-sample)\n          - IS: runs the parameter sweep, selects params by the configured select_by metric\n          - OOS: runs the selected params on the OOS period\n          - Reports wfe_mean, parameter_stability, pct_profitable_windows\n\n        Args:\n            strategy_id: Strategy to analyze.\n            total_lookback: Historical period to divide (e.g., \"1yr\", \"2yr\", \"6mo\").\n            windows: Number of time windows.\n            mode: 'rolling' or 'anchored' window layout (default: rolling).\n            oos_pct: OOS fraction per window, Level 2 only.\n            sweep: Parameter sweep config for Level 2 re-optimization (optional).\n            select_by: Parameter selection metric for Level 2.\n            initial_cash: Starting capital per window (default: 100000).\n            fee_pct: Fee percentage. Omitted values use 0.00% for equities and\n                0.50% for crypto or mixed portfolios.\n            slippage_pct: Slippage percentage. Omitted values use 0.01% for\n                equities and 0.05% for crypto or mixed portfolios.\n\n        Returns:\n            RunWalkForwardResponse with walk_forward_id, status, total_backtests, level.\n\n        Raises:\n            StructuredToolError: With error codes:\n                - UNAUTHORIZED: If caller's tier doesn't include `walk_forward` (Hobby+).\n                - STRATEGY_NOT_FOUND: If strategy doesn't exist\n                - VALIDATION_ERROR: If parameters are invalid\n                - EXECUTION_SERVICE_ERROR: If API service fails\n        ",
      "input_schema": {
        "$defs": {
          "SweepConditionOverride": {
            "additionalProperties": false,
            "description": "One swept condition: a label, and a patch whose list-valued fields are axes.",
            "properties": {
              "label": {
                "title": "Label",
                "type": "string"
              },
              "patch": {
                "additionalProperties": true,
                "title": "Patch",
                "type": "object"
              }
            },
            "required": [
              "label",
              "patch"
            ],
            "title": "SweepConditionOverride",
            "type": "object"
          },
          "SweepConditionOverrides": {
            "additionalProperties": false,
            "description": "The only override shape a walk-forward sweep applies: condition patches.",
            "properties": {
              "conditions": {
                "anyOf": [
                  {
                    "items": {
                      "$ref": "#/$defs/SweepConditionOverride"
                    },
                    "type": "array"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Conditions"
              }
            },
            "title": "SweepConditionOverrides",
            "type": "object"
          },
          "SweepSpec": {
            "additionalProperties": false,
            "description": "A parameter sweep: which fields vary, over which values, combined how.",
            "properties": {
              "mode": {
                "description": "How sweep combinations are generated. 'cartesian' runs every combination of the axes; 'zip_by_index' pairs them positionally and requires every axis to have the same length; 'random_sample' draws sample_size distinct combinations from the full grid, deterministically under seed.",
                "enum": [
                  "cartesian",
                  "random_sample",
                  "zip_by_index"
                ],
                "title": "SweepMode",
                "type": "string"
              },
              "overrides": {
                "anyOf": [
                  {
                    "$ref": "#/$defs/SweepConditionOverrides"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null
              },
              "sample_size": {
                "anyOf": [
                  {
                    "minimum": 1,
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Sample Size"
              },
              "seed": {
                "anyOf": [
                  {
                    "type": "integer"
                  },
                  {
                    "type": "null"
                  }
                ],
                "default": null,
                "title": "Seed"
              }
            },
            "title": "SweepSpec",
            "type": "object"
          }
        },
        "additionalProperties": false,
        "properties": {
          "benchmark_symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional secondary market-index benchmark (e.g. 'SPY'). When set, each window's child backtest reports market_benchmark_* fields alongside the per-symbol buy-and-hold benchmark.",
            "title": "Benchmark Symbol"
          },
          "fee_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Trading fee as percentage (0.1 = 0.1%). None=auto-detect (equities=0.00%; crypto/mixed=0.50%). Set 0 for zero fees.",
            "title": "Fee Pct"
          },
          "initial_cash": {
            "default": 100000.0,
            "description": "Initial cash for each backtest window",
            "exclusiveMinimum": 0,
            "title": "Initial Cash",
            "type": "number"
          },
          "mode": {
            "default": "rolling",
            "description": "Window layout: 'rolling' (each window shifts forward by one window length) or 'anchored' (IS start is fixed, OOS end advances). Default: rolling",
            "title": "Mode",
            "type": "string"
          },
          "oos_pct": {
            "default": 0.25,
            "description": "Fraction of each window reserved for out-of-sample testing (Level 2 only). 0.25 = 25% OOS, 75% IS.",
            "title": "Oos Pct",
            "type": "number"
          },
          "overrides": {
            "anyOf": [
              {
                "additionalProperties": true,
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional strategy-wide per-run override patch, applied to EVERY child window backtest (same shape as run_backtest overrides \u2014 distinct from sweep's per-variant 'overrides'). Example: {\"sizing\":{\"mode\":\"fixed_usd\",\"fixed_usd\":5000},\"execution\":{\"order_type\":\"market\"}}",
            "title": "Overrides"
          },
          "portfolio_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Portfolio identifier to analyze. Mutually exclusive with strategy_id. Portfolio walk-forward is Level 1 only (no sweep / overrides / oos_pct / select_by).",
            "title": "Portfolio Id"
          },
          "select_by": {
            "default": "sharpe_ratio",
            "description": "Metric used to select the parameter set in each IS window (Level 2). Options: 'sharpe_ratio', 'sortino_ratio', 'total_pnl_pct', 'win_rate'.",
            "title": "Select By",
            "type": "string"
          },
          "slippage_pct": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Slippage as percentage (0.05 = 0.05%). None=auto-detect (equities=0.01%; crypto/mixed=0.05%). Equity runs ALSO pay a per-symbol typical half-spread (0.5-2bp) on top of this; it is only waived when fee_pct and slippage_pct are BOTH set to 0, so setting slippage alone to 0 is not a frictionless run.",
            "title": "Slippage Pct"
          },
          "strategy_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Strategy identifier to analyze. Mutually exclusive with portfolio_id.",
            "title": "Strategy Id"
          },
          "sweep": {
            "anyOf": [
              {
                "$ref": "#/$defs/SweepSpec"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Parameter sweep config for Level 2 re-optimization. Only list-valued condition patch fields are swept axes; top-level initial_cash/fee_pct/slippage_pct are NOT swept here and are rejected. mode='random_sample' needs sample_size (and takes an optional seed); 'zip_by_index' needs every axis to be the same length. Example: {\"mode\": \"cartesian\", \"overrides\": {\"conditions\": [{\"label\": \"entry.rsi\", \"patch\": {\"kind\": \"compare\", \"right\": [25, 30, 35]}}]}}"
          },
          "total_lookback": {
            "default": "2yr",
            "description": "Total historical window for the analysis: '1yr', '2yr', '6mo', etc. This is divided into N windows. Longer lookbacks give more windows but require more data. Default: 2yr",
            "title": "Total Lookback",
            "type": "string"
          },
          "windows": {
            "default": 6,
            "description": "Number of time windows to divide the lookback into. Default: 6",
            "title": "Windows",
            "type": "integer"
          }
        },
        "title": "walk_forwardArguments",
        "type": "object"
      },
      "name": "walk_forward"
    }
  ],
  "quickstart_steps": [
    {
      "arguments": {
        "name": "RSI recovery research"
      },
      "description": "Create a project, or reuse an owned project from project_list. Use its returned id as project_id.",
      "order": 1,
      "tool": "project_create"
    },
    {
      "arguments": {
        "name": "SPY RSI recovery",
        "project_id": "<project_id>",
        "symbols": [
          "SPY"
        ],
        "timeframe": "1h"
      },
      "description": "Create a draft. Keep the returned strategy_id for subsequent calls.",
      "order": 2,
      "tool": "create_strategy"
    },
    {
      "arguments": {
        "patch": {
          "sizing": {
            "fixed_usd": 5000,
            "mode": "fixed_usd"
          }
        },
        "strategy_id": "<strategy_id>"
      },
      "description": "Set the position size explicitly.",
      "order": 3,
      "tool": "builder_set_strategy_config"
    },
    {
      "arguments": {
        "condition": {
          "kind": "sequence",
          "steps": [
            {
              "condition": {
                "direction": "below",
                "kind": "cross",
                "left": {
                  "indicator": "rsi",
                  "kind": "indicator",
                  "period": 14
                },
                "right": 35
              }
            },
            {
              "condition": {
                "direction": "above",
                "kind": "cross",
                "left": {
                  "indicator": "rsi",
                  "kind": "indicator",
                  "period": 14
                },
                "right": 45
              },
              "within_bars": 6
            }
          ]
        },
        "direction": "long",
        "name": "rsi_recovery",
        "role": "entry",
        "strategy_id": "<strategy_id>"
      },
      "description": "Attach the complete sequence as one entry rule; no child saves or composition calls.",
      "order": 4,
      "tool": "add_rule"
    },
    {
      "arguments": {
        "condition": {
          "kind": "compare",
          "left": {
            "field": "close",
            "kind": "price",
            "resolution": "4h"
          },
          "op": ">",
          "right": {
            "indicator": "ema",
            "kind": "indicator",
            "period": 100,
            "resolution": "4h"
          }
        },
        "name": "trend",
        "role": "gate",
        "strategy_id": "<strategy_id>"
      },
      "description": "Permit entries only while the 4h trend predicate is true.",
      "order": 5,
      "tool": "add_rule"
    },
    {
      "arguments": {
        "condition": {
          "conditions": [
            {
              "kind": "compare",
              "left": {
                "indicator": "rsi",
                "kind": "indicator",
                "period": 14
              },
              "op": ">",
              "right": 65
            },
            {
              "kind": "compare",
              "left": {
                "field": "bars_in_position",
                "kind": "live_position"
              },
              "op": ">=",
              "right": 12
            }
          ],
          "kind": "any_of"
        },
        "direction": "long",
        "name": "timeout_or_rsi",
        "role": "exit",
        "strategy_id": "<strategy_id>"
      },
      "description": "Exit when RSI exceeds 65 or the open position reaches 12 bars.",
      "order": 6,
      "tool": "add_rule"
    },
    {
      "arguments": {
        "strategy_id": "<strategy_id>"
      },
      "description": "Review source, active rules, unattached_definitions and entry_behavior.",
      "order": 7,
      "tool": "builder_get_strategy"
    },
    {
      "arguments": {
        "strategy_id": "<strategy_id>"
      },
      "description": "Check compilation/admission and inspect warnings before running research.",
      "order": 8,
      "tool": "builder_compile"
    },
    {
      "arguments": {
        "lookback": "2y",
        "strategy_id": "<strategy_id>"
      },
      "description": "Request two years; inspect actual coverage, admitted dates and warnings in the result.",
      "order": 9,
      "tool": "run_backtest"
    },
    {
      "arguments": {
        "backtest_id": "<backtest_id>",
        "detail": "summary"
      },
      "description": "If the run is queued, follow its returned instructions until terminal; inspect results and warnings.",
      "order": 10,
      "tool": "get_backtest"
    }
  ],
  "registry_etag": "sha256:1d66b533fd7a9fce0e8f071c70e47bd6d5c63ca28cb52f20b131d096b5f9f670",
  "schema_document": {
    "$defs": {
      "ADXIndicatorValueRef": {
        "additionalProperties": false,
        "description": "ADX with access to +DI / -DI directional indicators.\n\nThe ADX indicator computes three series internally: the composite ADX\n(trend strength) plus the Plus Directional Indicator (+DI) and Minus\nDirectional Indicator (-DI). Use ``output`` to select which series:\n\n  - ``adx`` (default): composite Wilder ADX, 0-100 trend strength.\n  - ``plus_di``: +DI, upward directional movement strength.\n  - ``minus_di``: -DI, downward directional movement strength.\n\nAll outputs first exist after 2N bars seen (zero-based index 2N-1).\nPublic DI access intentionally waits for composite ADX readiness; TA-Lib\nPLUS_DI/MINUS_DI instead start at index N (DEC-018).\n\n``plus_di > minus_di`` indicates an up-trending directional bias;\n``plus_di < minus_di`` indicates a down-trending bias.",
        "properties": {
          "indicator": {
            "const": "adx_di",
            "default": "adx_di",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "output": {
            "default": "adx",
            "enum": [
              "adx",
              "plus_di",
              "minus_di"
            ],
            "title": "Output",
            "type": "string"
          },
          "period": {
            "default": 14,
            "maximum": 500,
            "minimum": 2,
            "title": "Period",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "ADXIndicatorValueRef",
        "type": "object"
      },
      "AVWAPIndicatorValueRef": {
        "additionalProperties": false,
        "description": "Anchored VWAP \u2014 VWAP anchored to a specific session/week/month/custom point.\n\nMirrors the IR ``AnchoredVWAP`` model: ``anchor`` selects the canonical\nanchor boundary; ``anchor_datetime`` (ISO 8601 string) supplies the custom\nanchor instant when ``anchor=\"custom\"``.\n\nUse ``vwap`` for the simple session-anchored case; use ``avwap`` when you\nneed week/month/ytd/custom anchors or the ``std_dev`` band output.",
        "properties": {
          "anchor": {
            "default": "session",
            "enum": [
              "session",
              "session_open",
              "week",
              "week_open",
              "month",
              "month_open",
              "month_start",
              "ytd",
              "custom"
            ],
            "title": "Anchor",
            "type": "string"
          },
          "anchor_datetime": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Anchor Datetime"
          },
          "indicator": {
            "const": "avwap",
            "default": "avwap",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "output": {
            "default": "value",
            "enum": [
              "value",
              "std_dev"
            ],
            "title": "Output",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "AVWAPIndicatorValueRef",
        "type": "object"
      },
      "AdIndicatorValueRef": {
        "additionalProperties": false,
        "description": "Accumulation/Distribution line \u2014 running sum of close-location-value times volume.\n\nCumulative and unbounded from the first bar of loaded history (warmup bars\nincluded), so its absolute level is an artifact of where the data starts:\ncompare it against its own moving average or slope, never against a fixed\nnumber. A bar whose high equals its low contributes zero rather than\ndividing by zero.",
        "properties": {
          "indicator": {
            "const": "ad",
            "default": "ad",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "AdIndicatorValueRef",
        "type": "object"
      },
      "AllOfCondition": {
        "additionalProperties": false,
        "description": "Logical AND -- all child conditions must be true.",
        "properties": {
          "child_names": {
            "anyOf": [
              {
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Child Names"
          },
          "conditions": {
            "items": {
              "$ref": "#/$defs/Condition"
            },
            "minItems": 1,
            "title": "Conditions",
            "type": "array"
          },
          "kind": {
            "const": "all_of",
            "default": "all_of",
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "conditions"
        ],
        "title": "AllOfCondition",
        "type": "object"
      },
      "AlwaysTrueCondition": {
        "additionalProperties": false,
        "description": "Always true -- fires on every bar. Use as a no-op placeholder or unconditional trigger.",
        "properties": {
          "kind": {
            "const": "always_true",
            "default": "always_true",
            "title": "Kind",
            "type": "string"
          }
        },
        "title": "AlwaysTrueCondition",
        "type": "object"
      },
      "AnchorDefinition": {
        "additionalProperties": false,
        "description": "Persistent named candle anchor available to parse_value_ref(kind='anchor').",
        "properties": {
          "id": {
            "description": "Unique anchor identifier",
            "maxLength": 64,
            "minLength": 1,
            "pattern": "^[A-Za-z][A-Za-z0-9_-]*$",
            "title": "Id",
            "type": "string"
          },
          "source": {
            "discriminator": {
              "mapping": {
                "bar_index": "#/$defs/BarIndexAnchorSource",
                "condition_trigger": "#/$defs/ConditionTriggerAnchorSource",
                "timestamp": "#/$defs/TimestampAnchorSource"
              },
              "propertyName": "kind"
            },
            "oneOf": [
              {
                "$ref": "#/$defs/TimestampAnchorSource"
              },
              {
                "$ref": "#/$defs/BarIndexAnchorSource"
              },
              {
                "$ref": "#/$defs/ConditionTriggerAnchorSource"
              }
            ],
            "required": [
              "kind"
            ],
            "title": "Source"
          }
        },
        "required": [
          "id",
          "source"
        ],
        "title": "AnchorDefinition",
        "type": "object"
      },
      "AnchorPeriod": {
        "enum": [
          "session",
          "week",
          "month"
        ],
        "type": "string"
      },
      "AnchorPriceSpec": {
        "additionalProperties": false,
        "description": "Use a persisted anchor field as the execution price.",
        "properties": {
          "anchor_field": {
            "description": "Anchor field to use as the order price",
            "enum": [
              "open",
              "high",
              "low",
              "close",
              "mid",
              "range"
            ],
            "title": "Anchor Field",
            "type": "string"
          },
          "anchor_id": {
            "description": "Anchor identifier to read from",
            "minLength": 1,
            "title": "Anchor Id",
            "type": "string"
          },
          "kind": {
            "const": "anchor",
            "default": "anchor",
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "anchor_id",
          "anchor_field"
        ],
        "title": "AnchorPriceSpec",
        "type": "object"
      },
      "AnchorValueRef": {
        "additionalProperties": false,
        "description": "A field of a named anchor \u2014 a single bar captured earlier and then held.\n\nThe anchor is declared in the strategy's ``anchors`` (captured by\ntimestamp, bar index, or the first false-to-true flip of a condition);\nreferencing an ``anchor_id`` that is not declared fails at compile time.\nUntil the anchor actually fires the value is typed absence. A comparison\nover that absent operand is UNKNOWN; the action boundary takes no action.\n``mid`` and ``range`` are derived from the captured bar's high and low.\nDoes not accept ``resolution``.",
        "properties": {
          "anchor_field": {
            "enum": [
              "open",
              "high",
              "low",
              "close",
              "mid",
              "range"
            ],
            "title": "Anchor Field",
            "type": "string"
          },
          "anchor_id": {
            "title": "Anchor Id",
            "type": "string"
          },
          "kind": {
            "const": "anchor",
            "default": "anchor",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "anchor_id",
          "anchor_field"
        ],
        "title": "AnchorValueRef",
        "type": "object"
      },
      "AnyOfCondition": {
        "additionalProperties": false,
        "description": "Logical OR -- at least one child condition must be true.",
        "properties": {
          "child_names": {
            "anyOf": [
              {
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Child Names"
          },
          "conditions": {
            "items": {
              "$ref": "#/$defs/Condition"
            },
            "minItems": 1,
            "title": "Conditions",
            "type": "array"
          },
          "kind": {
            "const": "any_of",
            "default": "any_of",
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "conditions"
        ],
        "title": "AnyOfCondition",
        "type": "object"
      },
      "AroonIndicatorValueRef": {
        "additionalProperties": false,
        "description": "Aroon \u2014 how recently the window's extreme printed, scaled 0-100 (`line` picks up/down).\n\nMeasured over ``period + 1`` bars including the current one: 100 means the\nhighest high (or lowest low) is the current bar, 0 means it is the oldest\nbar in the window. Ties resolve to the **oldest** matching bar, so a level\nthat has been revisited reads lower than 100 even when the current bar\nequals the extreme. This ref exposes only the up and down lines; there is\nno oscillator (up - down) output.",
        "properties": {
          "indicator": {
            "const": "aroon",
            "default": "aroon",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "line": {
            "enum": [
              "up",
              "down"
            ],
            "title": "Line",
            "type": "string"
          },
          "period": {
            "maximum": 500,
            "minimum": 2,
            "title": "Period",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "period",
          "line"
        ],
        "title": "AroonIndicatorValueRef",
        "type": "object"
      },
      "AtLeastCondition": {
        "additionalProperties": false,
        "description": "At-least-N -- true when min_true or more child conditions are true.",
        "properties": {
          "child_names": {
            "anyOf": [
              {
                "items": {
                  "anyOf": [
                    {
                      "type": "string"
                    },
                    {
                      "type": "null"
                    }
                  ]
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Child Names"
          },
          "conditions": {
            "items": {
              "$ref": "#/$defs/Condition"
            },
            "minItems": 1,
            "title": "Conditions",
            "type": "array"
          },
          "kind": {
            "const": "at_least",
            "default": "at_least",
            "title": "Kind",
            "type": "string"
          },
          "min_true": {
            "maximum": 100,
            "minimum": 1,
            "title": "Min True",
            "type": "integer"
          }
        },
        "required": [
          "conditions",
          "min_true"
        ],
        "title": "AtLeastCondition",
        "type": "object"
      },
      "AtSessionCondition": {
        "additionalProperties": false,
        "description": "Execute a number of minutes after the session open or before the session close.\n\nSchedules the rule at that instant on every trading session, the general form of\n\"five minutes before the close\" or \"thirty minutes after the open\". The offset is\nresolved against each date's own open and close, so ``close`` with -5 is 12:55 on a\n13:00 half-day, and the order fills from the 1-minute execution print there. Works on\nANY timeframe, daily included; a daily strategy decides from the last completed daily\nbar (yesterday's).\n\n``open`` takes an offset of zero or more and ``close`` an offset of zero or less\n(negative is before the anchor): the opposite signs fall outside every session and are\nrefused when written. It needs a market with a session, so it is refused for crypto\n(24/7), which has no open or close; use ``at_time`` there. The rule is evaluated ONLY\nat these instants and places a market order, so other conditions alongside it are\nsampled then and a protective exit must not be scheduled. An entry at exactly the\nclose is refused by the simulator (its closing auction is reduce-only).\n\nBecause it names when to ACT, it can only be an entry or an exit trigger, alone or\ninside ``all_of`` with other conditions, one per rule. It cannot sit on a gate or\ninside any_of/not/sequence/consecutive/at_least/latch.\n\nExample, five minutes before the close: {\"kind\": \"at_session\", \"anchor\": \"close\", \"offset_minutes\": -5}",
        "properties": {
          "anchor": {
            "description": "The session boundary the offset is measured from: 'open' or 'close' of each trading session.",
            "enum": [
              "open",
              "close"
            ],
            "title": "Anchor",
            "type": "string"
          },
          "kind": {
            "const": "at_session",
            "default": "at_session",
            "title": "Kind",
            "type": "string"
          },
          "offset_minutes": {
            "description": "Whole minutes from the anchor; negative is before it. Zero or more after the 'open', zero or less before the 'close' (-5 is five minutes before the close). At most a day either way.",
            "maximum": 1440,
            "minimum": -1440,
            "title": "Offset Minutes",
            "type": "integer"
          }
        },
        "required": [
          "anchor",
          "offset_minutes"
        ],
        "title": "AtSessionCondition",
        "type": "object"
      },
      "AtTimeCondition": {
        "additionalProperties": false,
        "description": "Execute at a specific clock time (e.g. \"buy at 10:16\").\n\nSchedules the rule at that instant. The order is submitted at the clock time\nand fills from the 1-minute execution print opening exactly then \u2014 the time\nis honoured EXACTLY and is never snapped to the strategy's bar grid, because\nexecution resolution is independent of strategy resolution. Works on ANY\ntimeframe, daily included: a daily strategy scheduled at 10:31 takes its\ndecision from the last completed daily bar (yesterday's) and fills at\ntoday's 10:31 print.\n\nThe rule is evaluated ONLY at these moments and is removed from bar-close\nevaluation entirely, so any other conditions attached alongside it are\nsampled at the scheduled instant rather than checked every bar. That makes\nit the wrong place for a stop-loss or other protective exit, which must keep\nchecking every bar; the compiler refuses that combination by name.\n\nThe time is interpreted in the exchange session timezone (US equities:\nAmerica/New_York; crypto: UTC). A time that falls outside the session on a\ngiven date \u2014 15:30 on a 13:00 half-day \u2014 simply does not occur that day. A\ntime equal to that date's actual open or close routes to the opening or\nclosing auction, which backtests simulate and paper/live refuse.\n\nBecause it names when to ACT, it can only be an entry or an exit. It cannot\nsit on a gate or inside any_of/not/sequence; use predicates over ``time`` operands to restrict\nwhich bars qualify.",
        "properties": {
          "kind": {
            "const": "at_time",
            "default": "at_time",
            "title": "Kind",
            "type": "string"
          },
          "time": {
            "description": "Clock time in HH:MM 24-hour format, interpreted in the exchange session timezone. Schedules the decision at exactly this instant \u2014 it is never snapped to the strategy's bar grid, and works on any timeframe including daily.",
            "pattern": "^\\d{2}:\\d{2}$",
            "title": "Time",
            "type": "string"
          }
        },
        "required": [
          "time"
        ],
        "title": "AtTimeCondition",
        "type": "object"
      },
      "AtrOffsetSpec": {
        "additionalProperties": false,
        "description": "ATR-based offset from the signal bar's close price.\n\nThe limit/stop price is computed as: close + (ATR * atr_multiplier).\nFor example, atr_multiplier=-0.5 means half an ATR below close.",
        "properties": {
          "atr_multiplier": {
            "description": "ATR multiplier. -0.5 means half ATR below close.",
            "title": "Atr Multiplier",
            "type": "number"
          },
          "atr_period": {
            "default": 14,
            "description": "ATR lookback period",
            "exclusiveMinimum": 0,
            "title": "Atr Period",
            "type": "integer"
          },
          "kind": {
            "const": "atr_offset",
            "default": "atr_offset",
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "atr_multiplier"
        ],
        "title": "AtrOffsetSpec",
        "type": "object"
      },
      "BandOutput": {
        "enum": [
          "upper",
          "middle",
          "lower"
        ],
        "type": "string"
      },
      "BarIndexAnchorSource": {
        "additionalProperties": false,
        "description": "Capture the bar at the configured zero-based bar index.",
        "properties": {
          "bar_index": {
            "minimum": 0,
            "title": "Bar Index",
            "type": "integer"
          },
          "kind": {
            "const": "bar_index",
            "default": "bar_index",
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "bar_index"
        ],
        "title": "BarIndexAnchorSource",
        "type": "object"
      },
      "BasketAllocationAuthoring": {
        "additionalProperties": false,
        "description": "Existing basket modes, using the canonical collection policy shape.",
        "properties": {
          "capital_model": {
            "default": "partitioned",
            "enum": [
              "partitioned",
              "shared_pool"
            ],
            "title": "Capital Model",
            "type": "string"
          },
          "collection_risk": {
            "anyOf": [
              {
                "$ref": "#/$defs/CollectionRiskPolicy"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "constraints": {
            "anyOf": [
              {
                "$ref": "#/$defs/CollectionAuthoringConstraints"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "construction": {
            "discriminator": {
              "mapping": {
                "equal_weight": "#/$defs/EqualWeight",
                "manual": "#/$defs/ManualWeights",
                "rank_based": "#/$defs/BasketRankConstruction",
                "signal_proportional": "#/$defs/SignalProportional_IndicatorValueRef_"
              },
              "propertyName": "kind"
            },
            "oneOf": [
              {
                "$ref": "#/$defs/EqualWeight"
              },
              {
                "$ref": "#/$defs/ManualWeights"
              },
              {
                "$ref": "#/$defs/BasketRankConstruction"
              },
              {
                "$ref": "#/$defs/SignalProportional_IndicatorValueRef_"
              }
            ],
            "required": [
              "kind"
            ],
            "title": "Construction"
          },
          "rebalance": {
            "anyOf": [
              {
                "discriminator": {
                  "mapping": {
                    "calendar": "#/$defs/CalendarRebalance",
                    "none": "#/$defs/NoRebalance"
                  },
                  "propertyName": "kind"
                },
                "oneOf": [
                  {
                    "$ref": "#/$defs/NoRebalance"
                  },
                  {
                    "$ref": "#/$defs/CalendarRebalance"
                  }
                ],
                "required": [
                  "kind"
                ]
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Rebalance"
          }
        },
        "required": [
          "construction"
        ],
        "title": "BasketAllocationAuthoring",
        "type": "object"
      },
      "BasketRankConstruction": {
        "additionalProperties": false,
        "description": "Rank instruments by an indicator; construction owns their positions.",
        "properties": {
          "exit_top_n": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional looser exit threshold for entry/exit hysteresis. When set, a sleeve already held stays held until it drops out of the top exit_top_n (not just top_n); a sleeve NOT currently held only enters once it reaches the top top_n. Must be strictly greater than top_n (a looser exit threshold). None (default) = no hysteresis \u2014 a single top_n cutoff applies to both entry and exit, matching today's behavior. Use this to reduce rank-boundary whipsaw churn (e.g. top_n=2, exit_top_n=3 on a 5-name basket approximates 'enter top 40%, exit top 60%').",
            "title": "Exit Top N"
          },
          "kind": {
            "const": "rank_based",
            "title": "Kind",
            "type": "string"
          },
          "score_ref": {
            "$ref": "#/$defs/IndicatorValueRef"
          },
          "top_n": {
            "description": "Number of top-ranked sleeves to hold long at each rebalance. Must be >= 1.",
            "minimum": 1,
            "title": "Top N",
            "type": "integer"
          }
        },
        "required": [
          "kind",
          "score_ref",
          "top_n"
        ],
        "title": "BasketRankConstruction",
        "type": "object"
      },
      "BinaryExprValueRef": {
        "additionalProperties": false,
        "description": "Binary expression over two ValueRef operands.\n\nProvided alongside UnaryExprValueRef so tests / flat-Condition authors can\nbuild composite expressions like ``abs(close - 100)``. Compiles to a binary\nIRExpression.",
        "properties": {
          "kind": {
            "const": "binary_expr",
            "default": "binary_expr",
            "title": "Kind",
            "type": "string"
          },
          "left": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ]
          },
          "op": {
            "enum": [
              "+",
              "-",
              "*",
              "/",
              "max",
              "min"
            ],
            "title": "Op",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "right": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ]
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "op",
          "left",
          "right"
        ],
        "title": "BinaryExprValueRef",
        "type": "object"
      },
      "BollingerValueRef": {
        "additionalProperties": false,
        "description": "Bollinger Bands \u2014 select band edge or derived property.\n\nOutputs:\n  - upper / middle / lower: price-level bands\n  - bandwidth: (upper - lower) / middle * 100\n  - stddev: population standard deviation over the window",
        "properties": {
          "indicator": {
            "const": "bollinger",
            "default": "bollinger",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "multiplier": {
            "default": 2.0,
            "ge": 0.1,
            "le": 10.0,
            "title": "Multiplier",
            "type": "number"
          },
          "output": {
            "enum": [
              "upper",
              "middle",
              "lower",
              "bandwidth",
              "stddev"
            ],
            "title": "Output",
            "type": "string"
          },
          "period": {
            "default": 20,
            "maximum": 500,
            "minimum": 2,
            "title": "Period",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "output"
        ],
        "title": "BollingerValueRef",
        "type": "object"
      },
      "BreakoutRetestCondition": {
        "additionalProperties": false,
        "description": "Detect a breakout followed by a pullback retest within N bars.\n\nCompiles to a sequence: Donchian channel breakout, then ATR-based pullback.\nUse for confirmed breakout entries that wait for a retest of the breakout level.",
        "properties": {
          "direction": {
            "description": "long entry on an upside breakout; short entry on a downside breakout.",
            "enum": [
              "long",
              "short"
            ],
            "title": "Direction",
            "type": "string"
          },
          "kind": {
            "const": "breakout_retest",
            "default": "breakout_retest",
            "title": "Kind",
            "type": "string"
          },
          "lookback_bars": {
            "default": 20,
            "description": "Donchian breakout lookback in bars.",
            "maximum": 500,
            "minimum": 5,
            "title": "Lookback Bars",
            "type": "integer"
          },
          "pullback_depth_atr": {
            "default": 1.0,
            "description": "Pullback depth from the breakout, in ATR units.",
            "ge": 0.1,
            "le": 10.0,
            "title": "Pullback Depth Atr",
            "type": "number"
          },
          "within_bars": {
            "default": 20,
            "description": "Maximum bars after the breakout in which the retest can occur.",
            "maximum": 100,
            "minimum": 1,
            "title": "Within Bars",
            "type": "integer"
          }
        },
        "required": [
          "direction"
        ],
        "title": "BreakoutRetestCondition",
        "type": "object"
      },
      "CalendarRebalance": {
        "additionalProperties": false,
        "description": "Rebalance on a fixed calendar schedule (daily, weekly, or monthly).\n\nUses the existing ``Rebalance`` enum from the universe selector so the\nschedule vocabulary is consistent across the whole system.",
        "properties": {
          "kind": {
            "const": "calendar",
            "default": "calendar",
            "title": "Kind",
            "type": "string"
          },
          "min_interval_bars": {
            "default": 0,
            "description": "Minimum number of bars that must elapse between two consecutive rebalances, regardless of the trigger. 0 = no minimum (rebalance fires whenever the schedule or drift threshold fires). Use this to prevent thrashing on high-frequency drift triggers.",
            "minimum": 0,
            "title": "Min Interval Bars",
            "type": "integer"
          },
          "schedule": {
            "$ref": "#/$defs/Rebalance",
            "description": "Rebalance frequency: 'daily', 'weekly', or 'monthly'. Uses the same ``Rebalance`` enum as the universe selector."
          }
        },
        "required": [
          "schedule"
        ],
        "title": "CalendarRebalance",
        "type": "object"
      },
      "CalendarScheduleCondition": {
        "additionalProperties": false,
        "description": "Fire on a periodic calendar schedule (daily, weekly, biweekly, monthly, quarterly).\n\nUse for DCA / recurring-buy entries that trigger at regular intervals\nregardless of price action.\n\nSchedules the rule: it is evaluated ONLY at its occurrences and is removed\nfrom bar-close evaluation, so any other conditions attached alongside it are\nsampled at the scheduled moment rather than checked every bar. With ``time``\nset, the occurrence is that clock time and the order fills from the\nexecution print there; with ``time`` unset it is the session's own open\n(the opening auction), or midnight on a 24/7 market.\n\n``time`` is read in the exchange session timezone (US equities:\nAmerica/New_York; crypto: UTC) \u2014 exactly as ``at_time`` reads its own \u2014\nunless ``tz`` names another zone. A time that falls outside the session on\na given date simply does not occur that day.\n\nOccurrences landing on a non-trading day are moved or dropped by\n``holiday_policy``; the boundary's own date stays the occurrence's identity,\nso a rolled occurrence fires once, not twice.\n\nBecause it names when to ACT, it can only be an entry or an exit \u2014 not a\ngate, and not inside any_of/not/sequence. Use predicates over ``time`` operands to restrict\nwhich bars qualify instead.",
        "properties": {
          "day": {
            "anyOf": [
              {
                "$ref": "#/$defs/Weekday"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Day of week (required for '1w' and '2w' schedules)"
          },
          "every": {
            "description": "Calendar interval. '2w' fires on the target weekday of even ISO weeks (an absolute epoch, never chained off the last firing).",
            "enum": [
              "1d",
              "1w",
              "2w",
              "1m",
              "3m"
            ],
            "title": "Every",
            "type": "string"
          },
          "holiday_policy": {
            "default": "next_session",
            "description": "What happens when an occurrence lands on a non-trading day (exchange holiday or weekend) for calendar-backed (equity) markets. 'next_session' (default): fire on the first bar of the next trading session. 'skip': drop that occurrence entirely. 'previous_session': fire on the last trading session before the scheduled day. Ignored for 24/7 (crypto) markets, where every day trades.",
            "enum": [
              "next_session",
              "skip",
              "previous_session"
            ],
            "title": "Holiday Policy",
            "type": "string"
          },
          "kind": {
            "const": "calendar_schedule",
            "default": "calendar_schedule",
            "title": "Kind",
            "type": "string"
          },
          "time": {
            "anyOf": [
              {
                "pattern": "^\\d{2}:\\d{2}$",
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Time of day in HH:MM 24-hour format, interpreted in the exchange session timezone unless 'tz' names another one \u2014 the same rule at_time follows. Leave unset to fire at the session's own open.",
            "title": "Time"
          },
          "tz": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "IANA timezone name for 'time'. Omit (the default) to use the exchange session timezone (US equities: America/New_York; crypto: UTC), which is what at_time does. Set it only to pin a time to a zone other than the one the symbol trades in.",
            "title": "Tz"
          }
        },
        "required": [
          "every"
        ],
        "title": "CalendarScheduleCondition",
        "type": "object"
      },
      "CandlePatternCondition": {
        "additionalProperties": false,
        "description": "Detect candlestick patterns (hammer, engulfing, doji, morning star, etc.).\n\nFires on the bar where the pattern completes. Supports single-bar, two-bar,\nand three-bar patterns with optional quality filters. Use for reversal or continuation entries.",
        "properties": {
          "atr_period": {
            "default": 14,
            "description": "ATR period for min_range_atr filter",
            "maximum": 100,
            "minimum": 5,
            "title": "Atr Period",
            "type": "integer"
          },
          "kind": {
            "const": "candle_pattern",
            "default": "candle_pattern",
            "title": "Kind",
            "type": "string"
          },
          "max_body_frac": {
            "anyOf": [
              {
                "ge": 0.0,
                "le": 1.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Max body as fraction of total range. Hammer default: 0.33, Doji default: 0.1",
            "title": "Max Body Frac"
          },
          "max_opposite_wick_frac": {
            "anyOf": [
              {
                "ge": 0.0,
                "le": 1.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Max wick on the opposite side as fraction of range. Default: 0.1. Only applies to hammer/shooting_star/inverted_hammer.",
            "title": "Max Opposite Wick Frac"
          },
          "min_body_frac": {
            "anyOf": [
              {
                "ge": 0.0,
                "le": 1.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Min body as fraction of total range. Engulfing default: 0.5",
            "title": "Min Body Frac"
          },
          "min_range_atr": {
            "anyOf": [
              {
                "ge": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Min candle range as multiple of ATR. Filters noise candles. Default: pattern-specific; no filter for inside_bar.",
            "title": "Min Range Atr"
          },
          "min_wick_ratio": {
            "anyOf": [
              {
                "ge": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Min lower (hammer) or upper (shooting_star) wick as multiple of body. Default: 2.0. Only applies to hammer/shooting_star/inverted_hammer.",
            "title": "Min Wick Ratio"
          },
          "pattern": {
            "$ref": "#/$defs/PatternName",
            "description": "Candlestick pattern to detect. Single-bar: hammer, inverted_hammer, shooting_star, doji, dragonfly_doji, gravestone_doji, spinning_top, marubozu. Two-bar: bullish_engulfing, bearish_engulfing, harami, harami_cross, inside_bar. Three-bar: morning_star, evening_star, piercing_line, dark_cloud_cover, three_white_soldiers, three_black_crows."
          }
        },
        "required": [
          "pattern"
        ],
        "title": "CandlePatternCondition",
        "type": "object"
      },
      "CandlestickValueRef": {
        "additionalProperties": false,
        "description": "Candlestick pattern recognition as a numeric signal value (VIB-1316).\n\nEmits a per-bar value in ``{-1.0, 0.0, +1.0}`` indicating a bearish\npattern hit, no hit, or a bullish pattern hit respectively. Resolves the\npattern name to the same :class:`CandlePattern` class as\n``CandlePatternSpec`` and registers the same indicator, so the two paths\nare literally one value series, not two that agree.\n\nA name that reads as one side of a two-sided shape means that side only:\n``bearish_engulfing`` is ``-1`` on a bearish engulfing and ``0`` on a\nbullish one, never ``+1``.\n\nUse this ValueRef when you need the pattern value as an operand in a\n``compare`` or ``cross`` condition (e.g. ``candlestick(doji) == 1``).\nFor role-shaped entry/exit semantics with quality filters, prefer\n``CandlePatternSpec`` as the top-level ConditionSpec.",
        "properties": {
          "indicator": {
            "const": "candlestick",
            "default": "candlestick",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "pattern": {
            "$ref": "#/$defs/PatternName"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "pattern"
        ],
        "title": "CandlestickValueRef",
        "type": "object"
      },
      "CollectionAuthoringConstraints": {
        "additionalProperties": false,
        "description": "Only implemented constraints; policy admission narrows their contexts.",
        "properties": {
          "asset_class_caps": {
            "anyOf": [
              {
                "additionalProperties": {
                  "type": "number"
                },
                "type": "object"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Mapping of asset class -> maximum aggregate weight for that asset class. None = no asset-class caps.",
            "title": "Asset Class Caps"
          },
          "max_active_sleeves": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum number of sleeves that may hold a position concurrently \u2014 a book-level cap on concurrent open positions (routed to PortfolioPlan.max_positions). This is NOT the rank-based selection K, which is `top_n` on rank_based construction. None = unlimited. Must be >= 1.",
            "title": "Max Active Sleeves"
          },
          "max_position_pct": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "maximum": 1,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum weight any single sleeve may receive, as a fraction of the collection (0 < x <= 1). None = no per-position cap.",
            "title": "Max Position Pct"
          },
          "min_position_pct": {
            "anyOf": [
              {
                "exclusiveMaximum": 1,
                "minimum": 0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Minimum weight any held sleeve must receive, as a fraction of the collection (0 <= x < 1). None = no per-position floor.",
            "title": "Min Position Pct"
          }
        },
        "title": "CollectionAuthoringConstraints",
        "type": "object"
      },
      "CollectionRiskPolicy": {
        "additionalProperties": false,
        "description": "Book-level reactive risk controls at the collection altitude.\n\nThe sibling of ``CapitalPolicy`` at the collection level: where\n``CapitalPolicy`` governs how sleeves *share* capital, this governs how the\nwhole book *reacts* \u2014 a daily-loss halt, entry-rate caps, and a liquidity\nreserve. Mirrors ``RiskPolicy``'s frozen style (the per-sleeve breaker)\nbut applies to the entire collection's equity. All fields optional.",
        "properties": {
          "cooldown_bars": {
            "default": 0,
            "description": "Additional bars to wait after the halt condition clears before resuming entries. 0 = resume immediately when the loss condition clears.",
            "minimum": 0,
            "title": "Cooldown Bars",
            "type": "integer"
          },
          "day_basis": {
            "const": "utc_calendar",
            "default": "utc_calendar",
            "description": "How a 'day' is delimited for the daily-loss halt and entry-rate caps. 'utc_calendar' = UTC calendar day.",
            "title": "Day Basis",
            "type": "string"
          },
          "halt_behavior": {
            "default": "soft",
            "description": "What to do when the book halt is hit: 'soft' (resume after the loss condition clears and cooldown elapses) or 'hard' (require manual reset / restart).",
            "enum": [
              "soft",
              "hard"
            ],
            "title": "Halt Behavior",
            "type": "string"
          },
          "max_daily_loss_pct": {
            "anyOf": [
              {
                "maximum": 50.0,
                "minimum": 0.1,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Halt new entries across the whole book if the collection's daily P&L drops below -X% (0.1-50). None = no book-level daily-loss halt.",
            "title": "Max Daily Loss Pct"
          },
          "max_entries_per_day": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum number of new entries the whole book may open per calendar day. None = unlimited. Must be >= 1.",
            "title": "Max Entries Per Day"
          },
          "max_total_entries": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum number of new entries the whole book may open over the entire run. None = unlimited. Must be >= 1.",
            "title": "Max Total Entries"
          },
          "min_cash_pct": {
            "anyOf": [
              {
                "exclusiveMaximum": 1,
                "minimum": 0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Minimum fraction of collection equity to hold as a cash / liquidity reserve (0 <= x < 1). None = no reserve.",
            "title": "Min Cash Pct"
          }
        },
        "title": "CollectionRiskPolicy",
        "type": "object"
      },
      "CompareCondition": {
        "additionalProperties": false,
        "description": "Compare two signals with a relational operator (>, >=, <, <=, ==, !=).\n\nTrue on every bar where the comparison holds. Use for threshold checks like\n\"close > 100\", \"RSI > 70\", or \"EMA(20) > EMA(50)\".",
        "properties": {
          "kind": {
            "const": "compare",
            "default": "compare",
            "title": "Kind",
            "type": "string"
          },
          "left": {
            "$ref": "#/$defs/ValueRef",
            "description": "Left-hand value (e.g., close, ema(20))"
          },
          "op": {
            "$ref": "#/$defs/CompareOp",
            "description": "Comparison operator"
          },
          "right": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ],
            "description": "Right-hand value or constant",
            "title": "Right"
          }
        },
        "required": [
          "left",
          "op",
          "right"
        ],
        "title": "CompareCondition",
        "type": "object"
      },
      "CompareOp": {
        "description": "Comparison operators.",
        "enum": [
          "<",
          "<=",
          ">",
          ">=",
          "==",
          "!="
        ],
        "title": "CompareOp",
        "type": "string"
      },
      "Condition": {
        "discriminator": {
          "mapping": {
            "all_of": "#/$defs/AllOfCondition",
            "always_true": "#/$defs/AlwaysTrueCondition",
            "any_of": "#/$defs/AnyOfCondition",
            "at_least": "#/$defs/AtLeastCondition",
            "at_session": "#/$defs/AtSessionCondition",
            "at_time": "#/$defs/AtTimeCondition",
            "breakout_retest": "#/$defs/BreakoutRetestCondition",
            "calendar_schedule": "#/$defs/CalendarScheduleCondition",
            "candle_pattern": "#/$defs/CandlePatternCondition",
            "compare": "#/$defs/CompareCondition",
            "condition_ref": "#/$defs/ConditionReference",
            "consecutive": "#/$defs/ConsecutiveCondition",
            "cross": "#/$defs/CrossSignalCondition",
            "eod_flatten": "#/$defs/EodFlattenCondition",
            "fixed_targets": "#/$defs/FixedTargetsCondition",
            "flag_pattern": "#/$defs/FlagPatternCondition",
            "fvg": "#/$defs/FairValueGapCondition",
            "in_set": "#/$defs/InSetCondition",
            "latch": "#/$defs/LatchCondition",
            "liquidity_sweep": "#/$defs/LiquiditySweepCondition",
            "not": "#/$defs/NotCondition",
            "order_block": "#/$defs/OrderBlockCondition",
            "ote": "#/$defs/OTECondition",
            "pennant_pattern": "#/$defs/PennantPatternCondition",
            "range": "#/$defs/RangeCondition",
            "sequence": "#/$defs/SequenceCondition",
            "spread": "#/$defs/SpreadCondition",
            "trailing_stop": "#/$defs/TrailingStopCondition",
            "transition": "#/$defs/TransitionCondition"
          },
          "propertyName": "kind"
        },
        "oneOf": [
          {
            "$ref": "#/$defs/LiquiditySweepCondition"
          },
          {
            "$ref": "#/$defs/FairValueGapCondition"
          },
          {
            "$ref": "#/$defs/OrderBlockCondition"
          },
          {
            "$ref": "#/$defs/OTECondition"
          },
          {
            "$ref": "#/$defs/FlagPatternCondition"
          },
          {
            "$ref": "#/$defs/PennantPatternCondition"
          },
          {
            "$ref": "#/$defs/BreakoutRetestCondition"
          },
          {
            "$ref": "#/$defs/CandlePatternCondition"
          },
          {
            "$ref": "#/$defs/EodFlattenCondition"
          },
          {
            "$ref": "#/$defs/AtTimeCondition"
          },
          {
            "$ref": "#/$defs/CrossSignalCondition"
          },
          {
            "$ref": "#/$defs/TransitionCondition"
          },
          {
            "$ref": "#/$defs/InSetCondition"
          },
          {
            "$ref": "#/$defs/RangeCondition"
          },
          {
            "$ref": "#/$defs/CompareCondition"
          },
          {
            "$ref": "#/$defs/SpreadCondition"
          },
          {
            "$ref": "#/$defs/FixedTargetsCondition"
          },
          {
            "$ref": "#/$defs/TrailingStopCondition"
          },
          {
            "$ref": "#/$defs/CalendarScheduleCondition"
          },
          {
            "$ref": "#/$defs/AlwaysTrueCondition"
          },
          {
            "$ref": "#/$defs/AllOfCondition"
          },
          {
            "$ref": "#/$defs/AnyOfCondition"
          },
          {
            "$ref": "#/$defs/NotCondition"
          },
          {
            "$ref": "#/$defs/AtLeastCondition"
          },
          {
            "$ref": "#/$defs/SequenceCondition"
          },
          {
            "$ref": "#/$defs/ConsecutiveCondition"
          },
          {
            "$ref": "#/$defs/ConditionReference"
          },
          {
            "$ref": "#/$defs/LatchCondition"
          },
          {
            "$ref": "#/$defs/AtSessionCondition"
          }
        ],
        "required": [
          "kind"
        ]
      },
      "ConditionReference": {
        "additionalProperties": false,
        "description": "Binding-only source node. Resolve before Blueprint compilation.",
        "properties": {
          "definition_id": {
            "minLength": 1,
            "title": "Definition Id",
            "type": "string"
          },
          "kind": {
            "const": "condition_ref",
            "default": "condition_ref",
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "definition_id"
        ],
        "title": "ConditionReference",
        "type": "object"
      },
      "ConditionSequenceStep": {
        "additionalProperties": false,
        "properties": {
          "condition": {
            "$ref": "#/$defs/Condition"
          },
          "hold_bars": {
            "anyOf": [
              {
                "maximum": 5000,
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Hold Bars"
          },
          "id": {
            "anyOf": [
              {
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Explicit step id for SequenceStepValueRef lookup. Defaults to 'step_{index}' (e.g. step_0, step_1) when absent.",
            "title": "Id"
          },
          "within_bars": {
            "anyOf": [
              {
                "maximum": 5000,
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Within Bars"
          }
        },
        "required": [
          "condition"
        ],
        "title": "ConditionSequenceStep",
        "type": "object"
      },
      "ConditionTriggerAnchorSource": {
        "additionalProperties": false,
        "description": "Capture on a false->true transition of the embedded condition.",
        "properties": {
          "condition": {
            "$ref": "#/$defs/Condition",
            "description": "Condition that triggers the anchor capture"
          },
          "kind": {
            "const": "condition_trigger",
            "default": "condition_trigger",
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "condition"
        ],
        "title": "ConditionTriggerAnchorSource",
        "type": "object"
      },
      "ConsecutiveCondition": {
        "additionalProperties": false,
        "description": "N-of-M bar counter -- true when inner condition holds for min_true bars in a window.\n\nA bar on which the inner condition cannot be evaluated (an operand has no\nvalue yet) counts as a miss, so counting starts from the first bar the data\nexists; on that bar the count is UNKNOWN rather than false unless the window\nalready holds min_true truths -- so ``not(consecutive(...))`` takes no\naction until the data exists.",
        "properties": {
          "child_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Child Name"
          },
          "condition": {
            "$ref": "#/$defs/Condition"
          },
          "kind": {
            "const": "consecutive",
            "default": "consecutive",
            "title": "Kind",
            "type": "string"
          },
          "min_true": {
            "maximum": 100,
            "minimum": 1,
            "title": "Min True",
            "type": "integer"
          },
          "strict": {
            "default": true,
            "title": "Strict",
            "type": "boolean"
          },
          "window_bars": {
            "maximum": 100,
            "minimum": 1,
            "title": "Window Bars",
            "type": "integer"
          }
        },
        "required": [
          "condition",
          "min_true",
          "window_bars"
        ],
        "title": "ConsecutiveCondition",
        "type": "object"
      },
      "ConstantValueRef": {
        "additionalProperties": false,
        "description": "A fixed numeric literal, usable anywhere a value ref is accepted.\n\nThe one ref that is NOT a ``ValueRefBaseModel``: it has no ``symbol`` or\n``resolution`` qualifier. A bare int/float written into ``binary_expr``/\n``unary_expr`` operands or ``compare.right`` is coerced to this type\nautomatically, so writing it out explicitly is rarely necessary.",
        "properties": {
          "kind": {
            "const": "constant",
            "default": "constant",
            "title": "Kind",
            "type": "string"
          },
          "value": {
            "title": "Value",
            "type": "number"
          }
        },
        "required": [
          "value"
        ],
        "title": "ConstantValueRef",
        "type": "object"
      },
      "CrossSignalCondition": {
        "additionalProperties": false,
        "description": "Fires once on the bar where one signal crosses another (edge-based, not state).\n\nSupports any signal type on left and right \u2014 not just indicator-vs-indicator:\n- EMA/RSI/price crossing an indicator level (e.g., EMA 12 cross_above EMA 26)\n- Close crossing a swing high/low (e.g., edge-based breakout at prior swing high)\n- Close crossing a percentile level (e.g., price crosses 20-bar high)\n- Close crossing a rolling max/min (e.g., close cross_above rolling_max(high, 20))\n\nFor level-based (persistent) conditions use compare. For N-bar high/low breakouts\nthat fire every qualifying bar, compare against rolling_max/rolling_min with\nthe desired historical offset. Use cross+swing for edge-based breakouts.\n\nTo ask \"did this cross at any point in the last N bars\", wrap it in consecutive\nwith min_true=1, window_bars=N, strict=False \u2014 cross itself only reports the bar\nit fired on. For intrabar detection, cross against a high or low price operand\nrather than close; fills still follow the bar model of the order type you use.",
        "properties": {
          "direction": {
            "$ref": "#/$defs/LevelDirection"
          },
          "kind": {
            "const": "cross",
            "default": "cross",
            "title": "Kind",
            "type": "string"
          },
          "left": {
            "$ref": "#/$defs/ValueRef",
            "description": "Left-hand value (e.g., ema(20), close)"
          },
          "right": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ],
            "description": "Right-hand value or constant",
            "title": "Right"
          }
        },
        "required": [
          "left",
          "right",
          "direction"
        ],
        "title": "CrossSignalCondition",
        "type": "object"
      },
      "DispersionValueRef": {
        "additionalProperties": false,
        "description": "Spread of ``source`` across the WHOLE universe on the current bar.\n\nUnlike ``rank`` and ``xs_zscore`` it does not say where this symbol sits; every\nsymbol reads the same number, so it does not degrade while this symbol's own\nvalue is still warming up. ``stat`` chooses the standard deviation or the range.\n``source`` is evaluated once per symbol; it cannot carry a ``symbol`` and cannot\ncontain another cross-sectional operand. Requires a universe or portfolio strategy\nwith two or more symbols.\n\nExample, how widely 20-bar returns are spread across the universe:\n  {\"kind\": \"xs_dispersion\", \"stat\": \"stdev\",\n   \"source\": {\"kind\": \"indicator\", \"indicator\": \"roc\", \"period\": 20}}",
        "properties": {
          "kind": {
            "const": "xs_dispersion",
            "default": "xs_dispersion",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ],
            "description": "Per-symbol value whose spread across the universe is measured on the current bar. It is evaluated for each symbol on its own data."
          },
          "stat": {
            "description": "'stdev' = sample standard deviation (ddof=1) of the symbols' values. 'range' = highest minus lowest.",
            "enum": [
              "stdev",
              "range"
            ],
            "title": "Stat",
            "type": "string"
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "source",
          "stat"
        ],
        "title": "DispersionValueRef",
        "type": "object"
      },
      "DonchianValueRef": {
        "additionalProperties": false,
        "description": "Donchian Channel \u2014 rolling max/min over `period` bars; **excludes the current bar** (differs from most charting platforms which include it).\n\nNote: this engine excludes the current bar so that a close-exceeds-upper\nbreakout signal is meaningful (the current bar cannot contaminate its own\nband). Most charting platforms plot Donchian bands *including* the current\nbar \u2014 strategies ported from those platforms will see the breakout-bar\nupper/lower differ by one bar of high/low data. See\n``docs/indicator-conventions.md``.",
        "properties": {
          "indicator": {
            "const": "donchian",
            "default": "donchian",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "output": {
            "$ref": "#/$defs/BandOutput"
          },
          "period": {
            "default": 20,
            "maximum": 500,
            "minimum": 2,
            "title": "Period",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "output"
        ],
        "title": "DonchianValueRef",
        "type": "object"
      },
      "EntryBarField": {
        "enum": [
          "open",
          "high",
          "low",
          "close",
          "range",
          "body_high",
          "body_low"
        ],
        "type": "string"
      },
      "EntryBarValueRef": {
        "additionalProperties": false,
        "description": "Reference to a field of the signal bar for the currently-open position.\n\nAuto-captured by the engine when a position opens. Returns NaN when no\nposition is open. Clears on position close. Use for ORB-style \"stop out\nbelow the signal-bar low\" without AnchorDefinition's silent-latching bug.\n\nFields:\n  - open / high / low / close: signal-bar OHLC\n  - range: high - low\n  - body_high: max(open, close)\n  - body_low: min(open, close)",
        "properties": {
          "entry_bar_field": {
            "$ref": "#/$defs/EntryBarField"
          },
          "kind": {
            "const": "entry_bar",
            "default": "entry_bar",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "entry_bar_field"
        ],
        "title": "EntryBarValueRef",
        "type": "object"
      },
      "EodFlattenCondition": {
        "additionalProperties": false,
        "description": "Session end-of-day flatten exit: flat from close - N until the close.\n\nAt ``flatten_minutes_before_close`` minutes before the session close,\nresolved against THAT DATE's actual close \u2014 so a 13:00 half-day flattens at\n12:55, not at a 15:55 instant the session never reaches \u2014 it closes the\nposition (filled from the execution print at that instant) and cancels any\nentry still waiting to fill; until the close every entry signal is skipped\nas ``policy:eod_flat_window``. It must be its own, whole exit: combined with\nother conditions or attached with a size_frac it is refused at compile, as\nis a scheduled entry at or after close - N.\n\nEquity (session-bound) instruments only. A 24/7 crypto session has no close\nto anchor to, so the condition is refused at attach and at Blueprint\nconstruction for a crypto strategy (it used to compile to a\n``minutes_to_close`` comparison that is NaN on every bar and silently never\nfired). For a 24/7 market exit at a clock time with ``at_time`` instead.",
        "properties": {
          "flatten_minutes_before_close": {
            "default": 5,
            "description": "Minutes before session close at which to flatten, and from which the position stays flat until the close. Compiles to a scheduled exit at AnchorTrigger(close, -N) holding the flat window. Use at least 1 minute; 0 would require an official closing-auction print for market-on-close.",
            "maximum": 390,
            "minimum": 1,
            "title": "Flatten Minutes Before Close",
            "type": "integer"
          },
          "kind": {
            "const": "eod_flatten",
            "default": "eod_flatten",
            "title": "Kind",
            "type": "string"
          }
        },
        "title": "EodFlattenCondition",
        "type": "object"
      },
      "EqualWeight": {
        "additionalProperties": false,
        "description": "Allocate equal weight to every active sleeve in the collection.\n\nThis is the default when ``construction`` is ``None`` on a universe\nstrategy. No parameters are required.",
        "properties": {
          "kind": {
            "const": "equal_weight",
            "default": "equal_weight",
            "title": "Kind",
            "type": "string"
          }
        },
        "title": "EqualWeight",
        "type": "object"
      },
      "EquityValueRef": {
        "additionalProperties": false,
        "description": "The strategy's running equity-curve value.\n\n``field`` selects: ``current`` (equity right now), ``peak`` (the running\nhigh-water mark), or ``drawdown_pct`` (percent below that peak \u2014 0 at a\nnew high, positive while underwater). Use ``drawdown_pct`` directly for a\ncircuit-breaker gate rather than deriving it from ``current``/``peak``.\n\nVIB-1370 / VIB-1319: the sub-metric selector is named ``field``\nacross every ValueRef-style type. The legacy name ``equity_metric`` was\nremoved.",
        "properties": {
          "field": {
            "enum": [
              "drawdown_pct",
              "current",
              "peak"
            ],
            "title": "Field",
            "type": "string"
          },
          "kind": {
            "const": "equity",
            "default": "equity",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "field"
        ],
        "title": "EquityValueRef",
        "type": "object"
      },
      "EventDistanceValueRef": {
        "additionalProperties": false,
        "description": "Distance from the current bar to an event type's next or previous occurrence.\n\n``direction=\"previous\"`` counts back to the latest occurrence at or before the\nbar: 0 on the bar the occurrence is assigned to. ``direction=\"next\"`` counts\nforward to the earliest occurrence strictly after the bar, so it is never 0\nin minutes. ``unit`` is wall-clock minutes or bars.\n\nWhen no such occurrence is known the value is infinity (present, not absent), so\n``distance <= N`` is false and ``not (distance <= N)`` is true: that is how a\n\"stay away from events\" gate is written.\n\nA ``next`` distance needs the event's date to be known in advance. Among system\nevents only those with a forward release calendar (macro.cpi,\nmacro.nonfarm_payrolls, macro.unemployment) qualify; any other system event is\nrefused with ``direction=\"next\"``, because the platform cannot anticipate it.\nCustom events are unrestricted. Use ``direction=\"previous\"`` to react after a\nsystem event.\n\nExample, within 5 bars after an event:\n  {\"kind\": \"event_distance\", \"event_type_id\": \"my-signal\", \"direction\": \"previous\",\n   \"unit\": \"bars\"}",
        "properties": {
          "direction": {
            "description": "'previous' = distance back to the latest occurrence at or before this bar. 'next' = distance forward to the earliest occurrence after this bar; needs a custom event or a system event with a forward release calendar.",
            "enum": [
              "next",
              "previous"
            ],
            "title": "Direction",
            "type": "string"
          },
          "event_type_id": {
            "description": "Event type ID from list_event_types().",
            "title": "Event Type Id",
            "type": "string"
          },
          "kind": {
            "const": "event_distance",
            "default": "event_distance",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          },
          "unit": {
            "anyOf": [
              {
                "enum": [
                  "minutes",
                  "bars"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Measure the distance in wall-clock minutes or in bars; minutes when omitted.",
            "title": "Unit"
          }
        },
        "required": [
          "event_type_id",
          "direction"
        ],
        "title": "EventDistanceValueRef",
        "type": "object"
      },
      "EventFieldValueRef": {
        "additionalProperties": false,
        "description": "Field from latest event payload.\n\nAuthoring flow:\n  1. Call list_event_types().\n  2. Pick event_type_id from a returned event type.\n  3. Pick event_field from payload_schema.fields.\n\nExample:\n  {\"kind\": \"event_field\", \"event_type_id\": \"macro.cpi\",\n   \"event_field\": \"value\"}\n\nTo compare a release against a previous one, set occurrences_back on a\nsecond ref and subtract:\n  {\"kind\": \"binary_expr\", \"op\": \"-\",\n   \"left\":  {\"kind\": \"event_field\", \"event_type_id\": \"macro.cpi\",\n             \"event_field\": \"value\"},\n   \"right\": {\"kind\": \"event_field\", \"event_type_id\": \"macro.cpi\",\n             \"event_field\": \"value\", \"occurrences_back\": 1}}",
        "properties": {
          "event_field": {
            "description": "Payload field from payload_schema.fields. A field the event type's schema does not declare is refused, naming the declared fields.",
            "title": "Event Field",
            "type": "string"
          },
          "event_type_id": {
            "description": "Event type ID from list_event_types().",
            "title": "Event Type Id",
            "type": "string"
          },
          "fill": {
            "default": "previous",
            "description": "'previous' carries forward; 'none' resolves only on the event bar.",
            "enum": [
              "none",
              "previous"
            ],
            "title": "Fill",
            "type": "string"
          },
          "kind": {
            "const": "event_field",
            "default": "event_field",
            "title": "Kind",
            "type": "string"
          },
          "max_age_seconds": {
            "anyOf": [
              {
                "minimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Staleness limit for carried-forward values, in seconds.",
            "title": "Max Age Seconds"
          },
          "occurrences_back": {
            "default": 0,
            "description": "0 = latest release; 1 = the release before it, and so on. Counted by distinct data period, so a later revision of an earlier period does not consume a step. Requires an event type whose payload declares a 'period' (the macro.*/treasury.*/market.*/energy.* release families) and fill='previous'. Resolves as missing when fewer than occurrences_back+1 releases are known.",
            "minimum": 0,
            "title": "Occurrences Back",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "event_type_id",
          "event_field"
        ],
        "title": "EventFieldValueRef",
        "type": "object"
      },
      "ExecutionConfig": {
        "additionalProperties": false,
        "description": "How to place orders when a signal fires.\n\nOrder types:\n- market: Execute immediately at market price (default)\n- limit: Execute at limit_price or better\n- stop: Trigger when price reaches stop_price, then market order\n- stop_limit: Trigger at stop_price, then limit order at limit_price\n\nPrices can be static floats or dynamic PriceSpec objects:\n- float: Fixed price (e.g., 49000)\n- PctOffsetSpec: Percentage offset from close (e.g., -0.5 = 0.5% below close)\n- AtrOffsetSpec: ATR-based offset from close (e.g., -0.5 = half ATR below close)\n- AnchorPriceSpec: Use a persisted anchor field (e.g., session_open.close)\n- ZonePriceSpec: Use a zone level from the runtime zone registry\n- NamedZoneValueRef: Use a strategy-level named zone boundary or midpoint\n\nNote: A buy limit above close (or sell limit below close) fills immediately\nsince LEAN fills at the limit price or better \u2014 effectively a market order.\n\nExamples:\n    ExecutionConfig()                                          # market order\n    ExecutionConfig(order_type=\"limit\", limit_price=49000)     # static limit\n    ExecutionConfig(order_type=\"limit\",\n                    limit_price=PctOffsetSpec(pct=-0.5))       # 0.5% below close\n    ExecutionConfig(order_type=\"stop\",\n                    stop_price=AtrOffsetSpec(atr_multiplier=1.5))  # 1.5 ATR above close",
        "properties": {
          "alert_cooldown_minutes": {
            "anyOf": [
              {
                "minimum": 0,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Alert-mode debounce: minimum wall-clock minutes between successive alerts for the same signal. None or 0 fires on every rising edge.",
            "title": "Alert Cooldown Minutes"
          },
          "limit_price": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "discriminator": {
                  "mapping": {
                    "anchor": "#/$defs/AnchorPriceSpec",
                    "atr_offset": "#/$defs/AtrOffsetSpec",
                    "named_zone": "#/$defs/NamedZoneValueRef",
                    "pct_offset": "#/$defs/PctOffsetSpec",
                    "triggering_zone": "#/$defs/TriggeringZonePriceSpec",
                    "zone": "#/$defs/ZonePriceSpec"
                  },
                  "propertyName": "kind"
                },
                "oneOf": [
                  {
                    "$ref": "#/$defs/PctOffsetSpec"
                  },
                  {
                    "$ref": "#/$defs/AtrOffsetSpec"
                  },
                  {
                    "$ref": "#/$defs/AnchorPriceSpec"
                  },
                  {
                    "$ref": "#/$defs/ZonePriceSpec"
                  },
                  {
                    "$ref": "#/$defs/TriggeringZonePriceSpec"
                  },
                  {
                    "$ref": "#/$defs/NamedZoneValueRef"
                  }
                ],
                "required": [
                  "kind"
                ]
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Limit price: static float or dynamic PriceSpec",
            "title": "Limit Price"
          },
          "mode": {
            "default": "trade",
            "description": "Execution mode. 'trade' (default) places real orders. 'alert' turns the strategy into a notify-only monitor: entry signals emit ALERT_TRIGGERED notifications instead of orders (no fills, no positions). An omitted mode is always 'trade'.",
            "enum": [
              "trade",
              "alert"
            ],
            "title": "Mode",
            "type": "string"
          },
          "order_type": {
            "default": "market",
            "description": "Order type",
            "enum": [
              "market",
              "limit",
              "stop",
              "stop_limit"
            ],
            "title": "Order Type",
            "type": "string"
          },
          "stop_price": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "discriminator": {
                  "mapping": {
                    "anchor": "#/$defs/AnchorPriceSpec",
                    "atr_offset": "#/$defs/AtrOffsetSpec",
                    "named_zone": "#/$defs/NamedZoneValueRef",
                    "pct_offset": "#/$defs/PctOffsetSpec",
                    "triggering_zone": "#/$defs/TriggeringZonePriceSpec",
                    "zone": "#/$defs/ZonePriceSpec"
                  },
                  "propertyName": "kind"
                },
                "oneOf": [
                  {
                    "$ref": "#/$defs/PctOffsetSpec"
                  },
                  {
                    "$ref": "#/$defs/AtrOffsetSpec"
                  },
                  {
                    "$ref": "#/$defs/AnchorPriceSpec"
                  },
                  {
                    "$ref": "#/$defs/ZonePriceSpec"
                  },
                  {
                    "$ref": "#/$defs/TriggeringZonePriceSpec"
                  },
                  {
                    "$ref": "#/$defs/NamedZoneValueRef"
                  }
                ],
                "required": [
                  "kind"
                ]
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Stop trigger price: static float or dynamic PriceSpec",
            "title": "Stop Price"
          },
          "time_in_force": {
            "default": "gtc",
            "description": "Time in force for non-market orders",
            "enum": [
              "gtc",
              "day"
            ],
            "title": "Time In Force",
            "type": "string"
          }
        },
        "title": "ExecutionConfig",
        "type": "object"
      },
      "FairValueGapCondition": {
        "additionalProperties": false,
        "description": "Detect Fair Value Gap (FVG) zones -- 3-candle imbalance patterns.\n\nCreates zones in the zone registry when FVGs form. Entry triggers\nwhen price returns to an unfilled FVG zone.",
        "properties": {
          "direction": {
            "$ref": "#/$defs/PatternBias",
            "default": "both"
          },
          "expires_after_bars": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": 200,
            "description": "Zone expiry in bars",
            "title": "Expires After Bars"
          },
          "fill_frac": {
            "default": 0.5,
            "description": "Fill percentage (0-1) at which zone is considered filled",
            "ge": 0.0,
            "le": 1.0,
            "title": "Fill Frac",
            "type": "number"
          },
          "kind": {
            "const": "fvg",
            "default": "fvg",
            "title": "Kind",
            "type": "string"
          },
          "min_gap_pct": {
            "default": 0.1,
            "description": "Minimum gap size as % of price",
            "ge": 0.0,
            "title": "Min Gap Pct",
            "type": "number"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this zone's lifecycle. Set to e.g. '4h' to create, fill, expire, and invalidate this zone on 4H bar closes. None = strategy primary timeframe."
          },
          "select": {
            "$ref": "#/$defs/ZoneSelection",
            "default": "any",
            "description": "How to pick among matching zones at trigger time. 'any' (default) fires when any zone overlaps the bar. 'nearest'/'most_recent'/'oldest' deterministically pick one zone \u2014 required when binding execution price via TriggeringZonePriceSpec (VIB-591)."
          }
        },
        "title": "FairValueGapCondition",
        "type": "object"
      },
      "FixedTargetsCondition": {
        "additionalProperties": false,
        "description": "Fixed take-profit, stop-loss, and time-stop exits based on entry price.\n\nFires when price hits a percentage-based TP/SL level or a bar count is reached.\nUse as an exit condition for simple bracket-style position management.",
        "properties": {
          "breakeven_buffer_pct": {
            "default": 0.0,
            "ge": 0.0,
            "le": 10.0,
            "title": "Breakeven Buffer Pct",
            "type": "number"
          },
          "breakeven_trigger_pct": {
            "anyOf": [
              {
                "gt": 0.0,
                "le": 100.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Breakeven Trigger Pct"
          },
          "kind": {
            "const": "fixed_targets",
            "default": "fixed_targets",
            "title": "Kind",
            "type": "string"
          },
          "stop_loss_pct": {
            "anyOf": [
              {
                "ge": 0.1,
                "le": 100.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Stop Loss Pct"
          },
          "stop_loss_price_ref": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Structural stop price (absolute) resolved from a ValueRef at fill time. Mutually exclusive with stop_loss_pct."
          },
          "stop_order_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "ID of the stop order to use as the R-distance anchor for take_profit_r_multiple. Defaults to 'sl' (the stop emitted by this spec). Only valid when take_profit_r_multiple is set.",
            "title": "Stop Order Id"
          },
          "take_profit_pct": {
            "anyOf": [
              {
                "ge": 0.1,
                "le": 100.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Take Profit Pct"
          },
          "take_profit_r_multiple": {
            "anyOf": [
              {
                "gt": 0.0,
                "le": 100.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Take-profit at N x R from the SL's risk distance. Requires a stop (stop_loss_pct or stop_loss_price_ref). Mutually exclusive with take_profit_pct and take_profit_tiers. Resolved at fill time.",
            "title": "Take Profit R Multiple"
          },
          "take_profit_tiers": {
            "items": {
              "$ref": "#/$defs/TpTierSpec"
            },
            "title": "Take Profit Tiers",
            "type": "array"
          },
          "time_stop_bars": {
            "anyOf": [
              {
                "description": "Hold the position for exactly this many bars, counting the bar the entry filled in as bar 1: the exit is decided at the close of the Nth held bar and fills at the next bar's open, so exit_bar - entry_bar is N.",
                "maximum": 10000,
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Time Stop Bars"
          }
        },
        "title": "FixedTargetsCondition",
        "type": "object"
      },
      "FlagPatternCondition": {
        "additionalProperties": false,
        "description": "Flag chart pattern detection.\n\nA flag is a strong directional move (pole) followed by a shallow counter-trend\nconsolidation (flag). Breakout from the flag continues the pole direction.",
        "properties": {
          "consolidation_bars": {
            "maximum": 100,
            "minimum": 1,
            "title": "Consolidation Bars",
            "type": "integer"
          },
          "direction": {
            "enum": [
              "up",
              "down",
              "same"
            ],
            "title": "Direction",
            "type": "string"
          },
          "kind": {
            "const": "flag_pattern",
            "default": "flag_pattern",
            "title": "Kind",
            "type": "string"
          },
          "min_momentum_pct": {
            "default": 2.0,
            "ge": 0.5,
            "le": 20.0,
            "title": "Min Momentum Pct",
            "type": "number"
          },
          "momentum_bars": {
            "maximum": 100,
            "minimum": 1,
            "title": "Momentum Bars",
            "type": "integer"
          }
        },
        "required": [
          "momentum_bars",
          "consolidation_bars",
          "direction"
        ],
        "title": "FlagPatternCondition",
        "type": "object"
      },
      "GapIndicatorValueRef": {
        "additionalProperties": false,
        "description": "Session-open gap, in percent: (session open - prior session close) / prior session close * 100.\n\nThe value exists ONLY on the first bar of the chosen session, and only once the\nprior session's close is known; on every other bar it is absent, so a comparison\nover it is unknown. Compare it with a threshold to state a market fact: a gap up\nis ``gap > 0.5``, a gap down is ``gap < -0.5``. The operand names no trade side.\n\nThe source candles must preserve both session boundaries. US equity candles do so\nat every supported resolution; crypto candles (UTC-aligned) do so for all three\nsessions through 30m and for Asia at 1h. Other region and timeframe combinations\nare refused when the strategy is compiled. Unlike ``gap_pct`` (every bar, open\nagainst the previous close), this is session-aware.\n\nExample: {\"kind\": \"indicator\", \"indicator\": \"gap\", \"session\": \"us\"}",
        "properties": {
          "indicator": {
            "const": "gap",
            "default": "gap",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "session": {
            "anyOf": [
              {
                "enum": [
                  "us",
                  "eu",
                  "asia"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Session whose opening gap is measured: 'us', 'eu' or 'asia'; 'us' when omitted. Requires candles aligned to that session's open and close (see the operand description).",
            "title": "Session"
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "GapIndicatorValueRef",
        "type": "object"
      },
      "HaltBehavior": {
        "description": "What happens when a risk limit is breached.",
        "enum": [
          "soft",
          "hard"
        ],
        "title": "HaltBehavior",
        "type": "string"
      },
      "InSetCondition": {
        "additionalProperties": false,
        "description": "Membership test for discrete-valued refs: ``value \u2208 members`` (or its negation).\n\nIntended for categorical/discrete signals like ``supertrend.direction``\n(values in ``{-1, +1}``). Equivalent to ``any_of(compare(value == m) ...)``\nbut with cleaner ergonomics and a single capture node.\n\nSemantics:\n  - Evaluates once per bar from the resolved value of ``value``.\n  - If ``value`` has no value on the bar, the condition is unknown and\n    takes no action regardless of ``negate`` (undefined is neither in nor\n    out of the set).\n  - Numeric members are compared with tolerance 1e-9.\n  - ``negate=True`` flips in-set to not-in-set.\n\nExamples:\n    Direction is +1 or -1 (trend is engaged either way):\n        {\"kind\": \"in_set\", \"value\": {...supertrend.direction ref...},\n         \"members\": [-1, 1]}\n\n    Direction is NOT sideways (not zero):\n        {\"kind\": \"in_set\", \"value\": {...}, \"members\": [0], \"negate\": true}\n\nFor onset semantics on categorical values (fires once when a discrete ref's value\nchanges), use ``TransitionCondition`` \u2014 the discrete-valued counterpart to onset.",
        "properties": {
          "kind": {
            "const": "in_set",
            "default": "in_set",
            "title": "Kind",
            "type": "string"
          },
          "members": {
            "description": "Allowed values (numeric literals, compared with tolerance 1e-9).",
            "items": {
              "type": "number"
            },
            "minItems": 1,
            "title": "Members",
            "type": "array"
          },
          "negate": {
            "default": false,
            "description": "If True, fires when value is NOT in members.",
            "title": "Negate",
            "type": "boolean"
          },
          "value": {
            "$ref": "#/$defs/ValueRef",
            "description": "Value to test for set membership"
          }
        },
        "required": [
          "value",
          "members"
        ],
        "title": "InSetCondition",
        "type": "object"
      },
      "IndicatorValueRef": {
        "discriminator": {
          "mapping": {
            "ad": "#/$defs/AdIndicatorValueRef",
            "adx_di": "#/$defs/ADXIndicatorValueRef",
            "aroon": "#/$defs/AroonIndicatorValueRef",
            "atr": "#/$defs/PeriodIndicatorValueRef",
            "avwap": "#/$defs/AVWAPIndicatorValueRef",
            "bollinger": "#/$defs/BollingerValueRef",
            "candlestick": "#/$defs/CandlestickValueRef",
            "cci": "#/$defs/PeriodIndicatorValueRef",
            "cmf": "#/$defs/PeriodIndicatorValueRef",
            "donchian": "#/$defs/DonchianValueRef",
            "ema": "#/$defs/MovingAverageValueRef",
            "gap": "#/$defs/GapIndicatorValueRef",
            "keltner": "#/$defs/KeltnerValueRef",
            "macd": "#/$defs/MacdIndicatorValueRef",
            "macd_histogram": "#/$defs/MacdIndicatorValueRef",
            "macd_signal": "#/$defs/MacdIndicatorValueRef",
            "median": "#/$defs/PeriodIndicatorValueRef",
            "mfi": "#/$defs/PeriodIndicatorValueRef",
            "obv": "#/$defs/OBVIndicatorValueRef",
            "pivot_p": "#/$defs/PivotIndicatorValueRef",
            "pivot_r1": "#/$defs/PivotIndicatorValueRef",
            "pivot_r2": "#/$defs/PivotIndicatorValueRef",
            "pivot_r3": "#/$defs/PivotIndicatorValueRef",
            "pivot_s1": "#/$defs/PivotIndicatorValueRef",
            "pivot_s2": "#/$defs/PivotIndicatorValueRef",
            "pivot_s3": "#/$defs/PivotIndicatorValueRef",
            "roc": "#/$defs/PeriodIndicatorValueRef",
            "rsi": "#/$defs/PeriodIndicatorValueRef",
            "sma": "#/$defs/MovingAverageValueRef",
            "srsi_d": "#/$defs/SrsiIndicatorValueRef",
            "srsi_k": "#/$defs/SrsiIndicatorValueRef",
            "std": "#/$defs/PeriodIndicatorValueRef",
            "stochastic_d": "#/$defs/StochasticIndicatorValueRef",
            "stochastic_k": "#/$defs/StochasticIndicatorValueRef",
            "supertrend": "#/$defs/SupertrendIndicatorValueRef",
            "var": "#/$defs/PeriodIndicatorValueRef",
            "volume_sma": "#/$defs/PeriodIndicatorValueRef",
            "vwap": "#/$defs/VWAPIndicatorValueRef",
            "vwap_bands": "#/$defs/VWAPBandsValueRef",
            "vwma": "#/$defs/MovingAverageValueRef",
            "wma": "#/$defs/MovingAverageValueRef"
          },
          "propertyName": "indicator"
        },
        "oneOf": [
          {
            "$ref": "#/$defs/MovingAverageValueRef"
          },
          {
            "$ref": "#/$defs/PeriodIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/MacdIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/StochasticIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/SrsiIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/AdIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/OBVIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/AroonIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/SupertrendIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/BollingerValueRef"
          },
          {
            "$ref": "#/$defs/DonchianValueRef"
          },
          {
            "$ref": "#/$defs/KeltnerValueRef"
          },
          {
            "$ref": "#/$defs/VWAPBandsValueRef"
          },
          {
            "$ref": "#/$defs/VWAPIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/AVWAPIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/ADXIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/PivotIndicatorValueRef"
          },
          {
            "$ref": "#/$defs/CandlestickValueRef"
          },
          {
            "$ref": "#/$defs/GapIndicatorValueRef"
          }
        ],
        "required": [
          "indicator"
        ]
      },
      "KeltnerValueRef": {
        "additionalProperties": false,
        "description": "Keltner Channel \u2014 EMA middle with ATR-based upper/lower bands.\n\nMirrors BollingerValueRef/DonchianValueRef. Exposes typed access to the\nthree KC band edges. ``period`` drives the EMA middle band. Set\n``atr_period`` to use a different lookback for the ATR that shapes the\nupper/lower bands (common practice is a shorter ATR than the EMA, e.g.\n``period=20, atr_period=10``). ``atr_period=None`` (default) reuses\n``period`` for ATR \u2014 historical behavior.",
        "properties": {
          "atr_period": {
            "anyOf": [
              {
                "maximum": 500,
                "minimum": 2,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Atr Period"
          },
          "indicator": {
            "const": "keltner",
            "default": "keltner",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "multiplier": {
            "default": 2.0,
            "ge": 0.1,
            "le": 10.0,
            "title": "Multiplier",
            "type": "number"
          },
          "output": {
            "$ref": "#/$defs/BandOutput"
          },
          "period": {
            "default": 20,
            "maximum": 500,
            "minimum": 2,
            "title": "Period",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "output"
        ],
        "title": "KeltnerValueRef",
        "type": "object"
      },
      "LatchCondition": {
        "additionalProperties": false,
        "description": "Edge detector with memory -- true on the bar where ``fire`` holds after ``arm`` did.\n\nObserved at every bar close, warm-up bars included. A close where ``arm`` is true\narms it and the result is false; ``arm`` wins if both are true. While armed, a close\nwhere ``fire`` is true returns true once and disarms it. If either side has no value on\na bar the result has no value and the armed state does not change. Position events never\nreset it, only firing does, and two identical latches share one state.\n\nThis is the form of \"price re-enters the band after leaving it\" (``arm`` = outside,\n``fire`` = inside) and of a rising edge (``arm`` = not(c), ``fire`` = c). Under a\nscheduled rule only the outcome of the frame bar's close is seen: a fire on an earlier\nbar is consumed on that bar and is not seen at the next occurrence, so a latch fire\nbetween two occurrences is lost while an armed latch stays armed.\n\nBoth children are ordinary conditions or ``condition_ref``s. A protective policy\n(stop, target, trailing stop) or a schedule cannot sit inside either, as under any\nother combinator.\n\nExample, price closes back above a level after closing below it:\n{\"kind\": \"latch\",\n \"arm\": {\"kind\": \"compare\", \"left\": {\"kind\": \"price\", \"field\": \"close\"}, \"op\": \"<\", \"right\": 100},\n \"fire\": {\"kind\": \"compare\", \"left\": {\"kind\": \"price\", \"field\": \"close\"}, \"op\": \">=\", \"right\": 100}}",
        "properties": {
          "arm": {
            "$ref": "#/$defs/Condition",
            "description": "Condition that arms the latch on any close where it is true. Arming wins if `fire` is true on the same close."
          },
          "fire": {
            "$ref": "#/$defs/Condition",
            "description": "Condition that, while the latch is armed, makes it true for that one close and disarms it."
          },
          "kind": {
            "const": "latch",
            "default": "latch",
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "arm",
          "fire"
        ],
        "title": "LatchCondition",
        "type": "object"
      },
      "LevelDirection": {
        "enum": [
          "above",
          "below"
        ],
        "type": "string"
      },
      "LiquiditySweepCondition": {
        "additionalProperties": false,
        "description": "Detect a liquidity sweep pattern (price breaks a level then reclaims it).\n\nPrice sweeps beyond a recent high/low and then reverses back within\nwithin_bars. Common stop-hunt pattern used for reversal entries.\n\ndirection:\n  \"low\"  \u2014 sweep below recent low, reclaim above it (bullish reversal)\n  \"high\" \u2014 sweep above recent high, reclaim below it (bearish reversal)\n  \"both\" \u2014 detect either sweep type",
        "properties": {
          "direction": {
            "default": "low",
            "enum": [
              "low",
              "high",
              "both"
            ],
            "title": "Direction",
            "type": "string"
          },
          "kind": {
            "const": "liquidity_sweep",
            "default": "liquidity_sweep",
            "title": "Kind",
            "type": "string"
          },
          "lookback_bars": {
            "default": 20,
            "maximum": 5000,
            "minimum": 1,
            "title": "Lookback Bars",
            "type": "integer"
          },
          "within_bars": {
            "default": 5,
            "maximum": 100,
            "minimum": 1,
            "title": "Within Bars",
            "type": "integer"
          }
        },
        "title": "LiquiditySweepCondition",
        "type": "object"
      },
      "LivePositionValueRef": {
        "additionalProperties": false,
        "description": "A metric of the CURRENTLY OPEN position, read live every bar (not a\nfrozen snapshot from entry \u2014 contrast ``entry_bar``/``sequence_step``,\nwhich capture a value once and hold it).\n\n``field`` selects: ``entry_price``, ``bars_in_position``,\n``unrealized_pnl_pct`` / ``unrealized_pnl_usd``, or\n``max_excursion_pct`` / ``min_excursion_pct`` (the best/worst unrealized\nPnL% reached since entry \u2014 MAE/MFE). All are NaN while flat.\n\n``bars_in_position`` counts the bars the position has been open in,\nINCLUDING the bar it filled in: it is 1 at the close of the fill bar, not\n0. An exit on ``bars_in_position >= N`` therefore decides at the close of\nthe Nth held bar and fills at the next bar's open, so the trade's\n``exit_bar - entry_bar`` is exactly N.\n\nVIB-1398 / VIB-1370 / VIB-1319: the sub-metric selector is named\n``field`` across every ValueRef-style type. The legacy name\n``position_metric`` was removed (mirrors the IR-side\n``LivePositionRef.metric \u2192 field`` rename that VIB-1394 shipped).",
        "properties": {
          "field": {
            "enum": [
              "entry_price",
              "bars_in_position",
              "unrealized_pnl_pct",
              "unrealized_pnl_usd",
              "max_excursion_pct",
              "min_excursion_pct"
            ],
            "title": "Field",
            "type": "string"
          },
          "kind": {
            "const": "live_position",
            "default": "live_position",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "field"
        ],
        "title": "LivePositionValueRef",
        "type": "object"
      },
      "MacdIndicatorValueRef": {
        "additionalProperties": false,
        "description": "MACD \u2014 `indicator` selects the macd line, its signal line, or the histogram.\n\n``macd`` is ``EMA(fast) - EMA(slow)`` on close; ``macd_signal`` is an\nSMA-seeded EMA **of the MACD line**, not of price; ``macd_histogram`` is\n``macd - macd_signal``. The MACD line first exists after ``slow_period``\nbars have been seen, at zero-based index ``slow_period - 1``. The signal\nline and histogram first exist after ``slow_period + signal_period - 1``\nbars have been seen, at zero-based index ``slow_period + signal_period - 2``.\nEach line is NaN before its readiness point.",
        "properties": {
          "fast_period": {
            "maximum": 500,
            "minimum": 1,
            "title": "Fast Period",
            "type": "integer"
          },
          "indicator": {
            "enum": [
              "macd",
              "macd_signal",
              "macd_histogram"
            ],
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "signal_period": {
            "maximum": 500,
            "minimum": 1,
            "title": "Signal Period",
            "type": "integer"
          },
          "slow_period": {
            "maximum": 500,
            "minimum": 2,
            "title": "Slow Period",
            "type": "integer"
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "indicator",
          "fast_period",
          "slow_period",
          "signal_period"
        ],
        "title": "MacdIndicatorValueRef",
        "type": "object"
      },
      "ManualWeights": {
        "additionalProperties": false,
        "description": "Assign an explicit fixed weight to each construction target.\n\nWeights must sum to 1.0 within a 0.001 tolerance (same rounding allowance\nused by ``Portfolio`` allocation validators); a plan is seeded from\n:meth:`normalised_weights`, which sums to exactly 1 (DEC-010). Universe callers key weights\nby sleeve/symbol; member-strategy portfolios key weights by strategy_id.\nUse this when you know the desired allocation up front and it doesn't\nchange with market signals.",
        "properties": {
          "kind": {
            "const": "manual",
            "default": "manual",
            "title": "Kind",
            "type": "string"
          },
          "weights": {
            "additionalProperties": {
              "type": "number"
            },
            "description": "Mapping of target key \u2192 target weight fraction. Must contain at least one entry. Values must sum to 1.0 (\u00b10.001 tolerance). Example: {'BTC-USD': 0.6, 'ETH-USD': 0.4} for a universe or {'strategy-a': 0.6, 'strategy-b': 0.4} for a portfolio.",
            "minProperties": 1,
            "title": "Weights",
            "type": "object"
          }
        },
        "required": [
          "weights"
        ],
        "title": "ManualWeights",
        "type": "object"
      },
      "Member": {
        "additionalProperties": false,
        "description": "A reference to a member strategy of a Portfolio.\n\nA thin pointer: it names the strategy and optionally pins a specific\ncompiled revision. It carries NO weights \u2014 capital allocation across\nmembers lives entirely in ``Portfolio.allocation``.",
        "properties": {
          "revision_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional pin to a specific compiled revision of the strategy",
            "title": "Revision Id"
          },
          "strategy_id": {
            "description": "ID of the member strategy",
            "title": "Strategy Id",
            "type": "string"
          }
        },
        "required": [
          "strategy_id"
        ],
        "title": "Member",
        "type": "object"
      },
      "MovingAverageValueRef": {
        "additionalProperties": false,
        "description": "Moving-average series use the same shape with the authored MA period range.",
        "properties": {
          "indicator": {
            "enum": [
              "ema",
              "sma",
              "wma",
              "vwma"
            ],
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "offset": {
            "default": 0,
            "maximum": 500,
            "minimum": 0,
            "title": "Offset",
            "type": "integer"
          },
          "period": {
            "maximum": 800,
            "minimum": 1,
            "title": "Period",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "indicator",
          "period"
        ],
        "title": "MovingAverageValueRef",
        "type": "object"
      },
      "NamedZoneValueRef": {
        "additionalProperties": false,
        "description": "A boundary of a named strategy-level zone: its `upper`, `lower`, or derived `mid`.\n\n``mid`` is computed as ``(upper + lower) / 2`` at read time and is not a\nstored field. Zone boundaries may themselves be anchor refs, in which case\nthe whole zone reads NaN until that anchor fires. Referencing an undeclared\n``zone_id`` fails at compile time. Does not accept ``resolution``.",
        "properties": {
          "kind": {
            "const": "named_zone",
            "default": "named_zone",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          },
          "zone_field": {
            "$ref": "#/$defs/ZoneLevel"
          },
          "zone_id": {
            "title": "Zone Id",
            "type": "string"
          }
        },
        "required": [
          "zone_id",
          "zone_field"
        ],
        "title": "NamedZoneValueRef",
        "type": "object"
      },
      "NoRebalance": {
        "additionalProperties": false,
        "description": "Never rebalance \u2014 weights are set once at strategy start and held.\n\nThis is the default when ``rebalance`` is ``None`` on a universe strategy.",
        "properties": {
          "kind": {
            "const": "none",
            "default": "none",
            "title": "Kind",
            "type": "string"
          },
          "min_interval_bars": {
            "default": 0,
            "description": "Minimum number of bars that must elapse between two consecutive rebalances, regardless of the trigger. 0 = no minimum (rebalance fires whenever the schedule or drift threshold fires). Use this to prevent thrashing on high-frequency drift triggers.",
            "minimum": 0,
            "title": "Min Interval Bars",
            "type": "integer"
          }
        },
        "title": "NoRebalance",
        "type": "object"
      },
      "NotCondition": {
        "additionalProperties": false,
        "description": "Logical NOT -- inverts the inner condition.\n\nOver a reference that has no value on the bar (an indicator still warming\nup, an opening range before its window) the inner condition is unknown, and\nso is its negation: ``not`` takes no action there rather than firing.",
        "properties": {
          "child_name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Child Name"
          },
          "condition": {
            "$ref": "#/$defs/Condition"
          },
          "kind": {
            "const": "not",
            "default": "not",
            "title": "Kind",
            "type": "string"
          }
        },
        "required": [
          "condition"
        ],
        "title": "NotCondition",
        "type": "object"
      },
      "OBVIndicatorValueRef": {
        "additionalProperties": false,
        "description": "On-balance volume \u2014 running sum of volume signed by the close-to-close direction.\n\nAn unchanged close contributes nothing (neither added nor subtracted). NaN\non the very first bar, since there is no prior close. Like ``ad`` this is\ncumulative from the start of loaded history, so its absolute level is\nmeaningless \u2014 compare it to its own average or slope, not to a constant.",
        "properties": {
          "indicator": {
            "const": "obv",
            "default": "obv",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "OBVIndicatorValueRef",
        "type": "object"
      },
      "OTECondition": {
        "additionalProperties": false,
        "description": "Optimal Trade Entry -- Fibonacci retracement zone between swing points.\n\nCreates a zone between two Fibonacci levels (default 61.8%-78.6%) of the\nmost recent swing high to swing low range. Entry triggers when price\nretraces into this zone.",
        "properties": {
          "direction": {
            "$ref": "#/$defs/PatternBias",
            "default": "both"
          },
          "expires_after_bars": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": 100,
            "description": "Zone expiry in bars",
            "title": "Expires After Bars"
          },
          "fib_lower": {
            "default": 0.786,
            "description": "Lower fib level (deeper retracement)",
            "ge": 0.0,
            "le": 1.0,
            "title": "Fib Lower",
            "type": "number"
          },
          "fib_upper": {
            "default": 0.618,
            "description": "Upper fib level (closer to origin, shallower retracement)",
            "ge": 0.0,
            "le": 1.0,
            "title": "Fib Upper",
            "type": "number"
          },
          "fill_frac": {
            "default": 0.5,
            "description": "Fill percentage (0-1) at which zone is considered filled",
            "ge": 0.0,
            "le": 1.0,
            "title": "Fill Frac",
            "type": "number"
          },
          "kind": {
            "const": "ote",
            "default": "ote",
            "title": "Kind",
            "type": "string"
          },
          "select": {
            "$ref": "#/$defs/ZoneSelection",
            "default": "any",
            "description": "How to pick among matching zones at trigger time. 'any' (default) fires when any zone overlaps the bar. 'nearest'/'most_recent'/'oldest' deterministically pick one zone \u2014 required when binding execution price via TriggeringZonePriceSpec (VIB-591)."
          },
          "swing_strength": {
            "default": 5,
            "description": "Bars on each side to confirm swing point",
            "maximum": 50,
            "minimum": 2,
            "title": "Swing Strength",
            "type": "integer"
          }
        },
        "title": "OTECondition",
        "type": "object"
      },
      "OrderBlockCondition": {
        "additionalProperties": false,
        "description": "Detect Order Block zones -- last opposing candle before a displacement move.\n\nTracks the most recent opposing candle (bearish before a bullish move, or vice\nversa) and, when a displacement candle fires, creates a zone from it. Entry\ntriggers when price returns to the zone.\n\n**What the DEFAULTS actually do -- weaker than textbook SMC.** With no optional\nfield set, \"displacement\" is literally ``close > open`` (bullish) or\n``close < open`` (bearish): ANY up/down bar qualifies, with no size, body or\nwick test. The zone spans the opposing candle's FULL high/low range including\nwicks, not its body. And the opposing-candle tracker is never consumed, so every\nlater up-bar re-arms a new zone from the same -- possibly arbitrarily old --\ncandle.\n\nTo get the canonical SMC reading, set any of ``use_wicks=False`` (body bounds),\n``min_body_frac`` (body as a fraction of range) or ``min_displacement_atr`` (body\nin ATR(14) multiples). Setting ANY of the three also switches on\nconsume-after-fire, so one setup yields one zone.",
        "properties": {
          "direction": {
            "$ref": "#/$defs/PatternBias",
            "default": "both"
          },
          "expires_after_bars": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": 200,
            "description": "Zone expiry in bars",
            "title": "Expires After Bars"
          },
          "fill_frac": {
            "default": 0.5,
            "description": "Fill percentage (0-1) at which zone is considered filled",
            "ge": 0.0,
            "le": 1.0,
            "title": "Fill Frac",
            "type": "number"
          },
          "kind": {
            "const": "order_block",
            "default": "order_block",
            "title": "Kind",
            "type": "string"
          },
          "min_body_frac": {
            "anyOf": [
              {
                "ge": 0.0,
                "le": 1.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional displacement-body filter. Require the displacement candle's body |close-open| to be at least this fraction of its full range (high-low). None disables the filter (default-preserving). Setting this also activates canonical-mode consume-after-fire.",
            "title": "Min Body Frac"
          },
          "min_displacement_atr": {
            "anyOf": [
              {
                "gt": 0.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional displacement strength filter, in ATR(14) multiples. The displacement candle body must satisfy |close-open| >= mult * ATR(14). None disables the filter (default-preserving). Setting this also activates canonical-mode consume-after-fire.",
            "title": "Min Displacement Atr"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Higher-timeframe override for zone lifecycle. Set to '4h' to detect OBs on 4H bars. None = strategy timeframe."
          },
          "select": {
            "$ref": "#/$defs/ZoneSelection",
            "default": "any",
            "description": "How to pick among matching zones at trigger time. 'any' (default) fires when any zone overlaps the bar. 'nearest'/'most_recent'/'oldest' deterministically pick one zone \u2014 required when binding execution price via TriggeringZonePriceSpec (VIB-591)."
          },
          "use_wicks": {
            "default": true,
            "description": "Zone bounds source for the opposing candle. Default True preserves current behavior (full high/low including wicks). False switches to canonical SMC body bounds (max(open,close)/min(open,close)) and activates consume-after-fire so only one zone fires per setup.",
            "title": "Use Wicks",
            "type": "boolean"
          }
        },
        "title": "OrderBlockCondition",
        "type": "object"
      },
      "PatternBias": {
        "enum": [
          "bullish",
          "bearish",
          "both"
        ],
        "type": "string"
      },
      "PatternName": {
        "enum": [
          "hammer",
          "inverted_hammer",
          "shooting_star",
          "doji",
          "dragonfly_doji",
          "gravestone_doji",
          "spinning_top",
          "marubozu",
          "bullish_engulfing",
          "bearish_engulfing",
          "harami",
          "harami_cross",
          "inside_bar",
          "morning_star",
          "evening_star",
          "piercing_line",
          "dark_cloud_cover",
          "three_white_soldiers",
          "three_black_crows"
        ],
        "type": "string"
      },
      "PctOffsetSpec": {
        "additionalProperties": false,
        "description": "Percentage offset from the signal bar's close price.\n\nThe limit/stop price is computed as: close * (1 + pct/100).\nFor example, pct=-0.5 means 0.5% below close.",
        "properties": {
          "kind": {
            "const": "pct_offset",
            "default": "pct_offset",
            "title": "Kind",
            "type": "string"
          },
          "pct": {
            "description": "Percentage offset. -0.5 means 0.5% below close.",
            "exclusiveMinimum": -100,
            "title": "Pct",
            "type": "number"
          }
        },
        "required": [
          "pct"
        ],
        "title": "PctOffsetSpec",
        "type": "object"
      },
      "PennantPatternCondition": {
        "additionalProperties": false,
        "description": "Pennant chart pattern detection.\n\nA pennant is a strong directional move (pole) followed by converging trendlines\n(pennant). Breakout from the pennant continues the pole direction.",
        "properties": {
          "consolidation_bars": {
            "maximum": 100,
            "minimum": 2,
            "title": "Consolidation Bars",
            "type": "integer"
          },
          "direction": {
            "enum": [
              "up",
              "down",
              "same"
            ],
            "title": "Direction",
            "type": "string"
          },
          "kind": {
            "const": "pennant_pattern",
            "default": "pennant_pattern",
            "title": "Kind",
            "type": "string"
          },
          "min_momentum_pct": {
            "default": 2.0,
            "ge": 0.5,
            "le": 20.0,
            "title": "Min Momentum Pct",
            "type": "number"
          },
          "momentum_bars": {
            "maximum": 100,
            "minimum": 1,
            "title": "Momentum Bars",
            "type": "integer"
          }
        },
        "required": [
          "momentum_bars",
          "consolidation_bars",
          "direction"
        ],
        "title": "PennantPatternCondition",
        "type": "object"
      },
      "PercentileValueRef": {
        "additionalProperties": false,
        "description": "Percentile RANK of the current bar's `field` (or of any `source` value) within the trailing `lookback_bars` window.\n\nReturns ``100 * (values strictly below the current one) / (lookback_bars - 1)``\nover a window that **includes the current bar**: a new window high reads\n100, a new window low reads 0. Ties are not counted, so a perfectly flat\nwindow reads 0.\n\n**This is the inverse of** ``rolling_stats(stat=\"percentile\")``, which\nreturns the *value* sitting at a given percentile level. Use this ref to\nask \"how extreme is price right now\", and ``rolling_stats`` to ask \"what\nprice is the 90th percentile\". NaN propagates: any missing value in the\nwindow returns NaN.\n\n``source`` ranks any value ref rather than a price field, so \"is the volume\nunusually high\" or \"is the band width unusually narrow\" is one operand:\n``lookback_bars`` (2 to 500) is the window the current value is ranked in.\nEvery bar in the window is evaluated, so a long window over a nested\nexpression costs more than a price field does.\n\nExample, the percentile of the Bollinger band width over 100 bars:\n  {\"kind\": \"percentile\", \"lookback_bars\": 100,\n   \"source\": {\"kind\": \"binary_expr\", \"op\": \"-\",\n              \"left\": {\"kind\": \"indicator\", \"indicator\": \"bollinger\", \"output\": \"upper\"},\n              \"right\": {\"kind\": \"indicator\", \"indicator\": \"bollinger\", \"output\": \"lower\"}}}",
        "properties": {
          "field": {
            "anyOf": [
              {
                "$ref": "#/$defs/PriceField"
              },
              {
                "type": "null"
              }
            ],
            "default": "close",
            "description": "Price field to rank (open, high, low or close). Mutually exclusive with `source`: when `source` is given there is no price field. Close when neither is given."
          },
          "kind": {
            "const": "percentile",
            "default": "percentile",
            "title": "Kind",
            "type": "string"
          },
          "lookback_bars": {
            "default": 100,
            "maximum": 500,
            "minimum": 2,
            "title": "Lookback Bars",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Any value ref to rank instead of a price field: an indicator, a volume, or an expression. Mutually exclusive with `field`. Its own resolution and symbol are honoured."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "PercentileValueRef",
        "type": "object"
      },
      "PeriodIndicatorValueRef": {
        "additionalProperties": false,
        "description": "Entry point for the single-period indicator family (ema, sma, rsi, atr, roc, ...).\n\n``period`` means whatever that indicator's textbook definition means, and\nthat differs across the family: ``sma``/``std``/``median`` use a strict\nN-bar window, while ``ema``, ``rsi`` and ``atr`` are SMA-seeded\nand then smoothed exponentially (Wilder for rsi/atr), keeping a\nresponse to data older than N bars. SMA-seeded EMA first exists after N\nbars seen (zero-based index N-1); RSI and ATR at index N.\n\n``roc`` returns a **ratio, not a percentage** \u2014 a 5% move reads ``0.05``,\nso a threshold of ``5`` means 500%. ``offset`` reads the indicator's own\nvalue N bars back, which is how you express \"this indicator is rising\".",
        "properties": {
          "indicator": {
            "enum": [
              "rsi",
              "atr",
              "roc",
              "cci",
              "volume_sma",
              "mfi",
              "cmf",
              "std",
              "var",
              "median"
            ],
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "offset": {
            "default": 0,
            "maximum": 500,
            "minimum": 0,
            "title": "Offset",
            "type": "integer"
          },
          "period": {
            "maximum": 500,
            "minimum": 2,
            "title": "Period",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "indicator",
          "period"
        ],
        "title": "PeriodIndicatorValueRef",
        "type": "object"
      },
      "PivotIndicatorValueRef": {
        "additionalProperties": false,
        "description": "Classic floor-trader pivot levels (P, S1-S3, R1-R3) from the PRIOR day's H/L/C.\n\nLevels are computed once per day and stay **constant for every bar of the\ncurrent day**, rolling forward only at the boundary \u2014 they are not\nrecomputed intraday. The boundary is the **UTC** calendar day, not the\nexchange session, which matters for crypto and for non-US venues. NaN until\none full prior day has completed.",
        "properties": {
          "indicator": {
            "enum": [
              "pivot_p",
              "pivot_s1",
              "pivot_s2",
              "pivot_s3",
              "pivot_r1",
              "pivot_r2",
              "pivot_r3"
            ],
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "indicator"
        ],
        "title": "PivotIndicatorValueRef",
        "type": "object"
      },
      "PortfolioAllocationAuthoring": {
        "additionalProperties": false,
        "description": "Existing portfolio modes; scores name declared shared signals.",
        "properties": {
          "capital_model": {
            "default": "partitioned",
            "enum": [
              "partitioned",
              "shared_pool"
            ],
            "title": "Capital Model",
            "type": "string"
          },
          "collection_risk": {
            "anyOf": [
              {
                "$ref": "#/$defs/CollectionRiskPolicy"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "constraints": {
            "anyOf": [
              {
                "$ref": "#/$defs/CollectionAuthoringConstraints"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "construction": {
            "anyOf": [
              {
                "discriminator": {
                  "mapping": {
                    "equal_weight": "#/$defs/EqualWeight",
                    "manual": "#/$defs/ManualWeights",
                    "member_signal_rotation": "#/$defs/PortfolioMemberSignalConstruction",
                    "rank_based": "#/$defs/PortfolioRankConstruction",
                    "trailing_return": "#/$defs/TrailingReturnRotation"
                  },
                  "propertyName": "kind"
                },
                "oneOf": [
                  {
                    "$ref": "#/$defs/EqualWeight"
                  },
                  {
                    "$ref": "#/$defs/ManualWeights"
                  },
                  {
                    "$ref": "#/$defs/PortfolioRankConstruction"
                  },
                  {
                    "$ref": "#/$defs/TrailingReturnRotation"
                  },
                  {
                    "$ref": "#/$defs/PortfolioMemberSignalConstruction"
                  }
                ],
                "required": [
                  "kind"
                ]
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Construction"
          },
          "rebalance": {
            "anyOf": [
              {
                "discriminator": {
                  "mapping": {
                    "calendar": "#/$defs/CalendarRebalance",
                    "none": "#/$defs/NoRebalance"
                  },
                  "propertyName": "kind"
                },
                "oneOf": [
                  {
                    "$ref": "#/$defs/NoRebalance"
                  },
                  {
                    "$ref": "#/$defs/CalendarRebalance"
                  }
                ],
                "required": [
                  "kind"
                ]
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Rebalance"
          }
        },
        "title": "PortfolioAllocationAuthoring",
        "type": "object"
      },
      "PortfolioCreateAuthoring": {
        "additionalProperties": false,
        "description": "Authorable portfolio fields; persistence and ownership are server-owned.",
        "properties": {
          "allocation": {
            "anyOf": [
              {
                "$ref": "#/$defs/PortfolioAllocationAuthoring"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "members": {
            "items": {
              "$ref": "#/$defs/Member"
            },
            "minItems": 1,
            "title": "Members",
            "type": "array"
          },
          "name": {
            "title": "Name",
            "type": "string"
          },
          "project_id": {
            "title": "Project Id",
            "type": "string"
          },
          "shared_signals": {
            "items": {
              "$ref": "#/$defs/SharedSignal"
            },
            "title": "Shared Signals",
            "type": "array"
          }
        },
        "required": [
          "name",
          "project_id",
          "members"
        ],
        "title": "PortfolioCreateAuthoring",
        "type": "object"
      },
      "PortfolioMemberSignalConstruction": {
        "additionalProperties": false,
        "description": "Rank members by the declared shared signal; member rules trade while\nrotation trims and tops up existing holdings.",
        "properties": {
          "kind": {
            "const": "member_signal_rotation",
            "title": "Kind",
            "type": "string"
          },
          "score_signal": {
            "description": "Name of a Portfolio.shared_signals entry to rank members by. Mutually exclusive with score_ref \u2014 set exactly one.",
            "minLength": 1,
            "title": "Score Signal",
            "type": "string"
          },
          "top_n": {
            "description": "Number of highest-ranked members to hold at each rebalance. The construction mode determines the ranking metric. Must be >= 1.",
            "minimum": 1,
            "title": "Top N",
            "type": "integer"
          }
        },
        "required": [
          "kind",
          "score_signal",
          "top_n"
        ],
        "title": "PortfolioMemberSignalConstruction",
        "type": "object"
      },
      "PortfolioRankConstruction": {
        "additionalProperties": false,
        "description": "Rank position-hold members by a declared shared signal.",
        "properties": {
          "exit_top_n": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional looser exit threshold for entry/exit hysteresis. When set, a sleeve already held stays held until it drops out of the top exit_top_n (not just top_n); a sleeve NOT currently held only enters once it reaches the top top_n. Must be strictly greater than top_n (a looser exit threshold). None (default) = no hysteresis \u2014 a single top_n cutoff applies to both entry and exit, matching today's behavior. Use this to reduce rank-boundary whipsaw churn (e.g. top_n=2, exit_top_n=3 on a 5-name basket approximates 'enter top 40%, exit top 60%').",
            "title": "Exit Top N"
          },
          "kind": {
            "const": "rank_based",
            "title": "Kind",
            "type": "string"
          },
          "score_signal": {
            "description": "Name of a ``Portfolio.shared_signals`` entry to rank this portfolio's MEMBERS by (VIB-2102). Mutually exclusive with ``score_ref`` \u2014 set exactly one. Use this on a members portfolio; use ``score_ref`` for a universe strategy.",
            "minLength": 1,
            "title": "Score Signal",
            "type": "string"
          },
          "top_n": {
            "description": "Number of top-ranked sleeves to hold long at each rebalance. Must be >= 1.",
            "minimum": 1,
            "title": "Top N",
            "type": "integer"
          }
        },
        "required": [
          "kind",
          "score_signal",
          "top_n"
        ],
        "title": "PortfolioRankConstruction",
        "type": "object"
      },
      "PortfolioUpdateAuthoring": {
        "additionalProperties": false,
        "description": "Omitted fields preserve state; allocation null clears; signal [] clears.",
        "properties": {
          "allocation": {
            "anyOf": [
              {
                "$ref": "#/$defs/PortfolioAllocationAuthoring"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "members": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/$defs/Member"
                },
                "minItems": 1,
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Members"
          },
          "name": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Name"
          },
          "project_id": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Project Id"
          },
          "shared_signals": {
            "anyOf": [
              {
                "items": {
                  "$ref": "#/$defs/SharedSignal"
                },
                "type": "array"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Shared Signals"
          }
        },
        "title": "PortfolioUpdateAuthoring",
        "type": "object"
      },
      "PositionMode": {
        "description": "Position policy mode.",
        "enum": [
          "single",
          "accumulate",
          "scale_in",
          "reverse"
        ],
        "title": "PositionMode",
        "type": "string"
      },
      "PositionPolicyConfig": {
        "additionalProperties": false,
        "description": "Rules for managing multiple entries into a position.\n\nModes:\n- single: One position at a time (default)\n- accumulate: Allow repeated entries of same size (DCA)\n- scale_in: Allow repeated entries with diminishing size (pyramiding)\n- reverse: single position that flips to the opposite side when the opposite entry group fires (bidirectional only)\n\n``max_positions`` is a per-sleeve lot cap: on a multi-symbol basket, each\ninstrument is its own sleeve and gets its own independent budget of\n``max_positions`` lots, so the effective ceiling across the whole basket\nis ``max_positions * number of instruments`` -- not ``max_positions``.\nTo cap concurrent positions across the whole basket instead, set\n``allocation.constraints.max_active_sleeves`` via ``builder_set_allocation``\n(a book-level cap, reachable from any basket regardless of construction\ntype; it routes internally to ``PortfolioPlan.max_positions``, which a\nstrategy author does not set directly).\n\nExamples:\n    PositionPolicyConfig(mode=\"accumulate\", max_positions=5, min_bars_between=10)\n    PositionPolicyConfig(mode=\"scale_in\", scale_factor=0.5, max_positions=3)",
        "properties": {
          "max_entries_per_day": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum entries per calendar day",
            "title": "Max Entries Per Day"
          },
          "max_positions": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum number of lots PER SLEEVE (null = unlimited). On a multi-symbol basket, each instrument is its own sleeve, so the effective ceiling across the whole basket is max_positions * number of instruments, not max_positions itself. To cap concurrent positions across the whole basket instead, set allocation.constraints.max_active_sleeves via builder_set_allocation (a book-level cap, reachable from any basket regardless of construction type).",
            "title": "Max Positions"
          },
          "max_total_entries": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Maximum total entries for the entire backtest/session. None = unlimited.",
            "title": "Max Total Entries"
          },
          "min_bars_between": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Minimum bars between entries (cooldown)",
            "title": "Min Bars Between"
          },
          "mode": {
            "$ref": "#/$defs/PositionMode",
            "default": "single",
            "description": "Position accumulation mode"
          },
          "scale_factor": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "maximum": 1,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "For scale_in: each entry is this fraction of previous (e.g., 0.5)",
            "title": "Scale Factor"
          }
        },
        "title": "PositionPolicyConfig",
        "type": "object"
      },
      "PriceField": {
        "description": "Price bar fields.",
        "enum": [
          "open",
          "high",
          "low",
          "close"
        ],
        "title": "PriceField",
        "type": "string"
      },
      "PriceValueRef": {
        "additionalProperties": false,
        "description": "A single OHLC field of the current bar, or of a bar `offset` bars back.\n\n``offset=0`` (the default) is the bar being evaluated. Reading past the\nstart of loaded history returns NaN rather than clamping to the first bar,\nand a NaN operand makes the enclosing compare false.",
        "properties": {
          "field": {
            "$ref": "#/$defs/PriceField",
            "default": "close"
          },
          "kind": {
            "const": "price",
            "default": "price",
            "title": "Kind",
            "type": "string"
          },
          "offset": {
            "default": 0,
            "maximum": 500,
            "minimum": 0,
            "title": "Offset",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "PriceValueRef",
        "type": "object"
      },
      "RangeCondition": {
        "additionalProperties": false,
        "description": "Interval test: ``subject`` is between ``low`` and ``high``, each bound's inclusivity stated separately.\n\nTrue on every bar the interval contains ``subject`` \u2014 a LEVEL condition, not\nan edge. Two bounds are what make this its own type rather than another\n``compare`` operator.\n\nPer-bound inclusivity is not decoration. ``[30, 70)`` \u2014 enter when RSI is at\nor above 30 but strictly below 70 \u2014 cannot be said with one shared flag, and\nthe two interval tests already inside the runtime disagree: a band's\n``inside`` level is strictly exclusive on both edges, a zone membership test\nis inclusive on both. Both are expressible here.\n\nSemantics:\n  - Bounds are resolved every bar, so they may be moving series (a band\n    edge, a moving average) as well as literals.\n  - If ``subject``, ``low`` or ``high`` has no value (indicator warmup,\n    undefined prior bar) the condition is unknown and takes no action --\n    the same rule ``compare`` uses, so ``not(range)`` does not fire either.\n  - Literal bounds are checked at construction: ``low`` above ``high``, or\n    ``low`` equal to ``high`` with either bound exclusive, is an empty\n    interval that could never fire, and is refused rather than shipped as a\n    zero-trade strategy.\n\nExamples:\n    RSI in the mid-band, high end excluded (``[30, 70)``):\n        {\"kind\": \"range\", \"subject\": {...rsi ref...}, \"low\": 30, \"high\": 70,\n         \"low_inclusive\": true, \"high_inclusive\": false}\n\n    Close inside a Bollinger band, both edges excluded:\n        {\"kind\": \"range\", \"subject\": {...close...},\n         \"low\": {...bollinger lower...}, \"high\": {...bollinger upper...},\n         \"low_inclusive\": false, \"high_inclusive\": false}\n\nFor a one-sided threshold use ``compare``; for membership in a discrete set\nuse ``in_set``; to fire once on entering the interval rather than on every\nbar inside it, wrap this in ``transition`` semantics via ``cross`` on the\nbound you care about.",
        "properties": {
          "high": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ],
            "description": "Upper bound: a value ref or a constant",
            "title": "High"
          },
          "high_inclusive": {
            "description": "True tests `subject <= high`; False tests `subject < high`. Required for the same reason as `low_inclusive`.",
            "title": "High Inclusive",
            "type": "boolean"
          },
          "kind": {
            "const": "range",
            "default": "range",
            "title": "Kind",
            "type": "string"
          },
          "low": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ],
            "description": "Lower bound: a value ref or a constant",
            "title": "Low"
          },
          "low_inclusive": {
            "description": "True tests `subject >= low`; False tests `subject > low`. Required: the two two-bound sites this replaces DISAGREE (`band_level: inside` is exclusive on both edges, zone membership is inclusive on both), so there is no default that is not a silent choice between them.",
            "title": "Low Inclusive",
            "type": "boolean"
          },
          "subject": {
            "$ref": "#/$defs/ValueRef",
            "description": "Value tested against the interval"
          }
        },
        "required": [
          "subject",
          "low",
          "high",
          "low_inclusive",
          "high_inclusive"
        ],
        "title": "RangeCondition",
        "type": "object"
      },
      "RankValueRef": {
        "additionalProperties": false,
        "description": "Cross-sectional rank of ``source`` among the universe's symbols on the current bar, 0 to 1.\n\nThe lowest symbol reads 0, the highest 1 (mid-rank for ties). With fewer than 2\nsymbols holding a value there is no rank: it is absent, so a comparison over it\nis unknown (not 0.5). ``source`` is evaluated once per symbol; it cannot carry a\n``symbol`` and cannot contain another cross-sectional operand. Requires a universe\nor portfolio strategy with two or more symbols.\n\nExample, the top tercile of the universe by 20-bar rate of change:\n  {\"kind\": \"rank\", \"source\": {\"kind\": \"indicator\", \"indicator\": \"roc\", \"period\": 20}}\ncompared with ``> 0.66``.",
        "properties": {
          "kind": {
            "const": "rank",
            "default": "rank",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ],
            "description": "Per-symbol value to rank across the universe on the current bar, e.g. an indicator or a price. It is evaluated for each symbol on its own data."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "source"
        ],
        "title": "RankValueRef",
        "type": "object"
      },
      "Rebalance": {
        "description": "How often the selector re-evaluates membership.",
        "enum": [
          "daily",
          "weekly",
          "monthly"
        ],
        "title": "Rebalance",
        "type": "string"
      },
      "RiskPolicy": {
        "additionalProperties": false,
        "description": "Strategy-level risk controls.\n\nThe daily-loss breaker is evaluated before any entry signal; the\nshort-equity floor is evaluated once per bar against account equity.\n\nAll fields are optional. If max_daily_loss_pct is not set,\nhalt_behavior and cooldown_bars are ignored (and must be defaults).\nshort_equity_floor_pct is independent of all three.\n\nExamples:\n    # Default: no daily-loss breaker, but a 30% short-equity floor\n    RiskPolicy()\n\n    # Halt at -5% daily loss, resume next day\n    RiskPolicy(max_daily_loss_pct=5.0)\n\n    # Tighter short-equity floor, no daily-loss breaker\n    RiskPolicy(short_equity_floor_pct=50.0)\n\n    # Deliberately unconstrained shorts (research runs only)\n    RiskPolicy(short_equity_floor_pct=None)\n\n    # Halt at -3% daily loss, require manual reset\n    RiskPolicy(max_daily_loss_pct=3.0, halt_behavior=HaltBehavior.hard)\n\n    # Halt at -5%, wait 10 bars after recovery before resuming\n    RiskPolicy(max_daily_loss_pct=5.0, cooldown_bars=10)",
        "properties": {
          "cooldown_bars": {
            "default": 0,
            "description": "Additional bars to wait after halt condition clears before resuming. 0 = resume immediately when the loss condition clears (soft) or never (hard).",
            "maximum": 1000,
            "minimum": 0,
            "title": "Cooldown Bars",
            "type": "integer"
          },
          "halt_behavior": {
            "$ref": "#/$defs/HaltBehavior",
            "default": "soft",
            "description": "What to do when limit is hit: soft (resume after the loss condition clears and cooldown elapses), hard (require manual reset/restart)"
          },
          "max_daily_loss_pct": {
            "anyOf": [
              {
                "description": "Halt new entries if daily P&L drops below -X%.",
                "maximum": 50.0,
                "minimum": 0.1,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Max Daily Loss Pct"
          },
          "short_equity_floor_pct": {
            "anyOf": [
              {
                "description": "Short-equity floor, in percent (30.0 = 30%). Force-closes ALL open positions when account equity falls below this percentage of short market value, e.g. a $100k short book with a 30.0 floor liquidates once equity drops under $30k. The denominator is SHORT market value only \u2014 long positions do not offset shorts. It exists to stop a runaway short \u2014 one with no working exit \u2014 from producing an unachievable loss that no real account could have sustained. Account-level ruin guard, NOT a substitute for a per-position exit: it fires once, flattens everything, and blocks re-entry for the rest of the run, so a strategy still needs stop_loss / trailing_stop to manage individual trades. Independent of max_daily_loss_pct: that breaker only halts new entries, this one closes positions. Applies to backtest AND paper trading. The breach is detected on a bar's close and the forced cover is a reduce-only MARKET order that fills at the NEXT bar's open (latency_bars=1), so price may gap further against the position \u2014 it caps exposure, not loss. The resulting trade carries exit_reason 'margin_call' in results.trades ('margin_call_unfilled' if the run ends before the cover fills), so a liquidation is distinguishable from a normal exit. Set to null ONLY for research runs that deliberately want the unconstrained number; null means no forced liquidation and losses may exceed 100%. 0 is not accepted \u2014 use null to disable.",
                "exclusiveMinimum": 0.0,
                "maximum": 100.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": 30.0,
            "title": "Short Equity Floor Pct"
          }
        },
        "title": "RiskPolicy",
        "type": "object"
      },
      "RollingMaxValueRef": {
        "additionalProperties": false,
        "description": "Highest value of `source` over the prior `lookback_bars` \u2014 **excludes the current bar**.\n\n``source`` accepts ANY value ref, not just a price field: an indicator, a\nspread, or a nested expression. That is what makes normalisations\ncomposable \u2014 e.g. a stochastic of the MACD line is\n``(macd - rolling_min(macd)) / (rolling_max(macd) - rolling_min(macd))``\nbuilt with ``binary_expr``, with no dedicated indicator type.\n\nTwo behaviours to design around, both deliberate:\n\n- **The current bar is excluded** (same convention as ``donchian``), so a\n  close-exceeds-max breakout is meaningful \u2014 the current bar cannot\n  contaminate its own threshold. For a stochastic you want an INCLUSIVE\n  window, so rebuild one with ``binary_expr``:\n  ``{\"kind\": \"binary_expr\", \"op\": \"max\", \"left\": <source>,\n     \"right\": {\"kind\": \"rolling_max\", \"source\": <source>,\n               \"lookback_bars\": N - 1}}``\n- **NaN propagates**: one missing value anywhere in the window returns NaN\n  (no silent zero-substitution while `source` is still warming up), and a\n  NaN operand makes the enclosing compare false. Indicators with their own\n  NaN-compacting buffers \u2014 ``srsi_k``, ``stochastic_k`` \u2014 do NOT behave\n  this way, which is why they are not redundant with this ref.",
        "properties": {
          "field": {
            "anyOf": [
              {
                "$ref": "#/$defs/PriceField"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "kind": {
            "const": "rolling_max",
            "default": "rolling_max",
            "title": "Kind",
            "type": "string"
          },
          "lookback_bars": {
            "default": 20,
            "maximum": 500,
            "minimum": 2,
            "title": "Lookback Bars",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Any value ref (indicator, price, spread, or a nested binary_expr) as a raw dict \u2014 typed `dict` only to avoid a circular reference in the ref union, and validated against the full union at parse time."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "RollingMaxValueRef",
        "type": "object"
      },
      "RollingMinValueRef": {
        "additionalProperties": false,
        "description": "Lowest value of `source` over the prior `lookback_bars` \u2014 **excludes the current bar**.\n\nThe mirror of ``rolling_max``; see that class for the composition pattern,\nthe inclusive-window workaround via ``binary_expr`` ``min``, and the\nNaN-propagation rule. ``source`` accepts any value ref, not just a price\nfield.",
        "properties": {
          "field": {
            "anyOf": [
              {
                "$ref": "#/$defs/PriceField"
              },
              {
                "type": "null"
              }
            ],
            "default": null
          },
          "kind": {
            "const": "rolling_min",
            "default": "rolling_min",
            "title": "Kind",
            "type": "string"
          },
          "lookback_bars": {
            "default": 20,
            "maximum": 500,
            "minimum": 2,
            "title": "Lookback Bars",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Any value ref (indicator, price, spread, or a nested binary_expr) as a raw dict \u2014 typed `dict` only to avoid a circular reference in the ref union, and validated against the full union at parse time."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "RollingMinValueRef",
        "type": "object"
      },
      "RollingStatsValueRef": {
        "additionalProperties": false,
        "description": "A rolling statistic of `source` over `lookback_bars` \u2014 mean, std, zscore, sum, count, rank, percentile or ema.\n\n``source`` accepts ANY value ref, including a nested ``binary_expr``, so\nthis is the general smoothing and normalisation primitive: an SMA of an\narbitrary expression is ``stat=\"mean\"``, and a rolling z-score of a spread\nis ``stat=\"zscore\"``. Combined with ``rolling_max``/``rolling_min`` it\nexpresses whole indicator families that have no dedicated type \u2014 the %K of\na stochastic over any series is a 3-bar ``\"mean\"`` of the normalised ratio.\n\n**NaN propagates**: one missing value in the window returns NaN, and a NaN\noperand makes the enclosing compare false. Purpose-built indicators that\ncompact their buffers to finite samples (``srsi_k``, ``stochastic_k``)\nsurvive undefined stretches that this ref does not, so they are not\nredundant with it.\n\n``percentile_level`` is required when ``stat=\"percentile\"`` and must be\nomitted otherwise.",
        "properties": {
          "kind": {
            "const": "rolling_stats",
            "default": "rolling_stats",
            "title": "Kind",
            "type": "string"
          },
          "lookback_bars": {
            "maximum": 1000,
            "minimum": 2,
            "title": "Lookback Bars",
            "type": "integer"
          },
          "percentile_level": {
            "anyOf": [
              {
                "ge": 0.0,
                "le": 100.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Percentile Level"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ],
            "description": "Value or expression to summarize."
          },
          "stat": {
            "enum": [
              "mean",
              "std",
              "zscore",
              "sum",
              "count",
              "rank",
              "percentile",
              "ema"
            ],
            "title": "Stat",
            "type": "string"
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "source",
          "lookback_bars",
          "stat"
        ],
        "title": "RollingStatsValueRef",
        "type": "object"
      },
      "Rule": {
        "additionalProperties": false,
        "description": "ConditionDefinition attachment within a strategy.\n\nUses a condition definition in a strategy role with role-specific settings.\nThis is an embedded sub-document, not a standalone Firestore document.\n\nRole-specific fields:\n- entry: direction (long/short)\n- exit: direction (optional long/short scope; omitted means both) and\n  size_frac (partial vs full liquidation)\n- gate: no additional fields",
        "properties": {
          "definition_id": {
            "description": "ConditionDefinition identifier",
            "title": "Definition Id",
            "type": "string"
          },
          "direction": {
            "anyOf": [
              {
                "enum": [
                  "long",
                  "short"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Trade direction for entries, or optional position-side scope for exits. An exit with no direction applies to both long and short positions.",
            "title": "Direction"
          },
          "enabled": {
            "default": true,
            "description": "Whether attachment is enabled",
            "title": "Enabled",
            "type": "boolean"
          },
          "label": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Human-readable label",
            "title": "Label"
          },
          "remainder_unprotected": {
            "anyOf": [
              {
                "type": "boolean"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Explicit permission to leave a partial stop's remainder without another protective exit.",
            "title": "Remainder Unprotected"
          },
          "role": {
            "description": "ConditionDefinition role: entry, gate, or exit",
            "enum": [
              "entry",
              "exit",
              "gate"
            ],
            "title": "Role",
            "type": "string"
          },
          "rule_id": {
            "description": "Persistent identity for this attachment",
            "pattern": "^att_[0-9a-f]{32}$",
            "title": "Rule Id",
            "type": "string"
          },
          "size_frac": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "maximum": 1,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Fraction of position to close, greater than 0 and at most 1 (exit only). None = full liquidation.",
            "title": "Size Frac"
          }
        },
        "required": [
          "rule_id",
          "definition_id",
          "role"
        ],
        "title": "Rule",
        "type": "object"
      },
      "SequenceCondition": {
        "additionalProperties": false,
        "description": "Ordered sequence -- steps must fire in order, each optionally within N bars.\n\nSet ``id`` to use this sequence with ``SequenceStepValueRef`` (VIB-792):\nthe id plus each step's id addresses the matched bars so downstream\nrefs can read the retest bar low, breakout bar high, etc.\n\nA bar on which the active step cannot be evaluated (an operand has no value\nyet, e.g. an opening range before its window) counts as a miss for the\nsequence's progress, and the sequence is UNKNOWN on that bar rather than\nfalse -- so ``not(sequence(...))`` takes no action until the data exists.",
        "properties": {
          "id": {
            "anyOf": [
              {
                "minLength": 1,
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Explicit sequence id for SequenceStepValueRef lookup. Must be unique within a strategy. Auto-generated when absent.",
            "title": "Id"
          },
          "kind": {
            "const": "sequence",
            "default": "sequence",
            "title": "Kind",
            "type": "string"
          },
          "steps": {
            "items": {
              "$ref": "#/$defs/ConditionSequenceStep"
            },
            "minItems": 1,
            "title": "Steps",
            "type": "array"
          }
        },
        "required": [
          "steps"
        ],
        "title": "SequenceCondition",
        "type": "object"
      },
      "SequenceStepValueRef": {
        "additionalProperties": false,
        "description": "Reference to a field of the bar that matched a named sequence step.\n\nAddress the bar that satisfied a specific step inside a specific\nSequenceCondition. Useful for \"stop at the retest bar's low\" in\nbreak-retest setups.\n\nLifecycle mirrors EntryBarValueRef: the snapshot is captured at step\nfire, preserved for the lifetime of the open position, cleared on\nposition close. NaN when no position is open or the step has not yet\nfired on the current match.\n\nFields:\n  - open / high / low / close: step-bar OHLC\n  - range: high - low\n  - body_high: max(open, close)\n  - body_low: min(open, close)",
        "properties": {
          "kind": {
            "const": "sequence_step",
            "default": "sequence_step",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "sequence_id": {
            "description": "Id of the target SequenceCondition.",
            "minLength": 1,
            "title": "Sequence Id",
            "type": "string"
          },
          "step_field": {
            "$ref": "#/$defs/EntryBarField"
          },
          "step_id": {
            "description": "Id of the step within the sequence.",
            "minLength": 1,
            "title": "Step Id",
            "type": "string"
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "sequence_id",
          "step_id",
          "step_field"
        ],
        "title": "SequenceStepValueRef",
        "type": "object"
      },
      "SessionValueRef": {
        "additionalProperties": false,
        "description": "Session-level value reference.\n\nDay-scoped mode (default): resolves against the full trading day in the\nsession timezone. field in {open, high, low, close, prior_close,\nbars_into_session, range, mid}.\n\nIntraday window mode: set ``window_start`` (HH:MM wall-clock in the\nsession timezone) and ``window_duration_minutes`` to aggregate OHLC\nacross a fixed intraday slot (e.g., Asian session 00:00+480, ORB\n09:30+30). Before the window opens each day: NaN. During the window:\nevolving aggregate. After close: frozen aggregate for the rest of the\nday; resets at the next day's window_start. Fields prior_close and\nbars_into_session are day-scope only (not valid with a window).",
        "properties": {
          "kind": {
            "const": "session",
            "default": "session",
            "title": "Kind",
            "type": "string"
          },
          "offset": {
            "anyOf": [
              {
                "maximum": 500,
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Bars back. Absent is the session extreme through the current bar; k >= 1 is the extreme through bar i-k, with no value on a session's first k bars. Only the day-scoped 'high' and 'low' accept it. A level the current bar can still move needs offset 1 to be crossed.",
            "title": "Offset"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "session_field": {
            "enum": [
              "open",
              "high",
              "low",
              "close",
              "prior_close",
              "bars_into_session",
              "range",
              "mid",
              "in_session"
            ],
            "title": "Session Field",
            "type": "string"
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          },
          "window_duration_minutes": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Window Duration Minutes"
          },
          "window_start": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Intraday window start as HH:MM wall-clock in the session timezone (e.g., '09:30'). Requires window_duration_minutes.",
            "title": "Window Start"
          }
        },
        "required": [
          "session_field"
        ],
        "title": "SessionValueRef",
        "type": "object"
      },
      "SharedSignal": {
        "additionalProperties": false,
        "description": "A named portfolio-level cross-member metric, evaluated on each member's\nown primary symbol and made available to conditions and construction.",
        "properties": {
          "name": {
            "description": "Referenced by conditions + construction",
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "source": {
            "description": "Market-derived per-symbol metric (indicator / price / volume), evaluated on each member's own primary symbol.",
            "discriminator": {
              "mapping": {
                "indicator": "#/$defs/IndicatorValueRef",
                "price": "#/$defs/PriceValueRef",
                "volume": "#/$defs/VolumeValueRef"
              },
              "propertyName": "kind"
            },
            "oneOf": [
              {
                "$ref": "#/$defs/IndicatorValueRef"
              },
              {
                "$ref": "#/$defs/PriceValueRef"
              },
              {
                "$ref": "#/$defs/VolumeValueRef"
              }
            ],
            "required": [
              "kind"
            ],
            "title": "Source"
          }
        },
        "required": [
          "name",
          "source"
        ],
        "title": "SharedSignal",
        "type": "object"
      },
      "SharedSignalValueRef": {
        "additionalProperties": false,
        "description": "Reference to a portfolio-level shared signal by name (VIB-2102).\n\nResolves only inside a multi-member portfolio that declares a matching\n``shared_signals`` entry; bound to a member-local metric at portfolio\ncompile time. Illegal in a standalone strategy.",
        "properties": {
          "kind": {
            "const": "shared_signal",
            "default": "shared_signal",
            "title": "Kind",
            "type": "string"
          },
          "name": {
            "minLength": 1,
            "title": "Name",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "name"
        ],
        "title": "SharedSignalValueRef",
        "type": "object"
      },
      "SiblingValueRef": {
        "additionalProperties": false,
        "description": "The value of ``source`` on another symbol of the universe, on the current bar.\n\n``symbol`` must be a member of the strategy's universe; one outside it never has\na value, so such a strategy is refused when it is compiled. ``source`` is\nevaluated on that symbol's own data, not this one's; it cannot carry a ``symbol``\nand cannot contain another cross-sectional operand. Requires a universe or\nportfolio strategy with two or more symbols.\n\nExample, QQQ's close, to compare this symbol's close with:\n  {\"kind\": \"sibling\", \"symbol\": \"QQQ\", \"source\": {\"kind\": \"price\", \"field\": \"close\"}}",
        "properties": {
          "kind": {
            "const": "sibling",
            "default": "sibling",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ],
            "description": "Value read on the sibling's own bars and indicators, independent of this symbol's data."
          },
          "symbol": {
            "description": "Symbol of the sibling in the strategy's universe whose value is read, e.g. 'QQQ' when the universe is ['SPY', 'QQQ', 'IWM'].",
            "minLength": 1,
            "title": "Symbol",
            "type": "string"
          }
        },
        "required": [
          "symbol",
          "source"
        ],
        "title": "SiblingValueRef",
        "type": "object"
      },
      "SignalProportional_IndicatorValueRef_": {
        "additionalProperties": false,
        "properties": {
          "kind": {
            "const": "signal_proportional",
            "default": "signal_proportional",
            "title": "Kind",
            "type": "string"
          },
          "score_ref": {
            "$ref": "#/$defs/IndicatorValueRef",
            "description": "RAW per-sleeve metric evaluated for each sleeve at rebalance time. Each sleeve's weight = score / sum(scores). Negative scores are clamped to zero before normalisation. Must NOT be a cross-sectional ref (RankRef / ZScoreRef / percentile / sibling) \u2014 the constructor performs the cross-sectional normalisation itself."
          }
        },
        "required": [
          "score_ref"
        ],
        "title": "SignalProportional[IndicatorValueRef]",
        "type": "object"
      },
      "SizingConfig": {
        "additionalProperties": false,
        "description": "How much capital to deploy per trade.\n\nModes:\n- pct_equity: allocate a fraction of portfolio equity (default 95%)\n- fixed_usd: invest a fixed USD amount per entry\n- fixed_units: buy a fixed number of units per entry\n- fixed_risk_pct: risk a fixed percentage of equity per trade (requires stop loss)\n\nExamples:\n    SizingConfig()                                   # 95% equity (default)\n    SizingConfig(mode=\"fixed_usd\", fixed_usd=1000)   # $1000 per trade\n    SizingConfig(mode=\"pct_equity\", allocation=0.5)   # 50% equity\n    SizingConfig(mode=\"fixed_risk_pct\", risk_pct=2.0)  # Risk 2% equity per trade\n\n``headroom_pct`` reserves a slice of buying power to absorb signal->fill price\ndrift. It is the supported way to run near 100% allocation: prefer\n``allocation=1.0`` with headroom over quietly picking ``allocation=0.95``, because\nthe former says what you mean (deploy everything, reserve a margin for the gap)\nand the reserve is released into the position when the gap actually occurs.\n\nNote (VIB-1174): ``pct_equity`` sizes off CURRENT equity, so it compounds \u2014\nthe per-trade allocation grows after winning streaks and shrinks after losing\nones. ``fixed_usd`` is a constant notional regardless of equity. A ``pct_equity``\nand a ``fixed_usd`` config sized to match will produce the SAME first trade but\nDIVERGE thereafter as equity floats; account for this when comparing sizing\nmodes in a sweep (the P&L difference is the compounding effect, not the strategy).",
        "properties": {
          "allocation": {
            "default": 0.95,
            "description": "Fraction of equity per entry when mode=pct_equity: greater than 0 and at most 1.0. Spot only -- above 1.0 is leverage, which the platform does not support, and is refused here rather than silently clamped to ~100% at fill time. For full deployment use allocation=1.0 with headroom_pct.",
            "title": "Allocation",
            "type": "number"
          },
          "fixed_units": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Number of units when mode=fixed_units",
            "title": "Fixed Units"
          },
          "fixed_usd": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "USD amount when mode=fixed_usd",
            "title": "Fixed Usd"
          },
          "formula": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "ValueRef formula resolving to a USD amount or unit count per bar when mode=formula (VIB-751)."
          },
          "formula_fallback": {
            "const": "skip",
            "default": "skip",
            "description": "Behavior when formula returns NaN (e.g. indicator warmup). 'skip' = no entry (VIB-1237: only 'skip' is supported).",
            "title": "Formula Fallback",
            "type": "string"
          },
          "formula_unit": {
            "default": "usd",
            "description": "How to interpret the formula result: 'usd' = notional USD, 'units' = share count",
            "enum": [
              "usd",
              "units"
            ],
            "title": "Formula Unit",
            "type": "string"
          },
          "headroom_pct": {
            "anyOf": [
              {
                "maximum": 100,
                "minimum": 0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Percentage of buying power (0-100, e.g. 2.0 for 2%) held back when sizing an entry, to absorb price drift between the bar the order is SIZED on and the bar it FILLS on (market orders fill at the next bar's open). Without headroom an entry sized at ~100% of equity becomes unaffordable the moment the next bar opens higher: in a backtest it is silently reduced to fit, and at a live broker it is REJECTED outright. Headroom is not idle capital \u2014 it is consumed by the gap when the gap happens. It only binds near full deployment; at allocation 0.10 it costs nothing. Leave unset to use the platform default (0.25%, matching QuantConnect/LEAN's FreePortfolioValuePercentage); raise it when entries are being reduced or rejected -- 2-5% suits gap-prone names and full-allocation strategies.",
            "title": "Headroom Pct"
          },
          "max_usd": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Cap notional USD \u2014 clamp order if above this",
            "title": "Max Usd"
          },
          "min_usd": {
            "anyOf": [
              {
                "minimum": 0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Floor notional USD \u2014 skip order if below this",
            "title": "Min Usd"
          },
          "mode": {
            "$ref": "#/$defs/SizingMode",
            "default": "pct_equity",
            "description": "Sizing mode"
          },
          "risk_pct": {
            "anyOf": [
              {
                "exclusiveMinimum": 0,
                "maximum": 100,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Percentage of equity to risk per trade when mode=fixed_risk_pct",
            "title": "Risk Pct"
          }
        },
        "title": "SizingConfig",
        "type": "object"
      },
      "SizingMode": {
        "description": "Position sizing mode for entries.\n\nstr inheritance ensures backward compatibility:\n- SizingMode.PCT_EQUITY == \"pct_equity\" is True\n- model_dump() emits the string value\n- JSON deserialization works transparently",
        "enum": [
          "pct_equity",
          "fixed_usd",
          "fixed_units",
          "fixed_risk_pct",
          "formula"
        ],
        "title": "SizingMode",
        "type": "string"
      },
      "SpreadCondition": {
        "additionalProperties": false,
        "description": "Trigger on spread or ratio deviation between two symbols.\n\nCalculates ratio, difference, log-ratio, or z-score between two assets.\nUse for pairs trading, intermarket mean-reversion, or relative-value entries.",
        "properties": {
          "calc_type": {
            "default": "zscore",
            "description": "How to calculate the spread value",
            "enum": [
              "ratio",
              "difference",
              "log_ratio",
              "zscore"
            ],
            "title": "Calc Type",
            "type": "string"
          },
          "hedge_ratio": {
            "anyOf": [
              {
                "ge": 0.1,
                "le": 10.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Hedge ratio (default: 1.0 or rolling estimate)",
            "title": "Hedge Ratio"
          },
          "kind": {
            "const": "spread",
            "default": "spread",
            "title": "Kind",
            "type": "string"
          },
          "symbol_a": {
            "description": "First symbol in spread (numerator)",
            "title": "Symbol A",
            "type": "string"
          },
          "symbol_b": {
            "description": "Second symbol in spread (denominator)",
            "title": "Symbol B",
            "type": "string"
          },
          "threshold": {
            "default": 2.0,
            "description": "Threshold value for trigger",
            "title": "Threshold",
            "type": "number"
          },
          "trigger_op": {
            "default": "above",
            "description": "Trigger when spread is above/below threshold",
            "enum": [
              "above",
              "below",
              "crosses_above",
              "crosses_below"
            ],
            "title": "Trigger Op",
            "type": "string"
          },
          "window_bars": {
            "default": 100,
            "description": "Lookback for rolling calculations",
            "maximum": 1000,
            "minimum": 10,
            "title": "Window Bars",
            "type": "integer"
          }
        },
        "required": [
          "symbol_a",
          "symbol_b"
        ],
        "title": "SpreadCondition",
        "type": "object"
      },
      "SrsiIndicatorValueRef": {
        "additionalProperties": false,
        "description": "Stochastic RSI \u2014 the stochastic formula applied to RSI values, not to price.\n\n``period`` is used twice: it is both the RSI period and the lookback of the\nstochastic applied over it. ``srsi_k`` is the raw %K smoothed by\n``k_period``; ``srsi_d`` smooths that again by ``d_period``.\n\n**Range is 0-100, not 0-1** \u2014 ``100 * (rsi - lowest_rsi) / rsi_range``,\nthe pandas-ta/TA-Lib convention and the same scale as this platform's own\n``rsi`` and ``stochastic_k``. So \"deeply oversold\" is ``<= 5``, NOT\n``<= 0.05``; a 0-1 threshold makes the condition silently almost-always or\nalmost-never true instead of erroring. Measured on SPY 1m Q1 2025:\n``>= 50`` fires 50.8% of bars, ``>= 95`` fires 10.2%, ``>= 0.95`` fires\n95.5%.\n\n**Not equivalent to the same shape built from `rolling_stats`/`rolling_max`\nover an `rsi` ref**, for two reasons. The scale is the big one: the generic\ncomposition returns 0-1, this returns 0-100, so identical thresholds mean\ndifferent things. Second, the lookback here is the last ``period``\n**finite** RSI samples \u2014 undefined RSI bars are skipped rather than\nadmitted to the window \u2014 so it survives flat stretches where the generic\ncomposition propagates NaN.",
        "properties": {
          "d_period": {
            "default": 3,
            "maximum": 100,
            "minimum": 1,
            "title": "D Period",
            "type": "integer"
          },
          "indicator": {
            "enum": [
              "srsi_k",
              "srsi_d"
            ],
            "title": "Indicator",
            "type": "string"
          },
          "k_period": {
            "default": 3,
            "maximum": 100,
            "minimum": 1,
            "title": "K Period",
            "type": "integer"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "period": {
            "maximum": 500,
            "minimum": 2,
            "title": "Period",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "indicator",
          "period"
        ],
        "title": "SrsiIndicatorValueRef",
        "type": "object"
      },
      "StochasticIndicatorValueRef": {
        "additionalProperties": false,
        "description": "Stochastic oscillator \u2014 `stochastic_k` (smoothed %K) or `stochastic_d` (%D).\n\nRaw %K is ``100 * (close - lowest_low) / (highest_high - lowest_low)`` over\n``period`` bars **including the current bar** \u2014 the opposite convention to\n``rolling_max``/``rolling_min``, which exclude it. ``stochastic_k`` is\nalready SMA-smoothed over ``k_period`` (i.e. the slow %K, not raw %K), and\n``stochastic_d`` smooths that again over ``d_period``, so %D needs a\nfurther ``d_period`` bars before it is finite.\n\nA flat window (zero high-low range) yields ``0.0``, not NaN. This is a\npurpose-built indicator, not a shorthand for a ``rolling_max``/\n``rolling_min`` composition, which would use an exclusive window and\npropagate NaN instead.",
        "properties": {
          "d_period": {
            "default": 3,
            "maximum": 100,
            "minimum": 1,
            "title": "D Period",
            "type": "integer"
          },
          "indicator": {
            "enum": [
              "stochastic_k",
              "stochastic_d"
            ],
            "title": "Indicator",
            "type": "string"
          },
          "k_period": {
            "default": 3,
            "maximum": 100,
            "minimum": 1,
            "title": "K Period",
            "type": "integer"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "period": {
            "default": 14,
            "maximum": 500,
            "minimum": 2,
            "title": "Period",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "indicator"
        ],
        "title": "StochasticIndicatorValueRef",
        "type": "object"
      },
      "SupertrendIndicatorValueRef": {
        "additionalProperties": false,
        "description": "SuperTrend \u2014 `output=\"value\"` gives the active band price, `\"direction\"` gives +1/-1.\n\n``value`` is whichever band is currently active (lower band in an uptrend,\nupper band in a downtrend), so it **jumps discontinuously across the price\nevery time the trend flips** \u2014 it is a trailing stop level, not a smooth\nline, and a price-vs-value comparison changes meaning on each flip. Use\n``direction`` when you want trend state. Both are NaN until ``period``\nbars have been seen (Wilder ATR, SMA-seeded).",
        "properties": {
          "indicator": {
            "const": "supertrend",
            "default": "supertrend",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "multiplier": {
            "default": 3.0,
            "ge": 0.1,
            "le": 10.0,
            "title": "Multiplier",
            "type": "number"
          },
          "output": {
            "default": "value",
            "enum": [
              "value",
              "direction"
            ],
            "title": "Output",
            "type": "string"
          },
          "period": {
            "default": 10,
            "maximum": 500,
            "minimum": 2,
            "title": "Period",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "SupertrendIndicatorValueRef",
        "type": "object"
      },
      "SwingValueRef": {
        "additionalProperties": false,
        "description": "Price of a confirmed swing high/low \u2014 a bar whose extreme beats `strength` bars each side.\n\nConfirmation is **lagging by design**: a swing at bar N is not visible\nuntil bar ``N + strength``, because the bars to its right have to print\nfirst. That is what makes it lookahead-free, and it means the newest\nreadable swing is always at least ``strength`` bars old.\n\nThe comparison is strict, so a level matched exactly by a neighbouring bar\nnever forms a swing. ``offset`` counts back through confirmed swings\n(0 = most recent); typed absence if that many have not been confirmed yet.\nA comparison over that absent operand is UNKNOWN; the action boundary\ntakes no action.",
        "properties": {
          "kind": {
            "const": "swing",
            "default": "swing",
            "title": "Kind",
            "type": "string"
          },
          "offset": {
            "default": 0,
            "maximum": 20,
            "minimum": 0,
            "title": "Offset",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "strength": {
            "default": 5,
            "maximum": 50,
            "minimum": 1,
            "title": "Strength",
            "type": "integer"
          },
          "swing_type": {
            "enum": [
              "high",
              "low"
            ],
            "title": "Swing Type",
            "type": "string"
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          },
          "value_at_swing": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "The value to read at the swing bar. The swing itself is always found on PRICE (the bar high for a swing high, the bar low for a swing low); this chooses what is read there. Omitted means the swing's own price. Any value ref is accepted, and its own resolution and symbol are honoured."
          }
        },
        "required": [
          "swing_type"
        ],
        "title": "SwingValueRef",
        "type": "object"
      },
      "TimeValueRef": {
        "additionalProperties": false,
        "description": "Reference to the current bar's time field.\n\nVIB-1370 / VIB-1319: the sub-metric selector is named ``field`` across\nevery ValueRef-style type. The legacy name ``component`` was removed.\n\nCalendar/intraday fields: ``hour``, ``minute``, ``day_of_week`` (0=Mon),\n``day_of_month``, ``month`` (1=Jan), ``minutes_since_midnight``.\n\nSession-aware fields (use the strategy's session metadata):\n``minutes_to_close``, ``minutes_since_open``. Have no value for crypto (24h)\nand pre/post-market bars. A comparison over a missing value is unknown and\ntakes no action, negated or not: ``not(minutes_to_close <= 5)`` does not\nfire outside the session.",
        "properties": {
          "field": {
            "enum": [
              "hour",
              "minute",
              "day_of_week",
              "day_of_month",
              "month",
              "minutes_since_midnight",
              "minutes_to_close",
              "minutes_since_open"
            ],
            "title": "Field",
            "type": "string"
          },
          "kind": {
            "const": "time",
            "default": "time",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          },
          "timezone": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "IANA timezone (e.g. 'America/New_York'). None or 'UTC' = no conversion.",
            "title": "Timezone"
          }
        },
        "required": [
          "field"
        ],
        "title": "TimeValueRef",
        "type": "object"
      },
      "Timeframe": {
        "description": "Bar duration. These seven are the only granularities the data layer serves.",
        "enum": [
          "1m",
          "5m",
          "15m",
          "30m",
          "1h",
          "4h",
          "1d"
        ],
        "title": "Timeframe",
        "type": "string"
      },
      "TimestampAnchorSource": {
        "additionalProperties": false,
        "description": "Capture the first bar whose timestamp reaches the configured target.",
        "properties": {
          "kind": {
            "const": "timestamp",
            "default": "timestamp",
            "title": "Kind",
            "type": "string"
          },
          "timestamp": {
            "description": "ISO 8601 timestamp of the target bar",
            "title": "Timestamp",
            "type": "string"
          }
        },
        "required": [
          "timestamp"
        ],
        "title": "TimestampAnchorSource",
        "type": "object"
      },
      "TpTierSpec": {
        "additionalProperties": false,
        "description": "One tier in a multi-target take-profit ladder (VIB-1239).\n\npct = take-profit threshold (% from entry, ascending across tiers).\nsize_frac = fraction of the initial filled position closed at this tier.\nMulti-tier sum must equal 1.0; single-tier may carry size_frac<1.0 to\ncompose with attached trailing/SL exits.",
        "properties": {
          "pct": {
            "ge": 0.1,
            "le": 100.0,
            "title": "Pct",
            "type": "number"
          },
          "size_frac": {
            "gt": 0.0,
            "le": 1.0,
            "title": "Size Frac",
            "type": "number"
          }
        },
        "required": [
          "pct",
          "size_frac"
        ],
        "title": "TpTierSpec",
        "type": "object"
      },
      "TrackedValueRef": {
        "additionalProperties": false,
        "description": "Running highest or lowest value of ``source`` since the start of the run or since entry.\n\n``extreme`` chooses the maximum or the minimum and ``since`` the starting point.\nWith ``since: \"start\"`` (the default) it updates at the end of every bar, warm-up\nincluded, so a rule deciding at the close of bar t sees the extreme through bar t-1; a\nscheduled rule sees its frame bar included. With ``since: \"entry\"`` it is unset while\nflat, resets when a position opens from flat (not on a scale-in or a partial exit; a\nreversal opens from flat) and updates before decisions on each bar while invested, so a\nrule sees the extreme through the current bar. Absent values of ``source`` are skipped,\nand an unset value makes a comparison over it unknown. It keeps its state across a\npaper session's restarts. ``since: \"entry\"`` is refused in a signal scan, as every\noperation on the open position is.\n\nKnown gaps it inherits: a raw trailing ratchet built from it does not reset after it\nfires, ``since: \"entry\"`` folds in the whole bar of a mid-bar scheduled fill, and the\nreset runs only for the entry rule that filled. A ``since: \"entry\"`` value is refused\nanywhere inside a gate: a gate is evaluated while flat as well as invested, so a value\nthat resets at entry cannot be kept correct there. Use ``since: \"start\"``, or put the\ncondition on an exit. It returns the unit of ``source``.\n\nExample, the highest high since entry, to place a trailing exit under:\n  {\"kind\": \"tracked\", \"source\": {\"kind\": \"price\", \"field\": \"high\"}, \"extreme\": \"max\",\n   \"since\": \"entry\"}\ncompared with ``close`` using ``<``.",
        "properties": {
          "extreme": {
            "description": "'max' keeps the highest value of `source`, 'min' the lowest.",
            "enum": [
              "max",
              "min"
            ],
            "title": "Extreme",
            "type": "string"
          },
          "kind": {
            "const": "tracked",
            "default": "tracked",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "since": {
            "anyOf": [
              {
                "enum": [
                  "start",
                  "entry"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Where the extreme starts. 'start' (also when omitted) runs from the first delivered bar of the run. 'entry' is unset while flat, resets when a position opens from flat and runs while invested; it is refused in a signal scan and inside a gate (a gate is evaluated while flat too).",
            "title": "Since"
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ],
            "description": "Any value ref whose running extreme is kept, e.g. a price field, an indicator or an expression. It is evaluated every bar with its own resolution and symbol."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "source",
          "extreme"
        ],
        "title": "TrackedValueRef",
        "type": "object"
      },
      "TradeHistoryValueRef": {
        "additionalProperties": false,
        "description": "A statistic computed from the strategy's own closed-trade history.\n\n``field`` selects the metric: ``trade_count`` (closed trades so far),\n``consecutive_wins`` / ``consecutive_losses`` (current streak length),\n``last_pnl`` / ``last_pnl_pct`` (the most recently closed trade's PnL),\n``rolling_win_rate`` / ``rolling_avg_pnl_pct`` (win rate / average PnL%\nover the last ``lookback_bars`` closed trades \u2014 ``lookback_bars`` is REQUIRED for these\ntwo and forbidden for every other field, since it counts TRADES, not\nbars), or ``bars_since_last_exit``.\n\nBefore the first trade closes: ``trade_count``, ``consecutive_wins`` and\n``consecutive_losses`` are all-time counters and read ``0``. The other\nfive have no value yet -- a typed absence (``no_position``), not a number\n-- so a condition reading one is UNKNOWN and takes no action (neither\ntrue nor false), and a ``formula`` sizing over one is refused at compile\nbecause it could never size the first entry.\n\nVIB-1367 phase 4 / VIB-1319: the sub-metric selector is named ``field``\nacross every ValueRef-style type. The legacy name ``trade_metric`` was\nremoved.",
        "properties": {
          "field": {
            "enum": [
              "trade_count",
              "consecutive_wins",
              "consecutive_losses",
              "last_pnl",
              "last_pnl_pct",
              "rolling_win_rate",
              "rolling_avg_pnl_pct",
              "bars_since_last_exit"
            ],
            "title": "Field",
            "type": "string"
          },
          "kind": {
            "const": "trade_history",
            "default": "trade_history",
            "title": "Kind",
            "type": "string"
          },
          "lookback_bars": {
            "anyOf": [
              {
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Lookback Bars"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "field"
        ],
        "title": "TradeHistoryValueRef",
        "type": "object"
      },
      "TrailingReturnRotation": {
        "additionalProperties": false,
        "description": "Rotate capital across member strategies by ranking each member's own\ntrailing realized return over a lookback; hold the top_n.\n\nUnlike ``RankBased`` / ``SignalProportional`` (which score sleeves by a\nmarket ValueRef), this scores each member by its OWN realized sleeve NAV\nreturn \u2014 so it carries NO ``score_ref``. This is the member-rotation\nconstruction for a multi-strategy portfolio (VIB-2016).\n\n``partitioned`` capital model only \u2014 the weights are the per-member budget.\nDeploys like a basket: every member funds at its ``1/N`` slice until the\nfirst ranking, then each ranking trims benched members to zero and tops up\nheld, already-invested members to ``1/top_n`` of group NAV (a fresh entry\nsizes at that target too). The member still owns in/out \u2014 its own entries\nand exits fire on its own conditions, and a top-up is not gated by\n``position_policy`` (it is not an entry) \u2014 but the rotation, not the\nmember's own ``sizing``, owns how much it holds once ranked. Deployment is\n~fully invested (``1/1.0025`` regardless of N or top_n), not ``top_n/N``.",
        "properties": {
          "kind": {
            "const": "trailing_return",
            "default": "trailing_return",
            "title": "Kind",
            "type": "string"
          },
          "lookback_bars": {
            "description": "Number of trailing bars over which each member's realized return is measured for ranking. Must be > 0.",
            "exclusiveMinimum": 0,
            "title": "Lookback Bars",
            "type": "integer"
          },
          "metric": {
            "const": "return",
            "default": "return",
            "description": "Ranking metric. v1 supports only 'return' (the trailing realized return of the member's own NAV).",
            "title": "Metric",
            "type": "string"
          },
          "top_n": {
            "description": "Number of highest-ranked members to hold at each rebalance. The construction mode determines the ranking metric. Must be >= 1.",
            "minimum": 1,
            "title": "Top N",
            "type": "integer"
          }
        },
        "required": [
          "top_n",
          "lookback_bars"
        ],
        "title": "TrailingReturnRotation",
        "type": "object"
      },
      "TrailingStopCondition": {
        "additionalProperties": false,
        "description": "Trailing stop exit that follows the extreme price since entry.\n\nFires when price retraces from the highest high (long) or lowest low (short)\nsince entry by either atr_multiplier * ATR(atr_period) or trailing_pct percent \u2014 at\nmost one. Omit both to get the default atr_multiplier=2.0 over ATR(20). Use as the\nprimary exit for trend-following strategies.",
        "properties": {
          "activation_pct": {
            "anyOf": [
              {
                "ge": 0.1,
                "le": 100.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Minimum profit % before trailing stop activates. None = activate immediately on entry.",
            "title": "Activation Pct"
          },
          "atr_multiplier": {
            "anyOf": [
              {
                "ge": 0.5,
                "le": 10.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Atr Multiplier"
          },
          "atr_period": {
            "anyOf": [
              {
                "maximum": 500,
                "minimum": 1,
                "type": "integer"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "title": "Atr Period"
          },
          "kind": {
            "const": "trailing_stop",
            "default": "trailing_stop",
            "title": "Kind",
            "type": "string"
          },
          "trailing_pct": {
            "anyOf": [
              {
                "ge": 0.1,
                "le": 50.0,
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Trail distance as a percent of the extreme price since entry. The stop is live from the entry fill, at the fill price less this distance, then ratchets at each bar close. Mutually exclusive with atr_multiplier.",
            "title": "Trailing Pct"
          }
        },
        "title": "TrailingStopCondition",
        "type": "object"
      },
      "TransitionCondition": {
        "additionalProperties": false,
        "description": "Fires on the bar where ``source``'s value differs from the prior bar's value.\n\nOptionally constrained to a specific (from, to) pair. Intended for\ncategorical/discrete references such as ``supertrend.direction`` that\ntake a small set of values (e.g., -1 / +1).\n\nThe first bar ``source`` has a value is a baseline, not a change: the\ncondition fires on the first CHANGE it observes, never on bar 0 or on the\nbar a warming-up source first appears. A bar where ``source`` has no value is\nunknown (no action) and does not reset the last reading.\n\nExamples:\n    SuperTrend direction flip from bearish to bullish:\n        {\"kind\": \"transition\", \"source\": {...supertrend direction ref...},\n         \"from_value\": -1, \"to_value\": 1}\n\n    Any change in value:\n        {\"kind\": \"transition\", \"source\": {...}}",
        "properties": {
          "from_value": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Prior value constraint. None matches any prior value.",
            "title": "From Value"
          },
          "kind": {
            "const": "transition",
            "default": "transition",
            "title": "Kind",
            "type": "string"
          },
          "source": {
            "$ref": "#/$defs/ValueRef",
            "description": "Value to monitor for transitions"
          },
          "to_value": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Current value constraint. None matches any current value.",
            "title": "To Value"
          }
        },
        "required": [
          "source"
        ],
        "title": "TransitionCondition",
        "type": "object"
      },
      "TriggeringZonePriceSpec": {
        "additionalProperties": false,
        "description": "Use the *triggering* zone's level as the execution price (VIB-591).\n\nBinds execution price to the same zone that fired the entry's\nZoneCondition on the current bar. Avoids the decoupled-query problem\nwhere ZonePriceSpec can resolve to a different zone than the one\nthat triggered the signal.\n\nRequirements (enforced at compile time):\n- Entry condition must contain exactly one ZoneCondition node.\n- That ZoneCondition must use a deterministic selector\n  (mode != \"exists\", select != \"any\").\n- Only valid in ExecutionConfig limit_price/stop_price; not valid\n  in standing exit orders.",
        "properties": {
          "kind": {
            "const": "triggering_zone",
            "default": "triggering_zone",
            "title": "Kind",
            "type": "string"
          },
          "level": {
            "default": "mid",
            "description": "Zone price level to use",
            "enum": [
              "upper",
              "lower",
              "mid"
            ],
            "title": "Level",
            "type": "string"
          }
        },
        "title": "TriggeringZonePriceSpec",
        "type": "object"
      },
      "TriggeringZoneValueRef": {
        "additionalProperties": false,
        "description": "Reference to the zone that fired the entry's ZoneCondition (VIB-591).\n\nResolves to a level of the *triggering* zone \u2014 the zone selected by the\nentry's ZoneCondition on the signal bar. An immutable snapshot is captured\ninto ``TradeContext`` so post-entry references (e.g. a standing stop-loss\nbound to the FVG's lower wick) keep resolving to the same zone for the\ntrade's lifetime. The id is retained for persisted-state compatibility.\n\nReturns NaN when no triggering zone is bound (no entry condition with a\nrequired ZoneCondition fired) and no compatibility lookup is available.",
        "properties": {
          "kind": {
            "const": "triggering_zone",
            "default": "triggering_zone",
            "title": "Kind",
            "type": "string"
          },
          "level": {
            "$ref": "#/$defs/ZoneLevel",
            "default": "mid"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "TriggeringZoneValueRef",
        "type": "object"
      },
      "UnaryExprValueRef": {
        "additionalProperties": false,
        "description": "Unary expression over another ValueRef.\n\nWraps a single operand with an op from {abs, neg, log, log10, sqrt, pct_change}.\nCompiles to a unary IRExpression.",
        "properties": {
          "kind": {
            "const": "unary_expr",
            "default": "unary_expr",
            "title": "Kind",
            "type": "string"
          },
          "op": {
            "enum": [
              "abs",
              "neg",
              "log",
              "log10",
              "sqrt",
              "pct_change"
            ],
            "title": "Op",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ]
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "op",
          "source"
        ],
        "title": "UnaryExprValueRef",
        "type": "object"
      },
      "VWAPBandOutput": {
        "enum": [
          "upper",
          "middle",
          "lower",
          "std_dev"
        ],
        "type": "string"
      },
      "VWAPBandsValueRef": {
        "additionalProperties": false,
        "description": "VWAP Bands \u2014 stddev envelopes around anchored VWAP.\n\nOutputs:\n  - upper  = VWAP + mult * sigma\n  - middle = VWAP\n  - lower  = VWAP - mult * sigma\n  - std_dev = sigma itself, NOT multiplied by ``multiplier``\n\nwhere sigma is the volume-weighted std dev of typical price vs VWAP,\naccumulated since the last anchor reset (session/week/month).\nA distance from the VWAP in standard deviations is\n``(close - middle) / std_dev``, written with ``binary_expr``.",
        "properties": {
          "anchor": {
            "$ref": "#/$defs/AnchorPeriod",
            "default": "session"
          },
          "indicator": {
            "const": "vwap_bands",
            "default": "vwap_bands",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "multiplier": {
            "default": 2.0,
            "ge": 0.1,
            "le": 10.0,
            "title": "Multiplier",
            "type": "number"
          },
          "output": {
            "$ref": "#/$defs/VWAPBandOutput"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "output"
        ],
        "title": "VWAPBandsValueRef",
        "type": "object"
      },
      "VWAPIndicatorValueRef": {
        "additionalProperties": false,
        "description": "VWAP \u2014 anchored Volume-Weighted Average Price.\n\nResets at each anchor boundary (session/week/month). Use this ValueRef\nwhen you need the VWAP scalar as an operand in compare/cross conditions\n(e.g. ``close > vwap(session)``). For envelope/band semantics use\n``vwap_bands`` instead.\n\nMath: anchored cumulative volume-weighted typical price; zero-volume\nbars carry forward the prior VWAP value (no vol=1.0 substitution). See\n``docs/indicator-conventions.md``.",
        "properties": {
          "anchor": {
            "$ref": "#/$defs/AnchorPeriod",
            "default": "session"
          },
          "indicator": {
            "const": "vwap",
            "default": "vwap",
            "title": "Indicator",
            "type": "string"
          },
          "kind": {
            "const": "indicator",
            "default": "indicator",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "VWAPIndicatorValueRef",
        "type": "object"
      },
      "ValueRef": {
        "discriminator": {
          "mapping": {
            "anchor": "#/$defs/AnchorValueRef",
            "binary_expr": "#/$defs/BinaryExprValueRef",
            "constant": "#/$defs/ConstantValueRef",
            "entry_bar": "#/$defs/EntryBarValueRef",
            "equity": "#/$defs/EquityValueRef",
            "event_distance": "#/$defs/EventDistanceValueRef",
            "event_field": "#/$defs/EventFieldValueRef",
            "indicator": "#/$defs/IndicatorValueRef",
            "live_position": "#/$defs/LivePositionValueRef",
            "named_zone": "#/$defs/NamedZoneValueRef",
            "percentile": "#/$defs/PercentileValueRef",
            "price": "#/$defs/PriceValueRef",
            "rank": "#/$defs/RankValueRef",
            "rolling_max": "#/$defs/RollingMaxValueRef",
            "rolling_min": "#/$defs/RollingMinValueRef",
            "rolling_stats": "#/$defs/RollingStatsValueRef",
            "sequence_step": "#/$defs/SequenceStepValueRef",
            "session": "#/$defs/SessionValueRef",
            "shared_signal": "#/$defs/SharedSignalValueRef",
            "sibling": "#/$defs/SiblingValueRef",
            "swing": "#/$defs/SwingValueRef",
            "time": "#/$defs/TimeValueRef",
            "tracked": "#/$defs/TrackedValueRef",
            "trade_history": "#/$defs/TradeHistoryValueRef",
            "triggering_zone": "#/$defs/TriggeringZoneValueRef",
            "unary_expr": "#/$defs/UnaryExprValueRef",
            "volume": "#/$defs/VolumeValueRef",
            "xs_dispersion": "#/$defs/DispersionValueRef",
            "xs_zscore": "#/$defs/ZScoreValueRef"
          },
          "propertyName": "kind"
        },
        "oneOf": [
          {
            "$ref": "#/$defs/PriceValueRef"
          },
          {
            "$ref": "#/$defs/IndicatorValueRef"
          },
          {
            "$ref": "#/$defs/ConstantValueRef"
          },
          {
            "$ref": "#/$defs/AnchorValueRef"
          },
          {
            "$ref": "#/$defs/NamedZoneValueRef"
          },
          {
            "$ref": "#/$defs/TriggeringZoneValueRef"
          },
          {
            "$ref": "#/$defs/SwingValueRef"
          },
          {
            "$ref": "#/$defs/PercentileValueRef"
          },
          {
            "$ref": "#/$defs/RollingMaxValueRef"
          },
          {
            "$ref": "#/$defs/RollingMinValueRef"
          },
          {
            "$ref": "#/$defs/VolumeValueRef"
          },
          {
            "$ref": "#/$defs/EventFieldValueRef"
          },
          {
            "$ref": "#/$defs/TradeHistoryValueRef"
          },
          {
            "$ref": "#/$defs/EquityValueRef"
          },
          {
            "$ref": "#/$defs/LivePositionValueRef"
          },
          {
            "$ref": "#/$defs/SessionValueRef"
          },
          {
            "$ref": "#/$defs/TimeValueRef"
          },
          {
            "$ref": "#/$defs/EntryBarValueRef"
          },
          {
            "$ref": "#/$defs/SequenceStepValueRef"
          },
          {
            "$ref": "#/$defs/RollingStatsValueRef"
          },
          {
            "$ref": "#/$defs/UnaryExprValueRef"
          },
          {
            "$ref": "#/$defs/BinaryExprValueRef"
          },
          {
            "$ref": "#/$defs/SharedSignalValueRef"
          },
          {
            "$ref": "#/$defs/EventDistanceValueRef"
          },
          {
            "$ref": "#/$defs/RankValueRef"
          },
          {
            "$ref": "#/$defs/ZScoreValueRef"
          },
          {
            "$ref": "#/$defs/DispersionValueRef"
          },
          {
            "$ref": "#/$defs/SiblingValueRef"
          },
          {
            "$ref": "#/$defs/TrackedValueRef"
          }
        ],
        "required": [
          "kind"
        ]
      },
      "VolumeValueRef": {
        "additionalProperties": false,
        "description": "Traded volume of the current bar, or of a bar `offset` bars back.\n\nVolume is in **base-asset units** (shares, or coins for crypto) unless the\nrun is configured for quote units, in which case it is multiplied by that\nbar's close. Reading past the start of loaded history returns NaN.",
        "properties": {
          "kind": {
            "const": "volume",
            "default": "volume",
            "title": "Kind",
            "type": "string"
          },
          "offset": {
            "default": 0,
            "maximum": 500,
            "minimum": 0,
            "title": "Offset",
            "type": "integer"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "title": "VolumeValueRef",
        "type": "object"
      },
      "Weekday": {
        "enum": [
          "monday",
          "tuesday",
          "wednesday",
          "thursday",
          "friday",
          "saturday",
          "sunday"
        ],
        "type": "string"
      },
      "ZScoreValueRef": {
        "additionalProperties": false,
        "description": "Cross-sectional z-score of ``source`` among the universe's symbols on the current bar.\n\nHow many sample standard deviations this symbol's value sits from the universe\nmean. With fewer than 2 values, or when every symbol sits on the mean, there is no\nz-score: it is absent (not 0). ``source`` is evaluated once per symbol; it cannot\ncarry a ``symbol`` and cannot contain another cross-sectional operand. Requires a\nuniverse or portfolio strategy with two or more symbols.\n\nExample, how far this symbol's RSI is from the universe average:\n  {\"kind\": \"xs_zscore\", \"source\": {\"kind\": \"indicator\", \"indicator\": \"rsi\", \"period\": 14}}",
        "properties": {
          "kind": {
            "const": "xs_zscore",
            "default": "xs_zscore",
            "title": "Kind",
            "type": "string"
          },
          "resolution": {
            "anyOf": [
              {
                "$ref": "#/$defs/Timeframe"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional higher-timeframe override for this value ref. Set it inside left/right refs such as {'kind': 'indicator', ..., 'resolution': '4h'} or {'kind': 'price', 'field': 'close', 'resolution': '4h'}. Do not put timeframe/source_timeframe on the parent condition. None = strategy timeframe."
          },
          "source": {
            "anyOf": [
              {
                "$ref": "#/$defs/ValueRef"
              },
              {
                "type": "number"
              }
            ],
            "description": "Per-symbol value to standardise against the universe on the current bar. It is evaluated for each symbol on its own data."
          },
          "symbol": {
            "anyOf": [
              {
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional reference symbol this value ref reads from (e.g. 'SPY'). None = the traded/primary symbol. Mutually exclusive with resolution.",
            "title": "Symbol"
          }
        },
        "required": [
          "source"
        ],
        "title": "ZScoreValueRef",
        "type": "object"
      },
      "ZoneDefinition": {
        "additionalProperties": false,
        "description": "Named strategy-level price zone built from static levels or anchor refs.\n\nA zone exposes three read-time fields to `NamedZoneValueRef`: `upper`,\n`lower`, and `mid`. Only `upper` and `lower` are settable here; `mid` is\nauto-derived as `(upper + lower) / 2` at read time and must NOT be passed\nin \u2014 it is not a stored field.",
        "properties": {
          "id": {
            "description": "Unique zone identifier",
            "minLength": 1,
            "title": "Id",
            "type": "string"
          },
          "lower": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "$ref": "#/$defs/ConstantValueRef"
              },
              {
                "$ref": "#/$defs/AnchorValueRef"
              }
            ],
            "description": "Lower zone boundary as a static price, constant ref, or anchor ref",
            "title": "Lower"
          },
          "upper": {
            "anyOf": [
              {
                "type": "number"
              },
              {
                "$ref": "#/$defs/ConstantValueRef"
              },
              {
                "$ref": "#/$defs/AnchorValueRef"
              }
            ],
            "description": "Upper zone boundary as a static price, constant ref, or anchor ref",
            "title": "Upper"
          }
        },
        "required": [
          "id",
          "upper",
          "lower"
        ],
        "title": "ZoneDefinition",
        "type": "object"
      },
      "ZoneLevel": {
        "enum": [
          "upper",
          "lower",
          "mid"
        ],
        "type": "string"
      },
      "ZonePriceSpec": {
        "additionalProperties": false,
        "description": "Use a zone-registry level as the execution price.",
        "properties": {
          "direction": {
            "anyOf": [
              {
                "enum": [
                  "bullish",
                  "bearish"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional zone direction filter",
            "title": "Direction"
          },
          "kind": {
            "const": "zone",
            "default": "zone",
            "title": "Kind",
            "type": "string"
          },
          "level": {
            "default": "mid",
            "description": "Zone price level to use",
            "enum": [
              "upper",
              "lower",
              "mid"
            ],
            "title": "Level",
            "type": "string"
          },
          "select": {
            "default": "nearest",
            "description": "How to select among matching zones",
            "enum": [
              "nearest",
              "most_recent",
              "oldest"
            ],
            "title": "Select",
            "type": "string"
          },
          "zone_type": {
            "anyOf": [
              {
                "enum": [
                  "fvg",
                  "order_block",
                  "ote"
                ],
                "type": "string"
              },
              {
                "type": "null"
              }
            ],
            "default": null,
            "description": "Optional public zone type filter",
            "title": "Zone Type"
          }
        },
        "title": "ZonePriceSpec",
        "type": "object"
      },
      "ZoneSelection": {
        "enum": [
          "nearest",
          "most_recent",
          "oldest",
          "any"
        ],
        "type": "string"
      }
    },
    "$schema": "https://json-schema.org/draft/2020-12/schema",
    "roots": {
      "Condition": {
        "$ref": "#/$defs/Condition"
      },
      "Rule": {
        "$ref": "#/$defs/Rule"
      },
      "ValueRef": {
        "$ref": "#/$defs/ValueRef"
      },
      "condition:all_of": {
        "allOf": [
          {
            "$ref": "#/$defs/AllOfCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:always_true": {
        "allOf": [
          {
            "$ref": "#/$defs/AlwaysTrueCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:any_of": {
        "allOf": [
          {
            "$ref": "#/$defs/AnyOfCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:at_least": {
        "allOf": [
          {
            "$ref": "#/$defs/AtLeastCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:at_session": {
        "allOf": [
          {
            "$ref": "#/$defs/AtSessionCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:at_time": {
        "allOf": [
          {
            "$ref": "#/$defs/AtTimeCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:breakout_retest": {
        "allOf": [
          {
            "$ref": "#/$defs/BreakoutRetestCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:calendar_schedule": {
        "allOf": [
          {
            "$ref": "#/$defs/CalendarScheduleCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:candle_pattern": {
        "allOf": [
          {
            "$ref": "#/$defs/CandlePatternCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:compare": {
        "allOf": [
          {
            "$ref": "#/$defs/CompareCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:condition_ref": {
        "allOf": [
          {
            "$ref": "#/$defs/ConditionReference"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:consecutive": {
        "allOf": [
          {
            "$ref": "#/$defs/ConsecutiveCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:cross": {
        "allOf": [
          {
            "$ref": "#/$defs/CrossSignalCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:eod_flatten": {
        "allOf": [
          {
            "$ref": "#/$defs/EodFlattenCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:fixed_targets": {
        "allOf": [
          {
            "$ref": "#/$defs/FixedTargetsCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:flag_pattern": {
        "allOf": [
          {
            "$ref": "#/$defs/FlagPatternCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:fvg": {
        "allOf": [
          {
            "$ref": "#/$defs/FairValueGapCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:in_set": {
        "allOf": [
          {
            "$ref": "#/$defs/InSetCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:latch": {
        "allOf": [
          {
            "$ref": "#/$defs/LatchCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:liquidity_sweep": {
        "allOf": [
          {
            "$ref": "#/$defs/LiquiditySweepCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:not": {
        "allOf": [
          {
            "$ref": "#/$defs/NotCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:order_block": {
        "allOf": [
          {
            "$ref": "#/$defs/OrderBlockCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:ote": {
        "allOf": [
          {
            "$ref": "#/$defs/OTECondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:pennant_pattern": {
        "allOf": [
          {
            "$ref": "#/$defs/PennantPatternCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:range": {
        "allOf": [
          {
            "$ref": "#/$defs/RangeCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:sequence": {
        "allOf": [
          {
            "$ref": "#/$defs/SequenceCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:spread": {
        "allOf": [
          {
            "$ref": "#/$defs/SpreadCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:trailing_stop": {
        "allOf": [
          {
            "$ref": "#/$defs/TrailingStopCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "condition:transition": {
        "allOf": [
          {
            "$ref": "#/$defs/TransitionCondition"
          },
          {
            "$ref": "#/$defs/Condition"
          }
        ]
      },
      "config:allocation": {
        "$ref": "#/$defs/BasketAllocationAuthoring"
      },
      "config:collection_risk": {
        "$ref": "#/$defs/CollectionRiskPolicy"
      },
      "config:construction_constraints": {
        "$ref": "#/$defs/CollectionAuthoringConstraints"
      },
      "config:execution": {
        "$ref": "#/$defs/ExecutionConfig"
      },
      "config:portfolio_allocation": {
        "$ref": "#/$defs/PortfolioAllocationAuthoring"
      },
      "config:position_policy": {
        "$ref": "#/$defs/PositionPolicyConfig"
      },
      "config:rebalance": {
        "discriminator": {
          "mapping": {
            "calendar": "#/$defs/CalendarRebalance",
            "none": "#/$defs/NoRebalance"
          },
          "propertyName": "kind"
        },
        "oneOf": [
          {
            "$ref": "#/$defs/NoRebalance"
          },
          {
            "$ref": "#/$defs/CalendarRebalance"
          }
        ],
        "required": [
          "kind"
        ]
      },
      "config:risk": {
        "$ref": "#/$defs/RiskPolicy"
      },
      "config:sizing": {
        "$ref": "#/$defs/SizingConfig"
      },
      "construction:basket": {
        "discriminator": {
          "mapping": {
            "equal_weight": "#/$defs/EqualWeight",
            "manual": "#/$defs/ManualWeights",
            "rank_based": "#/$defs/BasketRankConstruction",
            "signal_proportional": "#/$defs/SignalProportional_IndicatorValueRef_"
          },
          "propertyName": "kind"
        },
        "oneOf": [
          {
            "$ref": "#/$defs/EqualWeight"
          },
          {
            "$ref": "#/$defs/ManualWeights"
          },
          {
            "$ref": "#/$defs/BasketRankConstruction"
          },
          {
            "$ref": "#/$defs/SignalProportional_IndicatorValueRef_"
          }
        ],
        "required": [
          "kind"
        ]
      },
      "construction:portfolio": {
        "discriminator": {
          "mapping": {
            "equal_weight": "#/$defs/EqualWeight",
            "manual": "#/$defs/ManualWeights",
            "member_signal_rotation": "#/$defs/PortfolioMemberSignalConstruction",
            "rank_based": "#/$defs/PortfolioRankConstruction",
            "trailing_return": "#/$defs/TrailingReturnRotation"
          },
          "propertyName": "kind"
        },
        "oneOf": [
          {
            "$ref": "#/$defs/EqualWeight"
          },
          {
            "$ref": "#/$defs/ManualWeights"
          },
          {
            "$ref": "#/$defs/PortfolioRankConstruction"
          },
          {
            "$ref": "#/$defs/TrailingReturnRotation"
          },
          {
            "$ref": "#/$defs/PortfolioMemberSignalConstruction"
          }
        ],
        "required": [
          "kind"
        ]
      },
      "portfolio:create": {
        "$ref": "#/$defs/PortfolioCreateAuthoring"
      },
      "portfolio:member": {
        "$ref": "#/$defs/Member"
      },
      "portfolio:shared_signal": {
        "$ref": "#/$defs/SharedSignal"
      },
      "portfolio:update": {
        "$ref": "#/$defs/PortfolioUpdateAuthoring"
      },
      "resource:anchor": {
        "$ref": "#/$defs/AnchorDefinition"
      },
      "resource:zone": {
        "$ref": "#/$defs/ZoneDefinition"
      },
      "value_ref:anchor": {
        "allOf": [
          {
            "$ref": "#/$defs/AnchorValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:binary_expr": {
        "allOf": [
          {
            "$ref": "#/$defs/BinaryExprValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:constant": {
        "allOf": [
          {
            "$ref": "#/$defs/ConstantValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:entry_bar": {
        "allOf": [
          {
            "$ref": "#/$defs/EntryBarValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:equity": {
        "allOf": [
          {
            "$ref": "#/$defs/EquityValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:event_distance": {
        "allOf": [
          {
            "$ref": "#/$defs/EventDistanceValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:event_field": {
        "allOf": [
          {
            "$ref": "#/$defs/EventFieldValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:indicator": {
        "allOf": [
          {
            "$ref": "#/$defs/IndicatorValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:live_position": {
        "allOf": [
          {
            "$ref": "#/$defs/LivePositionValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:named_zone": {
        "allOf": [
          {
            "$ref": "#/$defs/NamedZoneValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:percentile": {
        "allOf": [
          {
            "$ref": "#/$defs/PercentileValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:price": {
        "allOf": [
          {
            "$ref": "#/$defs/PriceValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:rank": {
        "allOf": [
          {
            "$ref": "#/$defs/RankValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:rolling_max": {
        "allOf": [
          {
            "$ref": "#/$defs/RollingMaxValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:rolling_min": {
        "allOf": [
          {
            "$ref": "#/$defs/RollingMinValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:rolling_stats": {
        "allOf": [
          {
            "$ref": "#/$defs/RollingStatsValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:sequence_step": {
        "allOf": [
          {
            "$ref": "#/$defs/SequenceStepValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:session": {
        "allOf": [
          {
            "$ref": "#/$defs/SessionValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:shared_signal": {
        "allOf": [
          {
            "$ref": "#/$defs/SharedSignalValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:sibling": {
        "allOf": [
          {
            "$ref": "#/$defs/SiblingValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:swing": {
        "allOf": [
          {
            "$ref": "#/$defs/SwingValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:time": {
        "allOf": [
          {
            "$ref": "#/$defs/TimeValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:tracked": {
        "allOf": [
          {
            "$ref": "#/$defs/TrackedValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:trade_history": {
        "allOf": [
          {
            "$ref": "#/$defs/TradeHistoryValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:triggering_zone": {
        "allOf": [
          {
            "$ref": "#/$defs/TriggeringZoneValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:unary_expr": {
        "allOf": [
          {
            "$ref": "#/$defs/UnaryExprValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:volume": {
        "allOf": [
          {
            "$ref": "#/$defs/VolumeValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:xs_dispersion": {
        "allOf": [
          {
            "$ref": "#/$defs/DispersionValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      },
      "value_ref:xs_zscore": {
        "allOf": [
          {
            "$ref": "#/$defs/ZScoreValueRef"
          },
          {
            "$ref": "#/$defs/ValueRef"
          }
        ]
      }
    }
  },
  "source_format": "kind_discriminated_json",
  "specification_etag": "sha256:c6e297bf78f373ee88a4fdfec7baf90dc04a854a0d289f295b23904793b00b73"
}
