chore: init qmt_bridge repo (HTTP+WS bridge, MCP endpoint, docs, references)

This commit is contained in:
Docker
2026-08-26 16:53:15 +08:00
commit 22a5b8ca04
210 changed files with 68176 additions and 0 deletions
@@ -0,0 +1,7 @@
datetime,symbol,open,high,low,close,volume,prev_close
2026-01-05 09:30:00,600000.SH,10.00,10.05,9.98,10.02,100000,9.95
2026-01-05 09:31:00,600000.SH,10.02,10.08,10.01,10.07,120000,9.95
2026-01-05 09:32:00,600000.SH,10.07,10.12,10.06,10.11,110000,9.95
2026-01-05 09:33:00,600000.SH,10.11,10.13,10.05,10.06,130000,9.95
2026-01-06 09:30:00,600000.SH,10.08,10.10,10.00,10.02,150000,10.06
2026-01-06 09:31:00,600000.SH,10.02,10.04,9.96,9.98,140000,10.06
1 datetime symbol open high low close volume prev_close
2 2026-01-05 09:30:00 600000.SH 10.00 10.05 9.98 10.02 100000 9.95
3 2026-01-05 09:31:00 600000.SH 10.02 10.08 10.01 10.07 120000 9.95
4 2026-01-05 09:32:00 600000.SH 10.07 10.12 10.06 10.11 110000 9.95
5 2026-01-05 09:33:00 600000.SH 10.11 10.13 10.05 10.06 130000 9.95
6 2026-01-06 09:30:00 600000.SH 10.08 10.10 10.00 10.02 150000 10.06
7 2026-01-06 09:31:00 600000.SH 10.02 10.04 9.96 9.98 140000 10.06
@@ -0,0 +1,22 @@
{
"initial_cash": 1000000,
"initial_positions": {},
"buy_commission_rate": 0.0003,
"sell_commission_rate": 0.0003,
"min_commission": 5,
"stamp_tax_rate": 0.0005,
"transfer_fee_rate": 0.00001,
"slippage_bps": 0,
"max_volume_participation": 0.1,
"price_limit_rate": 0.1,
"lot_size": 100,
"time_in_force": "NEXT_BAR",
"seed": 0,
"fee_schedule": "a_share_2023_08_28",
"market_rules_version": "a_share_v1",
"strategy_name": "ma_example",
"parameters": {
"fast": 2,
"slow": 3
}
}
@@ -0,0 +1,69 @@
"""Example external moving-average strategy for the ZMQ backtest bridge."""
import argparse
from bigqmt_backtest.client import BacktestZmqClient
from bigqmt_backtest.strategy import ExternalStrategyRunner
class MovingAverageStrategy(object):
def __init__(self, symbol, fast=5, slow=20):
self.symbol = symbol
self.fast = int(fast)
self.slow = int(slow)
self.sequence = 0
def on_bar(self, context, bars):
if self.symbol not in bars:
return []
rows = context.history(self.symbol, count=self.slow, fields=["close"])
if len(rows) < self.slow:
return []
closes = [float(row["close"]) for row in rows]
fast_value = sum(closes[-self.fast :]) / self.fast
slow_value = sum(closes) / self.slow
position = context.positions.get(self.symbol, {})
quantity = int(position.get("quantity") or 0)
available = int(position.get("available") or 0)
self.sequence += 1
if fast_value > slow_value and quantity == 0:
return [
{
"client_order_id": "ma-buy-%d" % self.sequence,
"symbol": self.symbol,
"side": "BUY",
"quantity": 100,
"order_type": "MARKET",
}
]
if fast_value < slow_value and available > 0:
return [
{
"client_order_id": "ma-sell-%d" % self.sequence,
"symbol": self.symbol,
"side": "SELL",
"quantity": available,
"order_type": "MARKET",
}
]
return []
def main():
parser = argparse.ArgumentParser()
parser.add_argument("--endpoint", default="tcp://127.0.0.1:16661")
parser.add_argument("--run-id", default="", help="Optional; discovered from QMT when omitted")
parser.add_argument("--symbol", required=True)
parser.add_argument("--fast", type=int, default=5)
parser.add_argument("--slow", type=int, default=20)
args = parser.parse_args()
with BacktestZmqClient(args.endpoint, args.run_id, client_id="ma-example") as client:
result = ExternalStrategyRunner(
client,
MovingAverageStrategy(args.symbol, fast=args.fast, slow=args.slow),
).run()
print(result)
if __name__ == "__main__":
main()