完成预下单优化

This commit is contained in:
2025-11-19 10:29:58 +08:00
parent d5fef7c0c1
commit 0262bfc71b
3 changed files with 58 additions and 44 deletions
-3
View File
@@ -119,19 +119,16 @@ class QmtV(XtQuantTraderCallback):
# ====== 市场回调方法 -- 以下方法由XtQuantData调用 ======
def onDataUpdate(self, data):
# 收集所有市场数据用于市场监控
PrintLog(LogLevel.INFO, f'- [市场数据更新] {len(data)}')
eBus.event_bus.publish(eBus.MarketDataUpdate, data)
now = time.time()
if now - self.lastMarketDataUpdateTimestamp < 5:
self.isMarketActive = True
PrintLog(LogLevel.INFO, f'- [市场状态变更] 市场已 Active') # 市场已 inactive
self.lastMarketDataUpdateTimestamp = now
def marketStatusNotifier(self):
# 市场状态通知器
tmpMarketStatus = False
while True:
PrintLog(LogLevel.INFO, f'- [市场状态检查器] {self.isMarketActive}')
tmpTime = time.time()
time.sleep(10)
if tmpMarketStatus != self.isMarketActive and tmpTime - self.lastMarketDataUpdateTimestamp < 5:
+55 -38
View File
@@ -24,8 +24,16 @@ class SFGridStrategy:
self.todayDownStopPrice=qmtv.dailyDownStop(tradeTarget.stock_code) # type: ignore
PrintLog(LogLevel.INFO, f'|- 标的{tradeTarget.targetName()}初始化: 停涨价 {self.todayUpStopPrice}, 停跌价 {self.todayDownStopPrice}')
self.orderGrid = {} # grid index, order_seq | order_id
self.loadExistOrders()
self.enabledTrading(tradeTarget.enabled) # type: ignore
self.dataUpdateLock = threading.Lock()
def loadExistOrders(self):
orders = qmtv.queryPendingOrder(self.tradeTarget.stock_code, self.getName()) # type: ignore
for order in orders:
gridIdx = int(order.order_remark.split(',')[1])
self.orderGrid[gridIdx] = order.order_id
PrintLog(LogLevel.INFO, f'|- 标的[{self.tradeTarget.targetName()}] 初始化: 加载现有订单, grid-{gridIdx} order_id:{self.orderGrid[gridIdx]}')
def onMarketActiveSwitch(self, isActive: bool):
if isActive and self.tradeTarget.enabled:
@@ -48,39 +56,50 @@ class SFGridStrategy:
OrderTypeInit, # remark # type: ignore
self.getName(), # strategy_name
)
self.orderGrid[xtconstant.STOCK_BUY] = tmpOrderSeq # seq
self.orderGrid[1] = tmpOrderSeq # seq
PrintLog(LogLevel.INFO, f'|- 标的[{self.tradeTarget.targetName()}] 初始化: 建仓单,建仓价: {price:.3f}')
else:
currentIdx = self.tradeTarget.grid_index # type: ignore
orders = qmtv.queryPendingOrder(self.tradeTarget.stock_code, self.getName()) # type: ignore
# 向上下一单,向下下一单
if currentIdx > 0: # 可以下空单
sellPrice = self.tradeTarget.getPriceGrid()[currentIdx - 1]
tmpOrderSeq = qmtv.orderAsync(
str(self.tradeTarget.stock_code),
self.tradeTarget.grid_volume,
xtconstant.STOCK_SELL,
sellPrice,
xtconstant.FIX_PRICE,
OrderTypeSell, # remark # type: ignore
self.getName(), # strategy_name
)
self.orderGrid[xtconstant.STOCK_SELL] = tmpOrderSeq # seq
PrintLog(LogLevel.INFO, f'|- 标的[{self.tradeTarget.targetName()}] 初始化: 下空单,价格: {sellPrice:.3f}')
sellIdx = currentIdx - 1
sellPrice = self.tradeTarget.getPriceGrid()[sellIdx]
remark = f'{OrderTypeSell},{sellIdx}'
if len([order for order in orders if order.order_type == xtconstant.STOCK_SELL and order.price == sellPrice]) == 0:
# 不存在策略内同价位订单,下单
tmpOrderSeq = qmtv.orderAsync(
str(self.tradeTarget.stock_code),
self.tradeTarget.grid_volume,
xtconstant.STOCK_SELL,
sellPrice,
xtconstant.FIX_PRICE,
remark, # remark # type: ignore
self.getName(), # strategy_name
)
self.orderGrid[sellIdx] = tmpOrderSeq # seq
PrintLog(LogLevel.INFO, f'|- 标的[{self.tradeTarget.targetName()}] 初始化: 下空单,价格: {sellPrice:.3f}')
else:
PrintLog(LogLevel.INFO, f'|- 标的[{self.tradeTarget.targetName()}] 初始化: 已存在同价位空单,跳过下单')
if currentIdx < len(self.tradeTarget.getPriceGrid()) - 1: # 可以下多单
buyPrice = self.tradeTarget.getPriceGrid()[currentIdx + 1]
tmpOrderSeq = qmtv.orderAsync(
buyIdx = currentIdx + 1
buyPrice = self.tradeTarget.getPriceGrid()[buyIdx]
remark = f'{OrderTypeBuy},{buyIdx}'
if len([order for order in orders if order.order_type == xtconstant.STOCK_BUY and order.price == buyPrice]) == 0:
tmpOrderSeq = qmtv.orderAsync(
str(self.tradeTarget.stock_code),
self.tradeTarget.grid_volume,
xtconstant.STOCK_BUY,
buyPrice,
xtconstant.FIX_PRICE,
OrderTypeBuy, # remark # type: ignore
remark, # remark # type: ignore
self.getName(), # strategy_name
)
self.orderGrid[xtconstant.STOCK_BUY] = tmpOrderSeq # seq
PrintLog(LogLevel.INFO, f'|- 标的[{self.tradeTarget.targetName()}] 初始化: 下多单,价格: {buyPrice:.3f}')
self.orderGrid[buyIdx] = tmpOrderSeq # seq
PrintLog(LogLevel.INFO, f'|- 标的[{self.tradeTarget.targetName()}] 初始化: 下多单,价格: {buyPrice:.3f}')
else:
PrintLog(LogLevel.INFO, f'|- 标的[{self.tradeTarget.targetName()}] 初始化: 已存在同价位多单,跳过下单')
def deleteTradeTarget(self, tradeTarget:model.SFGridTradeTarget):
PrintLog(LogLevel.INFO, f'|- 标的{tradeTarget.targetName()}信息删除: START')
@@ -96,18 +115,18 @@ class SFGridStrategy:
self.tradeTarget.enabled = enabled # type: ignore
if enabled:
print(f" |- 标的{self.tradeTarget.targetName()}交易启动, 持仓量:{self.tradeTarget.current_position}")
PrintLog(LogLevel.INFO, f" |- 标的{self.tradeTarget.targetName()}交易启动, 持仓量:{self.tradeTarget.current_position}")
if self.tradeTarget.status == 0: # 未建仓
print(f" |- 标的{self.tradeTarget.targetName()}初始状态, 设置网格序号 1,")
PrintLog(LogLevel.INFO, f" |- 标的{self.tradeTarget.targetName()}初始状态, 设置网格序号 1,")
self.tradeTarget.grid_index = 1 # pyright: ignore[reportAttributeAccessIssue]
else: # 已建仓
# 交易阶段,检查仓位,检查现有订单
print(f" |- 标的{self.tradeTarget.targetName()}已有仓位或非初始状态 无需建初始仓 当前仓位: {self.tradeTarget.current_position} 状态: {self.tradeTarget.status}")
PrintLog(LogLevel.INFO, f" |- 标的{self.tradeTarget.targetName()}已有仓位或非初始状态 无需建初始仓 当前仓位: {self.tradeTarget.current_position} 状态: {self.tradeTarget.status}")
minRequirePosition:int = self.tradeTarget.grid_volume * int(self.tradeTarget.grid_index) # type: ignore
if minRequirePosition <= int(self.tradeTarget.current_position): # type: ignore
print(f' |- 仓位检查: 持仓需求充足, (gridVolume*gridIndex)={minRequirePosition}, 当前持仓:{self.tradeTarget.current_position}')
PrintLog(LogLevel.INFO, f' |- 仓位检查: 持仓需求充足, (gridVolume*gridIndex)={minRequirePosition}, 当前持仓:{self.tradeTarget.current_position}')
else:
print(f' |- 仓位检查: 持仓需求不足, (gridVolume*gridIndex)={minRequirePosition}, 当前持仓:{self.tradeTarget.current_position}, 交易启动失败')
PrintLog(LogLevel.INFO, f' |- 仓位检查: 持仓需求不足, (gridVolume*gridIndex)={minRequirePosition}, 当前持仓:{self.tradeTarget.current_position}, 交易启动失败')
self.tradeTarget.enabled = False # type: ignore
self.refreshGridOrder()
else:
@@ -128,11 +147,10 @@ class SFGridStrategy:
self.dataUpdateLock.acquire()
try:
if response.strategy_name == self.getName() and response.seq == self.tradeTarget.current_order_no:
print(f"委托创建通知 onOrderCreateAsync[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}]: {response.order_id}")
for gridIdx, orderNo in self.orderGrid.items():
if orderNo == response.seq:
self.orderGrid[gridIdx] = response.order_id
break
PrintLog(LogLevel.INFO, f"委托创建通知 onOrderCreateAsync[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}]: {response.order_id}")
idx = response.order_remark.split(',')[1]
self.orderGrid[idx] = response.order_id
PrintLog(LogLevel.INFO, f"委托创建通知 onOrderCreateAsync 更新 grid-{idx} seq:{response.seq} -> order_id:{response.order_id}")
except Exception as e:
PrintLog(LogLevel.ERROR, f"|- 委托创建通知 onOrderCreateAsync[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}]: {response.order_id} - {str(e)}")
finally:
@@ -159,24 +177,23 @@ class SFGridStrategy:
if tmpOrderNo == trade.order_id:
if idx > self.tradeTarget.grid_index:
type = "下移一格"
self.tradeTarget.grid_index +=1
elif idx < self.tradeTarget.grid_index:
type = "上移一格"
self.tradeTarget.grid_index -= 1
elif idx == self.tradeTarget.grid_index:
type = "保持格, 理论上不应该输出"
self.tradeTarget.grid_index = idx
self.saveProxy()
break
PrintLog(LogLevel.INFO, f'|- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} - 原网格位置 {oriIdx}, 现网格位置 {self.tradeTarget.grid_index}')
self.saveProxy()
self.printTradeReport(trade, type)
PrintLog(LogLevel.INFO, f"|- 成交报告[{self.tradeTarget.targetName()}] : ====================================")
PrintLog(LogLevel.INFO, f"|- 标的[{self.tradeTarget.targetName()}] {type}-单号{self.tradeTarget.current_order_no}已成交 ")
PrintLog(LogLevel.INFO, f' 成交价: {trade.traded_price} 成交量: {trade.traded_volume}')
PrintLog(LogLevel.INFO, f' 手续费 : {trade.commission:.3f}')
self.refreshGridOrder() # 更新网格订单
finally:
self.dataUpdateLock.release()
def printTradeReport(self, trade:XtTrade, type:str):
PrintLog(LogLevel.INFO, f"|- 成交报告[{self.tradeTarget.targetName()}] : ====================================")
PrintLog(LogLevel.INFO, f"|- 标的[{self.tradeTarget.targetName()}] {type}-单号{self.tradeTarget.current_order_no}已成交 ")
PrintLog(LogLevel.INFO, f' 成交价: {trade.traded_price} 成交量: {trade.traded_volume}')
PrintLog(LogLevel.INFO, f' 手续费 : {trade.commission:.3f}')
def getName(self):
+3 -3
View File
@@ -57,10 +57,10 @@ class TradeTargetUI(ttk.Frame):
if stock_code in self.stockCodeIdMap:
id:int = self.stockCodeIdMap[stock_code]
tradeTarget = self.tradeTargetData[id]
timeStr = datetime.fromtimestamp(tickData['time']/1000)
PrintLog(LogLevel.INFO, f'|- 市价更新[{tradeTarget.targetName()}] - {timeStr.strftime("%H:%M:%S")} 市场数据更新======================={id}')
# timeStr = datetime.fromtimestamp(tickData['time']/1000)
lastPrice = float("{:.3f}".format(tickData['lastPrice']))
tradeTarget.market_price = lastPrice # type: ignore
# PrintLog(LogLevel.INFO, f'|- 市价更新[{tradeTarget.targetName()}] - {timeStr.strftime("%H:%M:%S")} 市价更新: {lastPrice}======================{id}')
self.updateTradeTarget(tradeTarget, False) # 市价更新
else:
# 非目标交易,发布市场数据更新事件用于市场监控
@@ -151,7 +151,7 @@ class TradeTargetUI(ttk.Frame):
while True:
self.after(0, self.refresh_table)
self.after(0, self.populate_market_table)
time.sleep(0.2) # 每0.5秒刷新一次
time.sleep(0.5) # 每0.5秒刷新一次
def create_tables_area(self, parent):