chore: init qmt_bridge repo (HTTP+WS bridge, MCP endpoint, docs, references)
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# -*- 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 ===")
|
||||
Reference in New Issue
Block a user