Files

37 lines
1.4 KiB
Python

from __future__ import annotations
from typing import Any, Dict
# Simple risk rules for MVP
MAX_POSITION_FRACTION = 0.6 # max 60% of equity in a single position
def _equity(sim_state: Dict[str, Any], price: float) -> float:
cash = float(sim_state.get("cash", 0.0))
pos = sim_state.get("position")
qty = float(pos["quantity"]) if pos else 0.0
return cash + qty * price
def validate_order(sim_state: Dict[str, Any], action: str, quantity: float, price: float) -> None:
action = str(action).upper()
if quantity <= 0 or price <= 0:
raise ValueError("Quantity and price must be positive")
if action == "BUY":
# Anti-stacking: only one symbol supported in MVP, allow averaging up to cap
pos = sim_state.get("position")
current_qty = float(pos["quantity"]) if pos else 0.0
new_qty = current_qty + float(quantity)
resulting_position_value = new_qty * float(price)
eq_now = _equity(sim_state, price)
if eq_now <= 0:
raise ValueError("Equity must be positive")
if resulting_position_value > MAX_POSITION_FRACTION * eq_now:
raise ValueError("Position exceeds max allowed exposure fraction")
elif action == "SELL":
pos = sim_state.get("position")
if not pos or float(quantity) > float(pos.get("quantity", 0.0)):
raise ValueError("Insufficient position to sell")
else:
raise ValueError("Unsupported action")