quant-ai / src /llm /parser.py
Ypeng12's picture
feat: 10/10 HRT style point-in-time alpha research platform, purged walk-forward CV, risk parity & test suite
b54319d
Raw
History Blame Contribute Delete
2.21 kB
import re
from typing import Dict, Any
from src.data.manifest import ExperimentManifest, create_manifest
class LLMHypothesisParser:
"""
Typed LLM Guardrail Parser:
Converts natural language user research prompts (e.g. "Test whether 20-day momentum predicts 5-day returns among sector ETFs at 5 bps cost")
into validated, deterministic Pydantic ExperimentManifest configurations.
"""
@staticmethod
def parse_hypothesis(prompt: str) -> ExperimentManifest:
prompt_lower = prompt.lower()
# Extract lookback days
lookback_match = re.search(r"(\d+)[ -]?day momentum", prompt_lower)
lookback_days = int(lookback_match.group(1)) if lookback_match else 20
# Extract holding days
holding_match = re.search(r"(\d+)[ -]?day return", prompt_lower)
holding_days = int(holding_match.group(1)) if holding_match else 5
# Extract transaction cost bps
cost_match = re.search(r"(\d+)[ -]?bps", prompt_lower)
cost_bps = float(cost_match.group(1)) if cost_match else 5.0
# Universe defaults
universe = [
"SPY", "QQQ", "IWM", "MDY",
"XLK", "XLF", "XLE", "XLV", "XLY", "XLP", "XLI", "XLB", "XLU", "XLC", "XLRE",
"SMH", "XBI", "KRE", "ITB",
"TLT", "IEF", "SHY", "LQD", "HYG", "TIP",
"GLD", "SLV", "USO", "DBA",
"EEM", "EFA", "FXI", "EWJ",
"MTUM", "USMV", "QUAL", "IWD", "IWF"
]
manifest = create_manifest(
asset_universe=universe,
lookback_days=lookback_days,
holding_days=holding_days,
transaction_cost_bps=cost_bps,
feature_config={
"raw_mom": True,
"sortino_mom": "sortino" in prompt_lower or "volatility" in prompt_lower,
"residual_mom": "residual" in prompt_lower,
"volume_z": "volume" in prompt_lower,
},
model_config={
"type": "lightgbm" if "tree" in prompt_lower or "lightgbm" in prompt_lower else "ridge",
"max_depth": 3,
"learning_rate": 0.01
}
)
return manifest