151 lines
5.3 KiB
Python
151 lines
5.3 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,
|
|
),
|
|
)
|
|
|