Files

96 lines
3.8 KiB
Python

# -*- coding: utf-8 -*-
"""Local test for trade endpoints (mock QMT). Run with QMT pythonw."""
import sys, io, os, json, time, urllib.request
if sys.stdout is None:
sys.stdout = io.StringIO()
if sys.stderr is None:
sys.stderr = io.StringIO()
RESULT = r"C:\Users\Docker\Development\qmt_bridge\tests\trade_test.txt"
SRC = os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "src")
sys.path.insert(0, SRC)
def log(msg):
with open(RESULT, "a") as f:
f.write(msg + "\n")
import bridge_util, bridge_http_server, bridge_data_adapter
class FakeCtx:
def get_market_data_ex(self, fields, codes, **kw):
import pandas as pd
df = pd.DataFrame({"open": [1.0], "close": [1.1]})
return {codes[0]: df}
def get_full_tick(self, codes):
return {c: {"lastPrice": 1.0} for c in codes}
def get_instrument_detail(self, code):
return {"InstrumentName": "贵州茅台", "UpStopPrice": 1438.67,
"DownStopPrice": 1177.09, "OpenDate": "20010827"}
def get_trading_dates(self, start="", end=""):
return ["20260818", "20260819", "20260820"]
bridge_util.CTX = FakeCtx()
bridge_util.ACCOUNT = "TESTACC"
def fake_trade(acct, atype, dtype):
if dtype == "position":
return [type("Pos", (), {"m_strInstrumentID": "600519", "m_strInstrumentName": "贵州茅台",
"m_nVolume": 100, "m_nCanUseVolume": 50,
"m_nFrozenVolume": 50, "m_dOpenPrice": 1500.0,
"m_dFloatProfit": 1000.0})()]
return [type("Pos", (), {"m_strInstrumentID": "600519.SH", "m_nVolume": 100,
"m_nCanUseVolume": 50, "m_dOpenPrice": 1500.0})()]
bridge_util.QMT_API["get_trade_detail_data"] = fake_trade
bridge_http_server.PORT = 18631
bridge_http_server.TOKEN = ""
bridge_http_server.ACCOUNT = "TESTACC"
# prime the trade cache by simulating a strategy-thread refresh
bridge_util._refresh_trade_cache("TESTACC", "STOCK")
bridge_http_server.start_server()
time.sleep(0.8)
BASE = "http://127.0.0.1:18631"
def get(path):
with urllib.request.urlopen(BASE + path, timeout=5) as r:
return json.loads(r.read().decode())
def check_positions():
"""Assert /trade/positions returns semantic fields + summary."""
r = get("/trade/positions")
data = r["data"]
assert r["ok"] is True, "positions ok flag"
assert "summary" in data, "summary present"
assert data["summary"]["count"] == 1, "summary count"
pos = data["positions"][0]
assert pos["stock_code"] == "600519.SH", "stock_code full"
assert pos["stock_name"] == "贵州茅台", "stock_name"
assert pos["volume"] == 100, "volume"
assert pos["available"] == 50, "available"
assert pos["avg_price"] == 1500.0, "avg_price"
assert pos["price"] == 1500.0, "price fallback to open"
assert pos["market_value"] == 150000.0, "market_value computed"
assert pos["profit"] == 1000.0, "profit from m_dFloatProfit"
assert pos["profit_pct"] == 0.67, "profit_pct computed"
# raw m_* fields preserved as superset
assert pos["m_strInstrumentID"] == "600519", "raw m_strInstrumentID"
assert pos["m_nVolume"] == 100, "raw m_nVolume"
log("OK positions enriched -> %s" % str(r)[:200])
for ep in ["/health", "/openapi.json", "/docs",
"/data/kline?code=600519.SH&period=1d&count=1",
"/data/quote?code=600519.SH", "/data/instrument?code=600519.SH",
"/data/calendar/trading_dates?start=20260818&end=20260820",
"/trade/positions", "/trade/asset",
"/trade/orders", "/trade/trades"]:
try:
if ep == "/trade/positions":
check_positions()
continue
r = get(ep)
log("OK %s -> %s" % (ep, str(r)[:80]))
except Exception as e:
log("FAIL %s -> %s" % (ep, str(e)[:80]))
bridge_http_server.stop_server()
log("=== done ===")