diff --git a/sanguo_api/routes_paper.py b/sanguo_api/routes_paper.py index 6a9f810..c3d73df 100644 --- a/sanguo_api/routes_paper.py +++ b/sanguo_api/routes_paper.py @@ -115,6 +115,27 @@ def get_strategies(aid: int): return list_strategy_summary(_db_path["path"], aid) +@router.get("/paper/{aid}/positions", dependencies=[Depends(verify_token)]) +def get_positions(aid: int): + """当前持仓快照(实走监控,Phase 3c)。{symbol:{volume,frozen,avg_price}} → list。""" + from sanguo_trader.persistence import load_positions + + pos = load_positions(_db_path["path"], aid, "account") + return [ + {"symbol": sym, "volume": p["volume"], "frozen": p.get("frozen", 0), + "avg_price": p["avg_price"]} + for sym, p in pos.items() + ] + + +@router.get("/paper/{aid}/pending", dependencies=[Depends(verify_token)]) +def get_pending(aid: int): + """跨日 pending 订单(实走监控,Phase 3c)。""" + from sanguo_trader.persistence import load_pending_orders + + return load_pending_orders(_db_path["path"], aid) + + class _DataSourceWrapper: """包装 iter_bars/fetch_day 给 PaperEngine/live_orchestrator。""" diff --git a/tests/api/test_paper_routes.py b/tests/api/test_paper_routes.py index ef3091c..4ebfdee 100644 --- a/tests/api/test_paper_routes.py +++ b/tests/api/test_paper_routes.py @@ -90,3 +90,56 @@ def test_strategy_summary_aggregation(tmp_path): assert summary["s1"]["filled"] == 2 assert summary["s1"]["rejected"] == 1 assert summary["s2"]["filled"] == 1 + + +def test_positions_endpoint(tmp_path): + """Phase 3c:当前持仓快照({symbol:{volume,frozen,avg_price}} → list)。""" + from sanguo_trader.persistence import save_positions + + c, token = _client(tmp_path) + db = os.path.join(str(tmp_path), "p.db") + aid = c.post( + "/api/v1/paper/create", + json={"symbols": ["600000"], + "strategies": [{"name": "S", "symbol": "600000"}], + "start": "2024-01-01", "end": "2024-06-30"}, + headers=_auth(token), + ).json()["account_id"] + save_positions(db, aid, "account", + {"600000": {"volume": 100, "frozen": 0, "avg_price": 10.5}}, + "2024-01-15") + resp = c.get(f"/api/v1/paper/{aid}/positions", headers=_auth(token)) + assert resp.status_code == 200 + data = resp.json() + assert len(data) == 1 + assert data[0]["symbol"] == "600000" + assert data[0]["volume"] == 100 + assert data[0]["frozen"] == 0 + assert data[0]["avg_price"] == 10.5 + + +def test_pending_endpoint(tmp_path): + """Phase 3c:跨日 pending 订单(C-S3)。""" + from sanguo_trader.persistence import save_pending_orders + + c, token = _client(tmp_path) + db = os.path.join(str(tmp_path), "p.db") + aid = c.post( + "/api/v1/paper/create", + json={"symbols": ["600000"], + "strategies": [{"name": "S", "symbol": "600000"}], + "start": "2024-01-01", "end": "2024-06-30"}, + headers=_auth(token), + ).json()["account_id"] + save_pending_orders(db, aid, [ + {"strategy_id": "s1", "symbol": "600000", "side": "buy", + "price": 10.0, "volume": 100, "is_market": True, + "match_session": "next_open", "listing_days": 0}, + ]) + resp = c.get(f"/api/v1/paper/{aid}/pending", headers=_auth(token)) + assert resp.status_code == 200 + data = resp.json() + assert len(data) == 1 + assert data[0]["symbol"] == "600000" + assert data[0]["side"] == "buy" + assert data[0]["is_market"] is True