feat: strategy builder

This commit is contained in:
OpenSquared
2026-07-18 16:37:35 +02:00
parent 16ccc7c2c7
commit 91054979ec
14 changed files with 2106 additions and 2 deletions

View File

@@ -44,6 +44,36 @@ def init_db():
created_at TEXT DEFAULT (datetime('now'))
)""")
c.execute("""CREATE TABLE IF NOT EXISTS strategy_scenarios (
id TEXT PRIMARY KEY,
symbol TEXT NOT NULL,
label TEXT,
horizon_days INTEGER NOT NULL,
spot_shock_pct REAL NOT NULL,
iv_level_shift REAL NOT NULL,
skew_tilt REAL NOT NULL,
term_shift REAL NOT NULL,
manual_grid TEXT,
created_at TEXT DEFAULT (datetime('now'))
)""")
c.execute("""CREATE TABLE IF NOT EXISTS saved_strategies (
id TEXT PRIMARY KEY,
scenario_id TEXT,
symbol TEXT NOT NULL,
template_name TEXT,
objective TEXT,
legs TEXT NOT NULL,
entry_cost REAL,
max_gain REAL,
max_loss REAL,
net_pnl_scenario REAL,
net_delta REAL,
notes TEXT,
created_at TEXT DEFAULT (datetime('now')),
FOREIGN KEY (scenario_id) REFERENCES strategy_scenarios(id)
)""")
c.execute("""CREATE TABLE IF NOT EXISTS custom_patterns (
id TEXT PRIMARY KEY,
name TEXT NOT NULL,
@@ -5885,3 +5915,105 @@ def get_market_events_near_date(date_str: str, days: int = 2,
return [dict(r) for r in rows]
finally:
conn.close()
# ── Strategy Builder: scenarios & saved strategies ───────────────────────────
def save_scenario(scenario: Dict[str, Any]) -> str:
import uuid
scenario_id = scenario.get("id") or f"SCN-{uuid.uuid4().hex[:8].upper()}"
conn = get_conn()
conn.execute("""INSERT INTO strategy_scenarios (
id, symbol, label, horizon_days, spot_shock_pct, iv_level_shift, skew_tilt, term_shift, manual_grid
) VALUES (?,?,?,?,?,?,?,?,?)""", (
scenario_id,
scenario["symbol"],
scenario.get("label", ""),
scenario["horizon_days"],
scenario["spot_shock_pct"],
scenario["iv_level_shift"],
scenario["skew_tilt"],
scenario["term_shift"],
json.dumps(scenario.get("manual_grid") or []),
))
conn.commit()
conn.close()
return scenario_id
def get_scenarios(symbol: Optional[str] = None) -> List[Dict[str, Any]]:
conn = get_conn()
if symbol:
rows = conn.execute(
"SELECT * FROM strategy_scenarios WHERE symbol=? ORDER BY created_at DESC", (symbol,)
).fetchall()
else:
rows = conn.execute("SELECT * FROM strategy_scenarios ORDER BY created_at DESC").fetchall()
conn.close()
out = []
for r in rows:
d = dict(r)
d["manual_grid"] = json.loads(d.get("manual_grid") or "[]")
out.append(d)
return out
def delete_scenario(scenario_id: str) -> bool:
conn = get_conn()
cur = conn.execute("DELETE FROM strategy_scenarios WHERE id=?", (scenario_id,))
conn.commit()
deleted = cur.rowcount > 0
conn.close()
return deleted
def save_strategy(strategy: Dict[str, Any]) -> str:
import uuid
strategy_id = strategy.get("id") or f"STR-{uuid.uuid4().hex[:8].upper()}"
conn = get_conn()
conn.execute("""INSERT INTO saved_strategies (
id, scenario_id, symbol, template_name, objective, legs,
entry_cost, max_gain, max_loss, net_pnl_scenario, net_delta, notes
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?)""", (
strategy_id,
strategy.get("scenario_id"),
strategy["symbol"],
strategy.get("template_name", ""),
strategy.get("objective", ""),
json.dumps(strategy.get("legs", [])),
strategy.get("entry_cost"),
strategy.get("max_gain"),
strategy.get("max_loss"),
strategy.get("net_pnl_scenario"),
strategy.get("net_delta"),
strategy.get("notes", ""),
))
conn.commit()
conn.close()
return strategy_id
def get_saved_strategies(symbol: Optional[str] = None) -> List[Dict[str, Any]]:
conn = get_conn()
if symbol:
rows = conn.execute(
"SELECT * FROM saved_strategies WHERE symbol=? ORDER BY created_at DESC", (symbol,)
).fetchall()
else:
rows = conn.execute("SELECT * FROM saved_strategies ORDER BY created_at DESC").fetchall()
conn.close()
out = []
for r in rows:
d = dict(r)
d["legs"] = json.loads(d.get("legs") or "[]")
out.append(d)
return out
def delete_saved_strategy(strategy_id: str) -> bool:
conn = get_conn()
cur = conn.execute("DELETE FROM saved_strategies WHERE id=?", (strategy_id,))
conn.commit()
deleted = cur.rowcount > 0
conn.close()
return deleted