{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://example.local/schemas/backtest_config.schema.json",
  "title": "BacktestConfig",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "strategy_name",
    "dataset_snapshot_id",
    "universe",
    "signal",
    "risk",
    "execution",
    "reporting"
  ],
  "properties": {
    "strategy_name": {
      "type": "string",
      "minLength": 1
    },
    "dataset_snapshot_id": {
      "type": "string",
      "minLength": 1
    },
    "universe": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "min_price",
        "min_avg_dollar_volume",
        "exclude_asset_types"
      ],
      "properties": {
        "min_price": {
          "type": "number",
          "minimum": 0
        },
        "min_avg_dollar_volume": {
          "type": "number",
          "minimum": 0
        },
        "exclude_asset_types": {
          "type": "array",
          "items": {
            "type": "string"
          }
        },
        "allowed_exchanges": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "signal": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "score_threshold",
        "max_candidates_per_day",
        "execution_timing"
      ],
      "properties": {
        "score_threshold": {
          "type": "number"
        },
        "max_candidates_per_day": {
          "type": "integer",
          "minimum": 1
        },
        "execution_timing": {
          "type": "string",
          "enum": [
            "next_open",
            "next_close"
          ]
        },
        "decision_timing": {
          "type": "string",
          "enum": [
            "reaction_close"
          ]
        },
        "ranking_fields": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    },
    "risk": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "per_trade_risk_pct",
        "max_daily_new_risk_pct",
        "max_positions",
        "max_positions_per_sector"
      ],
      "properties": {
        "per_trade_risk_pct": {
          "type": "number",
          "exclusiveMinimum": 0
        },
        "max_daily_new_risk_pct": {
          "type": "number",
          "exclusiveMinimum": 0
        },
        "max_positions": {
          "type": "integer",
          "minimum": 1
        },
        "max_positions_per_sector": {
          "type": "integer",
          "minimum": 1
        },
        "max_position_value_pct": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "max_adv_fraction": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "cooldown_after_loss_streak": {
          "type": "integer",
          "minimum": 0
        },
        "cooldown_days": {
          "type": "integer",
          "minimum": 0
        }
      }
    },
    "execution": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "entry_fill_model",
        "exit_fill_model",
        "slippage_bps_base",
        "same_bar_priority"
      ],
      "properties": {
        "entry_fill_model": {
          "type": "string",
          "enum": [
            "next_open"
          ]
        },
        "exit_fill_model": {
          "type": "string",
          "enum": [
            "daily_bar_approximation"
          ]
        },
        "slippage_bps_base": {
          "type": "number",
          "minimum": 0
        },
        "commission_per_share": {
          "type": "number",
          "minimum": 0
        },
        "same_bar_priority": {
          "type": "string",
          "enum": [
            "stop_first_conservative",
            "target_first_aggressive"
          ]
        },
        "stop_model": {
          "type": "string"
        },
        "target_1_r": {
          "type": "number",
          "minimum": 0
        },
        "target_1_fraction": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "trailing_model": {
          "type": "string"
        },
        "max_holding_days": {
          "type": "integer",
          "minimum": 1
        }
      }
    },
    "reporting": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "write_trade_blotter",
        "write_equity_curve",
        "write_metrics_summary"
      ],
      "properties": {
        "write_trade_blotter": {
          "type": "boolean"
        },
        "write_equity_curve": {
          "type": "boolean"
        },
        "write_metrics_summary": {
          "type": "boolean"
        },
        "generate_plots": {
          "type": "boolean"
        },
        "attribution_buckets": {
          "type": "array",
          "items": {
            "type": "string"
          }
        }
      }
    }
  }
}
