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