"""Minimal RegFlow implementation for tests. Provides a tiny DSL compiler and a per-trade proof generator sufficient for the unit tests in tests/test_core.py. """ from typing import Dict, List, Any def _parse_line_to_rule(tokens: List[str]) -> Dict[str, Any]: # Expected formats: # constraint max_position # constraint min_cash if len(tokens) < 2: raise ValueError("Invalid constraint line: need at least type") rtype = tokens[1] if rtype == "max_position": # tokens: ["constraint", "max_position", venue, instrument, limit] if len(tokens) != 5: raise ValueError("Invalid max_position constraint: need venue, instrument, limit") venue, instrument, limit = tokens[2], tokens[3], int(tokens[4]) return {"type": "max_position", "venue": venue, "instrument": instrument, "limit": limit} elif rtype == "min_cash": # tokens: ["constraint", "min_cash", venue, limit] if len(tokens) != 4: raise ValueError("Invalid min_cash constraint: need venue, limit") venue, limit = tokens[2], int(tokens[3]) return {"type": "min_cash", "venue": venue, "limit": limit} else: # Unknown constraint type; store generically return {"type": rtype, "raw": tokens[2:]} def compile_dsl(dsl: str) -> Dict[str, Any]: """Compile a tiny DSL into a canonical IR representation. The DSL supports lines like: constraint max_position venue AAPL 1000 constraint min_cash venue 5000 Returns a dict with a single key 'rules' containing a list of rule dicts. """ rules: List[Dict[str, Any]] = [] for raw_line in dsl.strip().splitlines(): line = raw_line.strip() if not line or line.startswith("#"): # skip empty or comments continue tokens = line.split() if not tokens: continue if tokens[0] != "constraint": # ignore non-constraint lines for tests continue rule = _parse_line_to_rule(tokens) rules.append(rule) return {"rules": rules} def _evaluate_rule(rule: Dict[str, Any], trade: Dict[str, Any]) -> Dict[str, Any]: venue = trade.get("venue") if rule.get("venue") is not None and venue != rule["venue"]: return {"ok": False, "rule": rule, "actual": None} if rule["type"] == "max_position": actual = trade.get("qty") ok = actual is not None and actual <= rule["limit"] return {"ok": ok, "rule": rule, "actual": actual} if rule["type"] == "min_cash": actual = trade.get("cash") ok = actual is not None and actual >= rule["limit"] return {"ok": ok, "rule": rule, "actual": actual} # Fallback: unknown rule type treated as OK (not used by tests) return {"ok": True, "rule": rule, "actual": None} def generate_proof(ir: Dict[str, Any], trade: Dict[str, Any]) -> Dict[str, Any]: """Generate a simple per-trade proof against the IR. Returns a dict with: - valid: bool - summary: str - details: list of {ok: bool, rule: dict, actual: Any} """ rules = ir.get("rules", []) details = [] all_ok = True for rule in rules: result = _evaluate_rule(rule, trade) details.append(result) if not result["ok"]: all_ok = False summary = "all applicable constraints satisfied" if all_ok else "some applicable constraints violated" return {"valid": all_ok, "summary": summary, "details": details}