{ "$schema": "https://json-schema.org/draft/2020-12/schema", "$id": "https://boat.local/quant60/schemas/broker_snapshot.schema.json", "title": "Quant60 broker snapshot", "description": "A point-in-time broker fact used for pre-trade and reconciliation.", "type": "object", "additionalProperties": false, "required": [ "schema_version", "snapshot_id", "signal_as_of", "next_trading_session", "first_executable_window", "observation_as_of", "as_of", "source_time", "broker", "account_hash", "cash", "total_asset", "positions", "open_orders" ], "properties": { "schema_version": { "const": "1.0" }, "snapshot_id": { "type": "string", "minLength": 1 }, "as_of": { "type": "string", "format": "date-time", "description": "Broker observation completion time. This may be later than the signal close when the snapshot is queried on the next executable session." }, "observation_as_of": { "type": "string", "format": "date-time", "description": "Explicit observation-clock alias for as_of. Account-bound decision paths require the two instants to be equal." }, "signal_as_of": { "type": "string", "format": "date-time", "description": "Required completed signal-close clock this snapshot is intended to bind." }, "next_trading_session": { "type": "string", "format": "date", "description": "The unique adjacent trading session from the verified decision calendar." }, "first_executable_window": { "$ref": "#/$defs/first_executable_window" }, "broker": { "type": "string", "minLength": 1 }, "account_hash": { "type": "string", "minLength": 8, "description": "One-way account identifier; never store the raw account number." }, "cash": { "type": "number", "minimum": 0 }, "total_asset": { "type": "number", "minimum": 0 }, "market_value": { "type": "number", "minimum": 0 }, "positions": { "type": "array", "items": { "$ref": "#/$defs/position" } }, "open_orders": { "type": "array", "items": { "$ref": "#/$defs/open_order" } }, "source_time": { "type": "string", "format": "date-time", "description": "Timestamp assigned to the broker facts; it must not predate the bound signal and must remain fresh relative to the observation clock." }, "metadata": { "type": "object" } }, "$defs": { "first_executable_window": { "type": "object", "additionalProperties": false, "required": [ "session", "timezone", "start", "end", "boundary", "purpose" ], "properties": { "session": { "type": "string", "format": "date" }, "timezone": { "const": "Asia/Shanghai" }, "start": { "type": "string", "format": "date-time" }, "end": { "type": "string", "format": "date-time" }, "boundary": { "const": "[start,end)" }, "purpose": { "const": "PRE_OPEN_BROKER_OBSERVATION" } } }, "canonical_symbol": { "type": "string", "pattern": "^[0-9]{6}\\.(XSHG|XSHE|XBSE)$" }, "position": { "type": "object", "additionalProperties": false, "required": [ "symbol", "quantity", "sellable_quantity" ], "properties": { "symbol": { "$ref": "#/$defs/canonical_symbol" }, "quantity": { "type": "integer", "minimum": 0 }, "sellable_quantity": { "type": "integer", "minimum": 0 }, "average_cost": { "type": [ "number", "null" ], "minimum": 0 }, "market_value": { "type": [ "number", "null" ], "minimum": 0 } } }, "open_order": { "type": "object", "additionalProperties": false, "required": [ "order_id", "broker_order_id", "symbol", "side", "quantity", "filled_quantity", "status", "limit_price", "order_type", "time_in_force" ], "properties": { "order_id": { "type": "string", "minLength": 1 }, "broker_order_id": { "type": "string", "minLength": 1 }, "symbol": { "$ref": "#/$defs/canonical_symbol" }, "side": { "enum": [ "BUY", "SELL" ] }, "quantity": { "type": "integer", "minimum": 1 }, "filled_quantity": { "type": "integer", "minimum": 0 }, "status": { "enum": [ "NEW", "ACCEPTED", "PARTIALLY_FILLED", "CANCEL_PENDING", "UNKNOWN" ] }, "limit_price": { "type": "number", "exclusiveMinimum": 0 }, "order_type": { "const": "LIMIT" }, "time_in_force": { "const": "DAY" } } } } }