2026-02-01 13:57:30 +00:00

151 lines
5.1 KiB
Python

import json
from datetime import datetime
from indian_paper_trading_strategy.engine.db import db_connection, get_context
DEFAULT_CONFIG = {
"active": False,
"sip_amount": 0,
"sip_frequency": {"value": 30, "unit": "days"},
"next_run": None
}
def _maybe_parse_json(value):
if value is None:
return None
if not isinstance(value, str):
return value
text = value.strip()
if not text:
return None
try:
return json.loads(text)
except Exception:
return value
def _format_ts(value: datetime | None):
if value is None:
return None
return value.isoformat()
def load_strategy_config(user_id: str | None = None, run_id: str | None = None):
scope_user, scope_run = get_context(user_id, run_id)
with db_connection() as conn:
with conn.cursor() as cur:
cur.execute(
"""
SELECT strategy, sip_amount, sip_frequency_value, sip_frequency_unit,
mode, broker, active, frequency, frequency_days, unit, next_run
FROM strategy_config
WHERE user_id = %s AND run_id = %s
LIMIT 1
""",
(scope_user, scope_run),
)
row = cur.fetchone()
if not row:
return DEFAULT_CONFIG.copy()
cfg = DEFAULT_CONFIG.copy()
cfg["strategy"] = row[0]
cfg["strategy_name"] = row[0]
cfg["sip_amount"] = float(row[1]) if row[1] is not None else cfg.get("sip_amount")
cfg["mode"] = row[4]
cfg["broker"] = row[5]
cfg["active"] = row[6] if row[6] is not None else cfg.get("active")
cfg["frequency"] = _maybe_parse_json(row[7])
cfg["frequency_days"] = row[8]
cfg["unit"] = row[9]
cfg["next_run"] = _format_ts(row[10])
if row[2] is not None or row[3] is not None:
cfg["sip_frequency"] = {"value": row[2], "unit": row[3]}
else:
value = cfg.get("frequency")
unit = cfg.get("unit")
if isinstance(value, dict):
unit = value.get("unit", unit)
value = value.get("value")
if value is None and cfg.get("frequency_days") is not None:
value = cfg.get("frequency_days")
unit = unit or "days"
if value is not None and unit:
cfg["sip_frequency"] = {"value": value, "unit": unit}
return cfg
def save_strategy_config(cfg, user_id: str | None = None, run_id: str | None = None):
scope_user, scope_run = get_context(user_id, run_id)
sip_frequency = cfg.get("sip_frequency")
sip_value = None
sip_unit = None
if isinstance(sip_frequency, dict):
sip_value = sip_frequency.get("value")
sip_unit = sip_frequency.get("unit")
frequency = cfg.get("frequency")
if not isinstance(frequency, str) and frequency is not None:
frequency = json.dumps(frequency)
next_run = cfg.get("next_run")
next_run_dt = None
if isinstance(next_run, str):
try:
next_run_dt = datetime.fromisoformat(next_run)
except ValueError:
next_run_dt = None
strategy = cfg.get("strategy") or cfg.get("strategy_name")
with db_connection() as conn:
with conn:
with conn.cursor() as cur:
cur.execute(
"""
INSERT INTO strategy_config (
user_id,
run_id,
strategy,
sip_amount,
sip_frequency_value,
sip_frequency_unit,
mode,
broker,
active,
frequency,
frequency_days,
unit,
next_run
)
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
ON CONFLICT (user_id, run_id) DO UPDATE
SET strategy = EXCLUDED.strategy,
sip_amount = EXCLUDED.sip_amount,
sip_frequency_value = EXCLUDED.sip_frequency_value,
sip_frequency_unit = EXCLUDED.sip_frequency_unit,
mode = EXCLUDED.mode,
broker = EXCLUDED.broker,
active = EXCLUDED.active,
frequency = EXCLUDED.frequency,
frequency_days = EXCLUDED.frequency_days,
unit = EXCLUDED.unit,
next_run = EXCLUDED.next_run
""",
(
scope_user,
scope_run,
strategy,
cfg.get("sip_amount"),
sip_value,
sip_unit,
cfg.get("mode"),
cfg.get("broker"),
cfg.get("active"),
frequency,
cfg.get("frequency_days"),
cfg.get("unit"),
next_run_dt,
),
)