From e8166e80167edba3455de4c9ac67c19d639d05b0 Mon Sep 17 00:00:00 2001 From: Metacube Date: Sun, 24 May 2026 09:33:07 +0200 Subject: [PATCH] Add trading cockpit storage --- trade_web/storage.py | 116 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) create mode 100644 trade_web/storage.py diff --git a/trade_web/storage.py b/trade_web/storage.py new file mode 100644 index 0000000..b4f6291 --- /dev/null +++ b/trade_web/storage.py @@ -0,0 +1,116 @@ +from __future__ import annotations + +import json +import sqlite3 +import time +from pathlib import Path +from typing import Any + + +class TradeStore: + def __init__(self, path: Path): + self.path = path + self.path.parent.mkdir(parents=True, exist_ok=True) + self._init() + + def _connect(self) -> sqlite3.Connection: + connection = sqlite3.connect(self.path) + connection.row_factory = sqlite3.Row + return connection + + def _init(self) -> None: + with self._connect() as db: + db.execute( + """ + create table if not exists runs ( + id integer primary key autoincrement, + kind text not null, + created_at integer not null, + label text, + payload text not null + ) + """ + ) + db.execute( + """ + create table if not exists paper_orders ( + id integer primary key autoincrement, + created_at integer not null, + symbol text not null, + side text not null, + status text not null, + quantity real not null, + entry real not null, + stop real not null, + target real not null, + risk_amount real not null, + payload text not null + ) + """ + ) + + def save_run(self, kind: str, payload: dict[str, Any], label: str | None = None) -> int: + with self._connect() as db: + cursor = db.execute( + "insert into runs(kind, created_at, label, payload) values(?, ?, ?, ?)", + (kind, int(time.time()), label, json.dumps(payload)), + ) + return int(cursor.lastrowid) + + def recent_runs(self, kind: str | None = None, limit: int = 25) -> list[dict[str, Any]]: + query = "select id, kind, created_at, label, payload from runs" + params: list[Any] = [] + if kind: + query += " where kind = ?" + params.append(kind) + query += " order by id desc limit ?" + params.append(limit) + with self._connect() as db: + rows = db.execute(query, params).fetchall() + return [ + { + "id": row["id"], + "kind": row["kind"], + "created_at": row["created_at"], + "label": row["label"], + "payload": json.loads(row["payload"]), + } + for row in rows + ] + + def save_paper_order(self, order: dict[str, Any]) -> int: + with self._connect() as db: + cursor = db.execute( + """ + insert into paper_orders( + created_at, symbol, side, status, quantity, entry, stop, target, risk_amount, payload + ) values(?, ?, ?, ?, ?, ?, ?, ?, ?, ?) + """, + ( + int(time.time()), + order["symbol"], + order["side"], + order["status"], + order["quantity"], + order["entry"], + order["stop"], + order["target"], + order["risk_amount"], + json.dumps(order), + ), + ) + return int(cursor.lastrowid) + + def recent_paper_orders(self, limit: int = 25) -> list[dict[str, Any]]: + with self._connect() as db: + rows = db.execute( + "select id, created_at, payload from paper_orders order by id desc limit ?", + (limit,), + ).fetchall() + result = [] + for row in rows: + payload = json.loads(row["payload"]) + payload["id"] = row["id"] + payload["created_at"] = row["created_at"] + result.append(payload) + return result