feat: strategy builder
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user