Implement P1 local matcher/ledger and P2 strategy engine.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,61 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import time
|
||||
from typing import Any
|
||||
|
||||
from ..models.db import Database, get_db
|
||||
|
||||
|
||||
class Ledger:
|
||||
def __init__(self, db: Database | None = None) -> None:
|
||||
self.db = db or get_db()
|
||||
|
||||
def snapshot(self) -> dict[str, Any]:
|
||||
row = self.db.fetchone("SELECT * FROM ledger_meta WHERE id=1")
|
||||
assert row is not None
|
||||
return {
|
||||
"equity": float(row["equity"]),
|
||||
"available": float(row["available"]),
|
||||
"reserved": float(row["reserved"]),
|
||||
"updated_at_ms": int(row["updated_at_ms"]),
|
||||
}
|
||||
|
||||
def apply_cash(
|
||||
self,
|
||||
amount: float,
|
||||
*,
|
||||
kind: str,
|
||||
group_id: str | None = None,
|
||||
note: str = "",
|
||||
) -> float:
|
||||
"""amount>0 入账;amount<0 出账。返回余额。"""
|
||||
now = int(time.time() * 1000)
|
||||
with self.db._lock:
|
||||
row = self.db._conn.execute("SELECT * FROM ledger_meta WHERE id=1").fetchone()
|
||||
assert row is not None
|
||||
equity = float(row["equity"]) + float(amount)
|
||||
available = float(row["available"]) + float(amount)
|
||||
if available < -1e-9:
|
||||
raise RuntimeError("可用资金不足")
|
||||
self.db._conn.execute(
|
||||
"UPDATE ledger_meta SET equity=?, available=?, updated_at_ms=? WHERE id=1",
|
||||
(equity, available, now),
|
||||
)
|
||||
self.db._conn.execute(
|
||||
"INSERT INTO ledger_entries(group_id, kind, amount, balance_after, note, ts_ms) VALUES (?,?,?,?,?,?)",
|
||||
(group_id, kind, float(amount), equity, note, now),
|
||||
)
|
||||
self.db._conn.commit()
|
||||
return equity
|
||||
|
||||
def get_setting_float(self, key: str, default: float) -> float:
|
||||
v = self.db.get_setting(key)
|
||||
if v is None or v == "":
|
||||
return default
|
||||
try:
|
||||
return float(v)
|
||||
except ValueError:
|
||||
return default
|
||||
|
||||
def get_setting_int(self, key: str, default: int) -> int:
|
||||
return int(self.get_setting_float(key, float(default)))
|
||||
Reference in New Issue
Block a user