Files
sanguo_vnpy_v2/tests/api/test_paper_routes.py
T

146 lines
5.3 KiB
Python

"""模拟盘 API 路由测试(spec §10)。"""
import os
from fastapi.testclient import TestClient
from sanguo_api.app import create_app
from sanguo_api.auth import create_token, set_jwt_config
from sanguo_api.routes_paper import set_db_path
def _client(tmp_path):
set_jwt_config(secret="t", expire_minutes=60)
db = os.path.join(str(tmp_path), "p.db")
app = create_app(db_path=db)
set_db_path(db)
return TestClient(app), create_token("admin")
def _auth(token):
return {"Authorization": f"Bearer {token}"}
def test_create_paper(tmp_path):
c, token = _client(tmp_path)
resp = c.post(
"/api/v1/paper/create",
json={
"symbols": ["600000"],
"strategies": [{"name": "DoubleMa", "symbol": "600000",
"match_session": "next_open"}],
"start": "2024-01-01", "end": "2024-06-30",
"initial_capital": 1_000_000,
},
headers=_auth(token),
)
assert resp.status_code == 200
assert "account_id" in resp.json()
def test_get_paper_and_empty_trades(tmp_path):
c, token = _client(tmp_path)
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"]
assert c.get(f"/api/v1/paper/{aid}", headers=_auth(token)).status_code == 200
assert c.get(f"/api/v1/paper/{aid}/trades", headers=_auth(token)).json() == []
assert c.get(f"/api/v1/paper/{aid}/equity", headers=_auth(token)).json() == []
def test_get_paper_404(tmp_path):
c, token = _client(tmp_path)
assert c.get("/api/v1/paper/999", headers=_auth(token)).status_code == 404
def test_unauthorized_401(tmp_path):
c, _ = _client(tmp_path)
assert c.get("/api/v1/paper/1").status_code == 401
def test_strategy_summary_aggregation(tmp_path):
"""C-S2 归因:分策略成交/拒单/费用聚合(spec §7)。"""
from sanguo_trader.persistence import init_db, save_account, save_trade
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"]
# 造假 2 笔成交 + 1 拒单(s1),1 成交(s2)
save_trade(db, aid, {"strategy_id": "s1", "symbol": "600000", "price": 10,
"volume": 100, "commission": 5, "transfer_fee": 0.02})
save_trade(db, aid, {"strategy_id": "s1", "symbol": "600000", "price": 11,
"volume": 100, "commission": 5, "stamp_duty": 0.55,
"transfer_fee": 0.02})
save_trade(db, aid, {"strategy_id": "s1", "symbol": "300750"},
rejected=True, reject_reason="limit_up_locked")
save_trade(db, aid, {"strategy_id": "s2", "symbol": "000001", "price": 15,
"volume": 100, "commission": 5})
resp = c.get(f"/api/v1/paper/{aid}/strategies", headers=_auth(token))
assert resp.status_code == 200
summary = {s["strategy_id"]: s for s in resp.json()}
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