{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://tradecat.local/contracts/tradecat-auto-portfolio-risk-policy.schema.json",
  "title": "TradeCat Auto Portfolio Risk Policy",
  "description": "Operator/Agent supplied paper/watch portfolio risk policy. It defines rejection limits only and never supplies trade sizing or exits.",
  "type": "object",
  "required": [
    "schema",
    "schema_version",
    "mode",
    "enabled",
    "limits",
    "provenance",
    "safety",
    "hard_boundaries",
    "limitations"
  ],
  "properties": {
    "schema": {"const": "tradecat_auto.portfolio_risk_policy.v1"},
    "schema_version": {"const": "1.0.0"},
    "mode": {"enum": ["paper", "watch"]},
    "enabled": {"type": "boolean"},
    "new_entries_enabled": {"type": "boolean"},
    "limits": {
      "type": "object",
      "properties": {
        "max_daily_loss_usdt": {"type": ["number", "null"], "exclusiveMinimum": 0},
        "max_drawdown_usdt": {"type": ["number", "null"], "exclusiveMinimum": 0},
        "max_open_positions": {"type": ["integer", "null"], "minimum": 1},
        "max_positions_per_symbol": {"type": ["integer", "null"], "minimum": 1},
        "max_symbol_notional_usdt": {"type": ["number", "null"], "exclusiveMinimum": 0},
        "max_total_notional_usdt": {"type": ["number", "null"], "exclusiveMinimum": 0},
        "max_symbol_risk_usdt": {"type": ["number", "null"], "exclusiveMinimum": 0},
        "max_symbol_risk_pct": {"type": ["number", "null"], "exclusiveMinimum": 0, "maximum": 1},
        "max_leverage": {"type": ["number", "null"], "exclusiveMinimum": 0},
        "min_agent_confidence": {"type": ["number", "null"], "minimum": 0, "maximum": 1},
        "cooldown_minutes_after_reject": {"type": ["number", "null"], "exclusiveMinimum": 0},
        "cooldown_minutes_after_close": {"type": ["number", "null"], "exclusiveMinimum": 0},
        "abnormal_move_halt_bps": {"type": ["number", "null"], "exclusiveMinimum": 0},
        "max_consecutive_losses": {"type": ["integer", "null"], "minimum": 1}
      },
      "additionalProperties": false
    },
    "kill_switch": {
      "type": "object",
      "properties": {
        "active": {"type": "boolean"},
        "reason": {"type": "string"},
        "source": {"type": "string"}
      },
      "additionalProperties": false
    },
    "provenance": {
      "type": "object",
      "required": ["source"],
      "properties": {
        "source": {"type": "string", "minLength": 1},
        "generated_at": {"type": "string"},
        "agent": {"type": "string"}
      },
      "additionalProperties": true
    },
    "safety": {
      "type": "object",
      "required": ["public_readonly_market_data", "public_readonly", "paper_or_watch_only", "real_orders", "signed_requests", "reads_api_keys", "binance_account_state"],
      "properties": {
        "public_readonly_market_data": {"const": true},
        "public_readonly": {"const": true},
        "paper_or_watch_only": {"const": true},
        "real_orders": {"const": false},
        "signed_requests": {"const": false},
        "reads_api_keys": {"const": false},
        "binance_account_state": {"const": false}
      },
      "additionalProperties": true
    },
    "hard_boundaries": {
      "type": "object",
      "required": [
        "does_not_set_order_size",
        "does_not_set_leverage",
        "does_not_set_exit_plan",
        "real_orders",
        "signed_requests",
        "reads_api_keys"
      ],
      "properties": {
        "does_not_set_order_size": {"const": true},
        "does_not_set_leverage": {"const": true},
        "does_not_set_exit_plan": {"const": true},
        "real_orders": {"const": false},
        "signed_requests": {"const": false},
        "reads_api_keys": {"const": false}
      },
      "additionalProperties": true
    },
    "limitations": {
      "type": "array",
      "minItems": 1,
      "items": {"type": "string"},
      "contains": {"type": "string", "pattern": "paper|watch|risk|no real"}
    }
  },
  "not": {
    "anyOf": [
      {"required": ["requested_margin_usdt"]},
      {"required": ["requested_notional_usdt"]},
      {"required": ["paper_leverage"]},
      {"required": ["stop_loss_price"]},
      {"required": ["take_profit_price"]},
      {"required": ["max_holding_minutes"]}
    ]
  },
  "additionalProperties": true
}
