框架调整

This commit is contained in:
2025-10-28 17:15:37 +08:00
parent 26cf98ce17
commit 5dbf4b79d9
6 changed files with 124 additions and 100 deletions
-68
View File
@@ -1,68 +0,0 @@
from xttrader import XtQuantTraderCallback
import datetime
class MyXtQuantTraderCallback(XtQuantTraderCallback):
def on_disconnected(self):
"""
连接断开
:return:
"""
print(datetime.datetime.now(), '连接断开回调')
def on_stock_order(self, order):
"""
委托回报推送
:param order: XtOrder对象
:return:
"""
print(datetime.datetime.now(), '委托回调 投资备注', order.order_remark)
def on_stock_trade(self, trade):
"""
成交变动推送
:param trade: XtTrade对象
:return:
"""
print(datetime.datetime.now(), '成交回调', trade.order_remark, f"委托方向(48买 49卖) {trade.offset_flag} 成交价格 {trade.traded_price} 成交数量 {trade.traded_volume}")
def on_order_error(self, order_error):
"""
委托失败推送
:param order_error:XtOrderError 对象
:return:
"""
# print("on order_error callback")
# print(order_error.order_id, order_error.error_id, order_error.error_msg)
print(f"委托报错回调 {order_error.order_remark} {order_error.error_msg}")
def on_cancel_error(self, cancel_error):
"""
撤单失败推送
:param cancel_error: XtCancelError 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)
def on_order_stock_async_response(self, response):
"""
异步下单回报推送
:param response: XtOrderResponse 对象
:return:
"""
print(f"异步委托回调 投资备注: {response.order_remark}")
def on_cancel_order_stock_async_response(self, response):
"""
:param response: XtCancelOrderResponse 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)
def on_account_status(self, status):
"""
:param response: XtAccountStatus 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)
BIN
View File
Binary file not shown.
+97 -21
View File
@@ -2,37 +2,40 @@
import time, sys import time, sys
sys.stdout.reconfigure(encoding='utf-8') # 设置标准输出编码为UTF-8 sys.stdout.reconfigure(encoding='utf-8') # 设置标准输出编码为UTF-8
import strategy_db import strategy_db
from stock_trade_controller import StockTradeController import sfgrid_constants
from sfgrid_trade_controller import StockTradeController
from util import getInstrumentName, getStockPosition from util import getInstrumentName, getStockPosition
from xtquant.xttrader import XtQuantTrader from xtquant.xttrader import XtQuantTrader
from xtquant.xttype import StockAccount from xtquant.xttype import StockAccount
from xtquant import xtdata from xtquant import xtdata
from xtquant.xttrader import XtQuantTraderCallback
import datetime
class SFGridController: class SFGridController(XtQuantTraderCallback):
def __init__(self, account_no: str = '99082560'): def __init__(self, account_no: str, miniQmtPath: str):
print('=== 数据库模块初始化 ===\n') super().__init__()
xtdata.enable_hello = False
strategy_db.db.connect() strategy_db.db.connect()
strategy_db.db.create_tables([strategy_db.TradeTarget]) strategy_db.db.create_tables([strategy_db.TradeTarget])
print('=== 三疯网格策略控制器初始化 ===\n') print('- 数据库模块初始化完成')
self.init_instrument_pool() self.init_trader(miniQmtPath)
self.init_trader(r'D:\\Programs\\DTQMT\\userdata_mini')
self.init_trade_account(account_no, 'STOCK') self.init_trade_account(account_no, 'STOCK')
self.grid_price = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1]
self.stock_trade_ctrl = {} self.stock_trade_ctrl = {}
self.init_instrument_pool()
self.seq = None self.seq = None
print('=== 三疯网格策略控制器初始化完成 ===\n') print('- 三疯交易系统初始化完成')
def startMarketData(self): def startMarketData(self):
print('=== 三疯网格策略 启动市场数据接收 ===\n') print('- 启动市场数据订阅')
self.seq = xtdata.subscribe_whole_quote(['SH', 'SZ'], callback=self.onDataUpdate) self.seq = xtdata.subscribe_whole_quote(['SH', 'SZ'], callback=self.onDataUpdate)
if self.seq == -1: if self.seq == -1:
print('市场数据订阅失败\n') print('- 市场数据订阅失败')
else: else:
print(f'市场数据订阅成功, 订阅号={self.seq}\n') print(f'- 市场数据订阅成功, 订阅号={self.seq}')
def stopMarketData(self): def stopMarketData(self):
print('=== 三疯网格策略 停止市场数据接收 ===\n') print('- 停止市场数据订阅')
if self.seq is not None and self.seq > 0: if self.seq is not None and self.seq > 0:
xtdata.unsubscribe_quote(self.seq) xtdata.unsubscribe_quote(self.seq)
@@ -80,13 +83,14 @@ class SFGridController:
def init_trader(self, path): def init_trader(self, path):
session_id = int(time.time()) session_id = int(time.time())
self.xt_trader = XtQuantTrader(path, session_id) self.xt_trader = XtQuantTrader(path, session_id)
self.xt_trader.register_callback(self)
self.xt_trader.start() self.xt_trader.start()
self.xt_trader.connect() self.xt_trader.connect()
print(f'交易对象初始化完成, {self.xt_trader.connected}') print(f'- 交易对象初始化完成, {self.xt_trader.connected}')
def init_trade_account(self, account_id, account_type): def init_trade_account(self, account_id, account_type):
self.account= StockAccount(account_id, account_type) self.account= StockAccount(account_id, account_type)
print(f'交易账号对象初始化完成, {self.account}') print(f'- 交易账号对象初始化完成, 账号: {self.account.account_id}')
def init_instrument_pool(self): def init_instrument_pool(self):
self.instrument_pool = strategy_db.TradeTarget.select() self.instrument_pool = strategy_db.TradeTarget.select()
@@ -95,20 +99,20 @@ class SFGridController:
stockTradeController = StockTradeController(tradeTarget, self.xt_trader, self.account, tradeTarget.enabled) stockTradeController = StockTradeController(tradeTarget, self.xt_trader, self.account, tradeTarget.enabled)
self.stock_trade_ctrl[tradeTarget.stock_code] = stockTradeController self.stock_trade_ctrl[tradeTarget.stock_code] = stockTradeController
print(f'初始化标的池初始化完成 , 共 {len(self.instrument_pool)} 个标的\n')
self.print_pool() self.print_pool()
print(f'- 初始化标的池初始化完成 , 共 {len(self.instrument_pool)} 个标的')
def print_pool(self): def print_pool(self):
print("\n=== 标的池信息 ===") print("- 标的池信息")
for i in range(len(self.instrument_pool)): for i in range(len(self.instrument_pool)):
target: strategy_db.TradeTarget = self.instrument_pool[i] target: strategy_db.TradeTarget = self.instrument_pool[i]
status = "新建" if target.status == 0 else "已建初始仓" status = "新建" if target.status == 0 else "已建初始仓"
print(f"[Index-{i}] 股票代码: {target.stock_code}-{target.stock_name} 当前持仓: {target.current_position} 网格索引: {target.grid_index+1} Price {self.grid_price[target.grid_index]} 状态: {status} 启用交易线程: {target.enabled}") print(f"|- [序号-{i}] 股票代码: {target.stock_code}-{target.stock_name} 当前持仓: {target.current_position} 网格索引: {target.grid_index+1} Price {sfgrid_constants.grid_price[target.grid_index]} 状态: {status} 启用交易线程: {target.enabled}")
def print_position_info(self): def print_position_info(self):
positions = self.xt_trader.query_stock_positions(self.account) positions = self.xt_trader.query_stock_positions(self.account)
if positions: if positions:
print("\n=== 持仓信息 ===") print("\n- 持仓信息")
for pos in positions: for pos in positions:
if pos.m_nVolume <=0: if pos.m_nVolume <=0:
continue continue
@@ -145,7 +149,7 @@ class SFGridController:
print("\n当前无委托记录") print("\n当前无委托记录")
# 初始化指定标的交易线程 # 初始化指定标的交易控制器
def start_stock_trade(self, index: int): def start_stock_trade(self, index: int):
tradeTarget = self.instrument_pool[index] tradeTarget = self.instrument_pool[index]
# check existing thread # check existing thread
@@ -159,7 +163,7 @@ class SFGridController:
else: else:
stockTradeController = StockTradeController(tradeTarget, self.xt_trader, self.account, tradeTarget.enabled) stockTradeController = StockTradeController(tradeTarget, self.xt_trader, self.account, tradeTarget.enabled)
self.stock_trade_ctrl[tradeTarget.stock_code] = stockTradeController self.stock_trade_ctrl[tradeTarget.stock_code] = stockTradeController
print(f"创建标的交易控制器 {tradeTarget.stock_code} {getInstrumentName(tradeTarget.stock_code)}\n") print(f"|- 创建标的交易控制器 {tradeTarget.stock_code} {getInstrumentName(tradeTarget.stock_code)}")
def pause_stock_trade(self, index: int): def pause_stock_trade(self, index: int):
@@ -174,3 +178,75 @@ class SFGridController:
else: else:
print(f"标的交易控制器不存在 {tradeTarget.stock_code} {getInstrumentName(tradeTarget.stock_code)}\n") print(f"标的交易控制器不存在 {tradeTarget.stock_code} {getInstrumentName(tradeTarget.stock_code)}\n")
# ====== 市场回调方法 -- 以下方法由XtQuantTrader调用 ======
def on_connected(self):
"""
连接成功推送
"""
print(datetime.datetime.now(), '连接成功回调')
def on_disconnected(self):
"""
连接断开
:return:
"""
print(datetime.datetime.now(), '连接断开回调')
def on_stock_order(self, order):
"""
委托回报推送
:param order: XtOrder对象
:return:
"""
print(datetime.datetime.now(), '委托回调 投资备注', order.order_remark)
def on_stock_trade(self, trade):
"""
成交变动推送
:param trade: XtTrade对象
:return:
"""
print(datetime.datetime.now(), '成交回调', trade.order_remark, f"委托方向(48买 49卖) {trade.offset_flag} 成交价格 {trade.traded_price} 成交数量 {trade.traded_volume}")
def on_order_error(self, order_error):
"""
委托失败推送
:param order_error:XtOrderError 对象
:return:
"""
# print("on order_error callback")
# print(order_error.order_id, order_error.error_id, order_error.error_msg)
print(f"委托报错回调 {order_error.order_remark} {order_error.error_msg}")
def on_cancel_error(self, cancel_error):
"""
撤单失败推送
:param cancel_error: XtCancelError 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)
def on_order_stock_async_response(self, response):
"""
异步下单回报推送
:param response: XtOrderResponse 对象
:return:
"""
print(f"异步委托回调 投资备注: {response.order_remark}")
def on_cancel_order_stock_async_response(self, response):
"""
:param response: XtCancelOrderResponse 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)
def on_account_status(self, status):
"""
:param response: XtAccountStatus 对象
:return:
"""
print(datetime.datetime.now(), sys._getframe().f_code.co_name)
+4
View File
@@ -0,0 +1,4 @@
miniQMTPath = r'D:\\Programs\\DTQMT\\userdata_mini' # miniQMT软件的安装路径
grid_price = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] # 网格价格设置,从高到低
grid_volume = 100 # 每个网格的交易手数
account_no = '99082560' # 交易账号
@@ -1,33 +1,43 @@
import threading
import time
from strategy_db import TradeTarget from strategy_db import TradeTarget
import strategy_db import strategy_db
from util import getInstrumentName, getStockPosition from util import getInstrumentName, getStockPosition
from xtquant import xttrader, xtdata
from xtquant import xttrader, xtdata, xtconstant
from xtquant.xttype import StockAccount from xtquant.xttype import StockAccount
import sfgrid_constants
class StockTradeController: class StockTradeController:
def __init__(self, tradeTarget: TradeTarget, xt_trader: xttrader.XtQuantTrader, account: StockAccount, enabled: bool = False): def __init__(self, tradeTarget: TradeTarget, xt_trader: xttrader.XtQuantTrader, account: StockAccount, enabled: bool = False):
super().__init__() #必须调用父类的初始化方法
self.tradeTarget = tradeTarget self.tradeTarget = tradeTarget
self.xt_trader = xt_trader self.xt_trader = xt_trader
self.account = account self.account = account
self.currentPosition = getStockPosition(self.tradeTarget.stock_code, self.xt_trader, self.account) self.currentPosition = getStockPosition(self.tradeTarget.stock_code, self.xt_trader, self.account)
self.tradeRecords = strategy_db.TradeRecord.select().where(strategy_db.TradeRecord.stock_code == self.tradeTarget.stock_code).order_by(strategy_db.TradeRecord.trade_time.desc()) self.tradeRecords = strategy_db.TradeRecord.select().where(strategy_db.TradeRecord.stock_code == self.tradeTarget.stock_code).order_by(strategy_db.TradeRecord.trade_time.desc())
print(f"创建标的交易线程 {self.tradeTarget.stock_code} {getInstrumentName(self.tradeTarget.stock_code)} {tradeTarget}\n") print(f"|- 创建标的 {tradeTarget.stock_code} {getInstrumentName(tradeTarget.stock_code)} 交易控制器")
xtdata.subscribe_quote(tradeTarget.stock_code, period='tick', start_time='', end_time='', count=0, callback=self.onDataUpdate)
def enabledTrading(self, enabled: bool): def enabledTrading(self, enabled: bool):
self.tradeTarget.enabled = enabled self.tradeTarget.enabled = enabled
self.tradeTarget.save() self.tradeTarget.save()
# 建仓状态检查
if self.tradeTarget.current_position == 0 and self.tradeTarget.status == 0:
self.tradeTarget.grid_index = 1
self.tradeTarget.save()
self.initBuyOrderId = self.xt_trader.order_stock(
self.account,
self.tradeTarget.stock_code,
xtconstant.STOCK_BUY,
sfgrid_constants.grid_volume,
xtconstant.FIX_PRICE,
sfgrid_constants.grid_price[self.tradeTarget.grid_index],
'sf_grid', f'{self.tradeTarget.stock_code}_init_buy')
def isEnabled(self) -> bool: def isEnabled(self) -> bool:
return self.tradeTarget.enabled return self.tradeTarget.enabled
def onDataUpdate(self, data): def onDataUpdate(self, data):
if self.isEnabled(): if self.isEnabled():
print(f"标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 行情数据更新 {data[self.tradeTarget.stock_code]}\n") print(f"标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 行情数据更新 {data[self.tradeTarget.stock_code]}\n")
+6 -4
View File
@@ -1,7 +1,9 @@
# coding:utf-8 # coding:utf-8
import sys import sys
import sfgrid_constants
sys.stdout.reconfigure(encoding='utf-8') # 设置标准输出编码为UTF-8 sys.stdout.reconfigure(encoding='utf-8') # 设置标准输出编码为UTF-8
from strategy_controller import SFGridController from main_controller import SFGridController
ctrl:SFGridController ctrl:SFGridController
@@ -37,8 +39,8 @@ def pauseTrade(index:int):
def help(): def help():
print("可用命令:") print("可用命令:")
print(" ===================================================") print(" ===================================================")
print(" startMarketData() - 启动市场数据接收") print(" startMarketData() - 启动市场数据接收")
print(" stopMarketData() - 停止市场数据接收") print(" stopMarketData() - 停止市场数据接收")
print(" addTradeTarget(stock_code) - 添加交易标的") print(" addTradeTarget(stock_code) - 添加交易标的")
print(" accountInfo() - 打印账户信息") print(" accountInfo() - 打印账户信息")
print(" positionInfo() - 打印持仓信息") print(" positionInfo() - 打印持仓信息")
@@ -49,6 +51,6 @@ def help():
print(" ctrl - 访问控制器实例") print(" ctrl - 访问控制器实例")
if __name__ == '__main__': if __name__ == '__main__':
ctrl = SFGridController('99082560') ctrl = SFGridController(sfgrid_constants.account_no, sfgrid_constants.miniQMTPath)
# 交互阻塞 # 交互阻塞
interact() interact()