diff --git a/core/qmt.py b/core/qmt.py index 06456fc..6095a9c 100644 --- a/core/qmt.py +++ b/core/qmt.py @@ -14,6 +14,7 @@ class QmtV(XtQuantTraderCallback): def __init__(self) -> None: self.xttrader: XtQuantTrader self.inited: bool = False + self.details = {} def getTrader(self) -> XtQuantTrader: return self.xttrader @@ -78,13 +79,21 @@ class QmtV(XtQuantTraderCallback): strategy_name, # strategy_name orderRemark # remark # type: ignore ) + + def cacheStockDetail(self, stock_code:str): + if stock_code in self.details: + return self.details[stock_code] + else: + self.details[stock_code] = xtdata.get_instrument_detail(stock_code, False) + return self.details[stock_code] def getInstrumentName(self, stock_code:str): - # print(f"getInstrumentName: 获取标的名称 {stock_code}") - detail = xtdata.get_instrument_detail(stock_code, False) - if detail is None: - return None - return detail['InstrumentName'] + return self.cacheStockDetail(stock_code)['InstrumentName'] + + def dailyUpStop(self, stock_code:str): + return self.cacheStockDetail(stock_code)['UpStopPrice'] + def dailyDownStop(self, stock_code:str): + return self.cacheStockDetail(stock_code)['DownStopPrice'] # def print_position_info(self): # positions:list[XtPosition] = self.xt_trader.query_stock_positions(self.account) diff --git a/core/sfgrid/sfgrid_strategy.py b/core/sfgrid/sfgrid_strategy.py index 60f268a..d8506e1 100644 --- a/core/sfgrid/sfgrid_strategy.py +++ b/core/sfgrid/sfgrid_strategy.py @@ -20,20 +20,23 @@ class SFGridStrategy: self.enabledTrading(tradeTarget.enabled) # type: ignore event_bus.subscribe(eBus.MarketOrderCreated, self.onOrderCreateAsync) event_bus.subscribe(eBus.MarketOrderTraded, self.onOrderTrade) + self.todayUpStopPrice=qmtv.dailyUpStop(tradeTarget.stock_code) # type: ignore + self.todayDownStopPrice=qmtv.dailyDownStop(tradeTarget.stock_code) # type: ignore self.refreshPlanPrice() self.dataUpdateLock = threading.Lock() def updateTradeTarget(self, inTradeTarget:model.SFGridTradeTarget): - PrintLog(LogLevel.INFO, f'|- 标的{self.tradeTarget.targetName()}信息更新: START') - self.dataUpdateLock.acquire() - PrintLog(LogLevel.INFO ,f'|- 标的{self.tradeTarget.targetName()}信息更新: LOCKED') - try: - self.tradeTarget = inTradeTarget - finally: - PrintLog(LogLevel.INFO ,f'|- 标的{self.tradeTarget.targetName()}信息更新: UNLOCKED') - self.dataUpdateLock.release() - self.refreshPlanPrice() - PrintLog(LogLevel.INFO ,f'|- 标的{self.tradeTarget.targetName()}信息更新: END') + # PrintLog(LogLevel.INFO, f'|- 标的{self.tradeTarget.targetName()}信息更新: START') + # self.dataUpdateLock.acquire() + # PrintLog(LogLevel.INFO ,f'|- 标的{self.tradeTarget.targetName()}信息更新: LOCKED') + # try: + self.tradeTarget = inTradeTarget + self.refreshPlanPrice() + # finally: + # PrintLog(LogLevel.INFO ,f'|- 标的{self.tradeTarget.targetName()}信息更新: UNLOCKED') + # self.dataUpdateLock.release() + # self.refreshPlanPrice() + # PrintLog(LogLevel.INFO ,f'|- 标的{self.tradeTarget.targetName()}信息更新: END') def enabledTrading(self, enabled: bool) -> model.SFGridTradeTarget: self.tradeTarget.enabled = enabled # type: ignore @@ -77,7 +80,6 @@ class SFGridStrategy: PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - START') self.dataUpdateLock.acquire() - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - LOCKED') try: lastPrice = inTradeTarget.market_price @@ -85,11 +87,11 @@ class SFGridStrategy: orderType = -1 index: int = self.tradeTarget.grid_index # pyright: ignore[reportAssignmentType] orderRemark= "" - - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 策略运行状态{self.tradeTarget.enabled}, 初始化状态{self.tradeTarget.status}') - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 当前价{lastPrice}') + status = "新建" if self.tradeTarget.status == 0 else "已建初始仓" + PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 当前持仓: {self.tradeTarget.current_position} 当前价{lastPrice} 基准价格 {self.tradeTarget.getPriceGrid()[1]} 状态: {status} 启用交易线程: {'自动交易中' if self.tradeTarget.enabled else '交易已停止'}') + PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 计划卖出价{self.tradeTarget.plan_sell_price}') PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 网格索引{index}, 网格价格{self.tradeTarget.getPriceGrid()[index]}') - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 计划买入价{self.tradeTarget.plan_buy_price}, 计划卖出价{self.tradeTarget.plan_sell_price}') + PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 计划买入价{self.tradeTarget.plan_buy_price}') if self.tradeTarget.enabled and self.tradeTarget.status == 0 and lastPrice <= inTradeTarget.getPriceGrid()[1]: # 已启用,未建仓,准备建仓单信息 PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 准备建仓单信息') orderPrice = inTradeTarget.getPriceGrid()[1] @@ -108,7 +110,6 @@ class SFGridStrategy: orderType = xtconstant.STOCK_SELL orderRemark = OrderTypeSell - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 下单信息: {orderType}, {orderPrice}, {orderRemark}') if orderType != -1: orders = qmtv.queryPendingOrder(str(self.tradeTarget.stock_code), self.getName()) if len([order for order in orders if order.order_type == orderType and order.price == orderPrice]) > 0: @@ -135,10 +136,9 @@ class SFGridStrategy: gridBasePrice = -1 if index>=len(inTradeTarget.getPriceGrid()) or index < 0 else inTradeTarget.getPriceGrid()[int(index)] # pyright: ignore[reportArgumentType] PrintLog(LogLevel.INFO, f' |- {orderTypeName}委托, 单号 {self.tradeTarget.current_order_no}, 网格基准价 {gridBasePrice}, 下单价 {orderPrice}, 下单量 {self.tradeTarget.grid_volume}') finally: - print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - release lock') self.saveProxy() self.dataUpdateLock.release() - print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - END') + PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}]: END') def onOrderCreateAsync(self, response:XtOrderResponse): self.dataUpdateLock.acquire() diff --git a/core/sfgrid/sfgrid_ui.py b/core/sfgrid/sfgrid_ui.py index d279f6e..dc3f44b 100644 --- a/core/sfgrid/sfgrid_ui.py +++ b/core/sfgrid/sfgrid_ui.py @@ -22,8 +22,8 @@ class TradeTargetUI(ttk.Frame): self.stockCodeIdMap:dict[str, int] = {} self.strategy_ctrl:dict[int, SFGridStrategy] = {} # stock_code->trade_target self.listening_stock = [] - if qmtv.inited: - self.init_trade_target_pool() + + self.init_trade_target_pool() # 市场监控数据 self.marketData: dict[str, Any] = {} # 存储市场数据 {stock_code: {stock_name, last_price, time}} @@ -43,7 +43,7 @@ class TradeTargetUI(ttk.Frame): for temp in results: tradeTarget:SFGridTradeTarget = temp tradeTarget.current_position = qmtv.getStockPosition(tradeTarget.stock_code) # type: ignore - self.updateTradeTarget(tradeTarget, True) + self.updateTradeTarget(tradeTarget, True) # 初始化的时候 PrintLog(LogLevel.INFO, f'- [成功]交易标的信息初始化, 共 {len(self.tradeTargetData)} 个标的') @@ -53,11 +53,11 @@ class TradeTargetUI(ttk.Frame): for stock_code, tickData in data.items(): if stock_code in self.stockCodeIdMap: id:int = self.stockCodeIdMap[stock_code] - PrintLog(LogLevel.INFO, f' [序号-{id}] 股票代码: {stock_code} in trade pool, 市场数据更新 {tickData["lastPrice"]}') + PrintLog(LogLevel.INFO, f'======[序号-{id}-{stock_code}-{qmtv.getInstrumentName(stock_code)}] 市场数据更新====') tradeTarget = self.tradeTargetData[id] lastPrice = float("{:.3f}".format(tickData['lastPrice'])) tradeTarget.market_price = lastPrice # type: ignore - self.updateTradeTarget(tradeTarget, False, True) + self.updateTradeTarget(tradeTarget, False, True) # 市价更新 else: # 非目标交易,发布市场数据更新事件用于市场监控 lastPrice = tickData['lastPrice'] @@ -85,14 +85,13 @@ class TradeTargetUI(ttk.Frame): self.tradeTargetData[id] = target + # priceChange 用于控制是否对更新价格数据,进行交易判断 def updateTradeTarget(self, target: SFGridTradeTarget, save: bool = True, priceChange:bool = False): if save: target.save() id = target.get_id() - status = "新建" if target.status == 0 else "已建初始仓" - PrintLog(LogLevel.INFO, f' [序号-{id}] 股票代码: {target.stock_code}-{target.stock_name} 当前持仓: {target.current_position} 网格索引: {target.grid_index} 基准价格 {target.getPriceGrid()[1]} 状态: {status} 启用交易线程: {'自动交易中' if target.enabled else '交易已停止'}') - PrintLog(LogLevel.INFO, f' [序号-{id}] 股票代码: {target.stock_code}-{target.stock_name}: {target.plan_buy_price} {target.plan_sell_price}') # type: ignore + # PrintLog(LogLevel.INFO, f' [序号-{id}] 股票代码: {target.stock_code}-{target.stock_name}: {target.plan_buy_price} {target.plan_sell_price}') # type: ignore # 更新或添加数据到本地缓存 self.tradeTargetData[id] = target @@ -129,7 +128,7 @@ class TradeTargetUI(ttk.Frame): # ttk.Button(toolbar_frame, text="🛠 网格修正(停用)", # command=self.btnHandlerGridCorrect, # width=12).pack(side=tk.LEFT, padx=2) - ttk.Button(toolbar_frame, text="▣ 实时监控", + ttk.Button(toolbar_frame, text="▣ 边栏", command=self.btnHandlerToggleMarketMonitor, width=12).pack(side=tk.RIGHT, padx=2) # 表格区域 @@ -696,7 +695,7 @@ class TradeTargetUI(ttk.Frame): setattr(target, 'status', 0) # 更新策略控制器 - self.updateTradeTarget(target, True) + self.updateTradeTarget(target, True) # 网格配置变更 # 关闭窗口 config_window.destroy() @@ -937,7 +936,7 @@ class TradeTargetUI(ttk.Frame): status=-1 ) # 更新标的池 - self.updateTradeTarget(new_target, True) + self.updateTradeTarget(new_target, True) # 新增标的,相当于也是初始化 except Exception as e: PrintLog(LogLevel.ERROR, f'新增交易标的失败 {stock_code} {e}')