"""LIVE 金额与组净盈亏口径。""" from __future__ import annotations from app.live.live_pnl import enrich_live_unrealized, group_paid_fees_usdt from app.live.money import abs_fee_usdt, to_usdt def test_to_usdt_one_to_one() -> None: assert to_usdt(12.5, "USDC") == 12.5 assert to_usdt(-3.0, "USDT") == -3.0 assert abs_fee_usdt(-0.2, "USDC") == 0.2 def test_group_paid_fees(tmp_path, monkeypatch) -> None: monkeypatch.setenv("MODE", "SIM") from app.models.db import Database db = Database(tmp_path / "f.db") with db._lock: db._conn.execute( """INSERT INTO groups(group_id, status, open_at_ms, fees) VALUES ('G1','open',1,0)""" ) db._conn.execute( """INSERT INTO fills(group_id, leg, action, side, inst_id, qty_eth, fill_px, fee, slip, notional, ts_ms) VALUES ('G1','option','open','long','OPT',2,10,0.5,0,20,1)""" ) db._conn.execute( """INSERT INTO fills(group_id, leg, action, side, inst_id, qty_eth, fill_px, fee, slip, notional, ts_ms) VALUES ('G1','perp','open','short','SWAP',1,100,-0.3,0,100,2)""" ) db._conn.commit() assert group_paid_fees_usdt(db, "G1") == 0.8 db.close() class _FakeClient: def get_perp_upl_usdt(self, *a, **k): return 8.0 def get_funding_usdt(self, *a, **k): return -1.5 def test_enrich_live_unrealized_keeps_book_net_plus_funding() -> None: base = { "has_position": True, "group_id": "G1", "perp_side": "short", "perp_upl": 1.0, "option_upl": 5.0, "est_close_fees": 0.8, "net_pnl": -3.9, } class _Db: def fetchall(self, *a, **k): return [{"fee": 0.4}, {"fee": 0.1}] out = enrich_live_unrealized( base=base, db=_Db(), client=_FakeClient(), exchange="okx", perp_inst_id="ETH-USDT-SWAP", perp_side="short", open_at_ms=1, ) assert out["perp_upl"] == 1.0 # 盘口可平 assert out["perp_upl_exchange"] == 8.0 assert out["option_upl"] == 5.0 assert out["fees_paid"] == 0.5 assert out["funding_usdt"] == -1.5 assert out["est_close_fees"] == 0.8 # 盯盘净利 = 盘口净利 + 资金费,不用标记 UPL 覆盖 assert abs(out["net_pnl"] - (-3.9 - 1.5)) < 1e-9 assert out["pnl_source"] == "live_book_plus_funding"