{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://github.com/fallblu/trading-engine/contracts/v3/scenario.schema.json",
  "title": "Trading Engine v3 replay scenario",
  "description": "Strict deterministic scenario contract for fractional quantities, explicit FX, corporate actions, signed positions, and margin risk.",
  "type": "object",
  "additionalProperties": false,
  "required": ["contract_version", "metadata", "run_id", "base_currency", "initial_cash", "instruments", "risk", "execution", "max_internal_events", "schedule", "slices"],
  "properties": {
    "contract_version": { "const": "3" },
    "metadata": { "type": "object" },
    "run_id": { "$ref": "#/$defs/identifier" },
    "base_currency": { "$ref": "#/$defs/identifier" },
    "initial_cash": {
      "type": "array",
      "minItems": 1,
      "items": { "$ref": "#/$defs/cashBalance" }
    },
    "instruments": {
      "type": "array",
      "minItems": 1,
      "maxItems": 4096,
      "items": { "$ref": "#/$defs/instrument" }
    },
    "risk": { "$ref": "#/$defs/risk" },
    "execution": { "$ref": "#/$defs/execution" },
    "max_internal_events": { "type": "integer", "minimum": 1, "maximum": 100000 },
    "schedule": { "type": "array", "items": { "$ref": "#/$defs/scheduleItem" } },
    "slices": {
      "description": "Slices are ordered and non-overlapping: each start_at is at or after the prior end_at. Equal boundaries are valid. This cross-item rule is enforced semantically.",
      "type": "array",
      "items": { "$ref": "#/$defs/marketSlice" }
    }
  },
  "$defs": {
    "identifier": {
      "type": "string",
      "minLength": 1,
      "pattern": "^[^\\s\\u0000-\\u001f\\u007f]+$"
    },
    "signedDecimal": {
      "type": "string",
      "pattern": "^(?:0|-?(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?))$"
    },
    "unsignedDecimal": {
      "type": "string",
      "pattern": "^(?:0|0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$"
    },
    "positiveDecimal": {
      "type": "string",
      "pattern": "^(?:0[.][0-9]{0,5}[1-9]|[1-9][0-9]*(?:[.][0-9]{0,5}[1-9])?)$"
    },
    "sequence": { "type": "string", "pattern": "^[1-9][0-9]*$" },
    "timestamp": {
      "type": "string",
      "format": "date-time",
      "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}[Tt][0-9]{2}:[0-9]{2}:[0-5][0-9](?:[.][0-9]{1,6})?(?:[zZ]|[+-][0-9]{2}:[0-9]{2})$"
    },
    "cashBalance": {
      "type": "object",
      "additionalProperties": false,
      "required": ["currency", "amount"],
      "properties": {
        "currency": { "$ref": "#/$defs/identifier" },
        "amount": { "$ref": "#/$defs/unsignedDecimal" }
      }
    },
    "instrument": {
      "type": "object",
      "additionalProperties": false,
      "required": ["instrument_id", "symbol", "quote_currency", "tick_size", "lot_size"],
      "properties": {
        "instrument_id": { "$ref": "#/$defs/identifier" },
        "symbol": { "$ref": "#/$defs/identifier" },
        "quote_currency": { "$ref": "#/$defs/identifier" },
        "tick_size": { "$ref": "#/$defs/positiveDecimal" },
        "lot_size": { "$ref": "#/$defs/positiveDecimal" }
      }
    },
    "risk": {
      "type": "object",
      "additionalProperties": false,
      "required": ["max_order_quantity", "max_long_position", "max_short_position", "max_gross_exposure", "max_leverage", "initial_margin_bps", "maintenance_margin_bps", "short_borrow_bps"],
      "properties": {
        "max_order_quantity": { "$ref": "#/$defs/positiveDecimal" },
        "max_long_position": { "$ref": "#/$defs/positiveDecimal" },
        "max_short_position": { "$ref": "#/$defs/positiveDecimal" },
        "max_gross_exposure": { "$ref": "#/$defs/positiveDecimal" },
        "max_leverage": { "$ref": "#/$defs/positiveDecimal" },
        "initial_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 },
        "maintenance_margin_bps": { "type": "integer", "minimum": 1, "maximum": 10000 },
        "short_borrow_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }
      }
    },
    "execution": {
      "type": "object",
      "additionalProperties": false,
      "required": ["model", "participation_bps", "fixed_fee", "fee_bps"],
      "properties": {
        "model": { "const": "completed_bar_v1" },
        "participation_bps": { "type": "integer", "minimum": 0, "maximum": 10000 },
        "fixed_fee": { "$ref": "#/$defs/unsignedDecimal" },
        "fee_bps": { "type": "integer", "minimum": 0, "maximum": 10000 }
      }
    },
    "scheduleItem": {
      "type": "object",
      "additionalProperties": false,
      "required": ["after_slice_sequence", "intents"],
      "properties": {
        "after_slice_sequence": { "$ref": "#/$defs/sequence" },
        "intents": { "type": "array", "maxItems": 4096, "items": { "$ref": "#/$defs/intent" } }
      }
    },
    "intent": {
      "oneOf": [
        { "$ref": "#/$defs/targetWeights" },
        { "$ref": "#/$defs/targetQuantities" },
        { "$ref": "#/$defs/submitOrder" },
        { "$ref": "#/$defs/cancelOrder" },
        { "$ref": "#/$defs/metric" }
      ]
    },
    "targetWeights": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "targets"],
      "properties": {
        "type": { "const": "target_weights" },
        "targets": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["instrument_id", "weight"],
            "properties": {
              "instrument_id": { "$ref": "#/$defs/identifier" },
              "weight": { "$ref": "#/$defs/signedDecimal" }
            }
          }
        }
      }
    },
    "targetQuantities": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "targets"],
      "properties": {
        "type": { "const": "target_quantities" },
        "targets": {
          "type": "array",
          "minItems": 1,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["instrument_id", "quantity"],
            "properties": {
              "instrument_id": { "$ref": "#/$defs/identifier" },
              "quantity": { "$ref": "#/$defs/signedDecimal" }
            }
          }
        }
      }
    },
    "submitOrder": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "instrument_id", "side", "quantity", "order_kind", "limit_price"],
      "properties": {
        "type": { "const": "submit_order" },
        "instrument_id": { "$ref": "#/$defs/identifier" },
        "side": { "enum": ["buy", "sell"] },
        "quantity": { "$ref": "#/$defs/positiveDecimal" },
        "order_kind": { "enum": ["market", "limit"] },
        "limit_price": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/positiveDecimal" }] }
      }
    },
    "cancelOrder": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "order_id"],
      "properties": {
        "type": { "const": "cancel_order" },
        "order_id": { "$ref": "#/$defs/identifier" }
      }
    },
    "metric": {
      "type": "object",
      "additionalProperties": false,
      "required": ["type", "name", "value"],
      "properties": {
        "type": { "const": "emit_metric" },
        "name": { "type": "string" },
        "value": { "type": "string" }
      }
    },
    "marketSlice": {
      "type": "object",
      "additionalProperties": false,
      "required": ["slice_sequence", "start_at", "end_at", "available_at", "received_at", "bars", "fx_rates", "corporate_actions"],
      "properties": {
        "slice_sequence": { "$ref": "#/$defs/sequence" },
        "start_at": { "$ref": "#/$defs/timestamp" },
        "end_at": { "$ref": "#/$defs/timestamp" },
        "available_at": { "$ref": "#/$defs/timestamp" },
        "received_at": { "$ref": "#/$defs/timestamp" },
        "bars": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/bar" } },
        "fx_rates": { "type": "array", "minItems": 1, "items": { "$ref": "#/$defs/fxRate" } },
        "corporate_actions": { "type": "array", "items": { "$ref": "#/$defs/corporateAction" } }
      }
    },
    "bar": {
      "type": "object",
      "additionalProperties": false,
      "required": ["instrument_id", "open", "high", "low", "close", "volume"],
      "properties": {
        "instrument_id": { "$ref": "#/$defs/identifier" },
        "open": { "$ref": "#/$defs/positiveDecimal" },
        "high": { "$ref": "#/$defs/positiveDecimal" },
        "low": { "$ref": "#/$defs/positiveDecimal" },
        "close": { "$ref": "#/$defs/positiveDecimal" },
        "volume": { "oneOf": [{ "type": "null" }, { "$ref": "#/$defs/unsignedDecimal" }] }
      }
    },
    "fxRate": {
      "type": "object",
      "additionalProperties": false,
      "required": ["currency", "rate"],
      "properties": {
        "currency": { "$ref": "#/$defs/identifier" },
        "rate": { "$ref": "#/$defs/positiveDecimal" }
      }
    },
    "corporateAction": {
      "oneOf": [
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["type", "action_id", "instrument_id", "numerator", "denominator"],
          "properties": {
            "type": { "const": "split" },
            "action_id": { "$ref": "#/$defs/identifier" },
            "instrument_id": { "$ref": "#/$defs/identifier" },
            "numerator": { "$ref": "#/$defs/sequence" },
            "denominator": { "$ref": "#/$defs/sequence" }
          }
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": ["type", "action_id", "instrument_id", "amount_per_unit"],
          "properties": {
            "type": { "const": "cash_dividend" },
            "action_id": { "$ref": "#/$defs/identifier" },
            "instrument_id": { "$ref": "#/$defs/identifier" },
            "amount_per_unit": { "$ref": "#/$defs/positiveDecimal" }
          }
        }
      ]
    }
  }
}
