diff --git a/core/sfgrid/bus_events.py b/core/sfgrid/bus_events.py index 1b2bad9..b142206 100644 --- a/core/sfgrid/bus_events.py +++ b/core/sfgrid/bus_events.py @@ -1,12 +1,3 @@ # 删除交易标的事件 EventTradeTargetUpdate = "trade_target_update" -ActionEventAddTradeTarget = "add_trade_target" -ResultEventTradeTargetAdded = "trade_target_added" -ActionEventDeleteTradeTarget = "delete_trade_target" -ResultEventTradeTargetDeleted = "trade_target_deleted" - -# 定义事件处理函数 -ActionEventEnableTrade = "enable_trade" -ResultEventTradeEnabled = "trade_enabled" -ActionEventDisableTrade = "disable_trade" -ResultEventTradeDisabled = "trade_disabled" +EventTradeTargetDeleted = "trade_target_deleted" diff --git a/core/sfgrid/model.py b/core/sfgrid/model.py index ed883a7..d8ad7fc 100644 --- a/core/sfgrid/model.py +++ b/core/sfgrid/model.py @@ -26,7 +26,7 @@ class SFGridTradeTarget(BaseModel): grid_lower_count = IntegerField(default=10) # 基线价格下方网格数 def targetName(self): - return f'{self.stock_name}[{self.stock_code}]' + return f'{self.stock_code}-{self.stock_name}' def getPriceGrid(self) -> list: self.priceGrid: list = [] diff --git a/core/sfgrid/sfgrid_strategy.py b/core/sfgrid/sfgrid_strategy.py index 17299d9..a8efd7c 100644 --- a/core/sfgrid/sfgrid_strategy.py +++ b/core/sfgrid/sfgrid_strategy.py @@ -1,5 +1,6 @@ from core.logger import LogLevel, PrintLog from core.qmt import qmtv +from core.sfgrid import bus_events from core.sfgrid.bus_events import EventTradeTargetUpdate import core.sfgrid.model as model from core import constants @@ -37,6 +38,16 @@ class SFGridStrategy: # self.dataUpdateLock.release() # self.refreshPlanPrice() # PrintLog(LogLevel.INFO ,f'|- 标的{self.tradeTarget.targetName()}信息更新: END') + + def deleteTradeTarget(self, tradeTarget:model.SFGridTradeTarget): + PrintLog(LogLevel.INFO, f'|- 标的{tradeTarget.targetName()}信息删除: START') + self.dataUpdateLock.acquire() + try: + tradeTarget.delete_instance() + event_bus.publish(bus_events.EventTradeTargetDeleted, tradeTarget) + PrintLog(LogLevel.INFO, f'|- 标的{tradeTarget.targetName()}信息删除: END') + finally: + self.dataUpdateLock.release() def enabledTrading(self, enabled: bool) -> model.SFGridTradeTarget: self.tradeTarget.enabled = enabled # type: ignore @@ -78,21 +89,19 @@ class SFGridStrategy: if not self.tradeTarget.enabled: # 策略中止,自动交易暂停 return - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - START') self.dataUpdateLock.acquire() - try: lastPrice = inTradeTarget.market_price orderPrice:float = -1 orderType = -1 index: int = self.tradeTarget.grid_index # pyright: ignore[reportAssignmentType] orderRemark= "" - status = "新建" if self.tradeTarget.status == 0 else "已建初始仓" - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 当前持仓: {self.tradeTarget.current_position} 当前价{lastPrice} 状态: {status} 启用交易线程: {'自动交易中' if self.tradeTarget.enabled else '交易已停止'}') - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 当前价 : \t{lastPrice}') - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 计划卖出价: \t{self.tradeTarget.plan_sell_price:.3f}') - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 网格价格({index}): \t{self.tradeTarget.getPriceGrid()[index]}') - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 计划买入价: \t{self.tradeTarget.plan_buy_price:.3f}') + status = "未建初始仓" if self.tradeTarget.status == 0 else "已建初始仓" + PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 当前持仓 : \t{self.tradeTarget.current_position}') + PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 当前价格 : \t{lastPrice}') + PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 计划卖出价 : \t{self.tradeTarget.plan_sell_price:.3f}') + PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 网格价格({index}): \t{self.tradeTarget.getPriceGrid()[index]:.3f}') + PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 计划买入价 : \t{self.tradeTarget.plan_buy_price:.3f}') 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] @@ -115,9 +124,9 @@ class SFGridStrategy: 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: # 已存在未交易的多单 - print(f' |- [{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}]已存在未交易的{"多单" if orderType == xtconstant.STOCK_BUY else "空单"},不重复下单') + PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 已存在未交易的{"多单" if orderType == xtconstant.STOCK_BUY else "空单"},不重复下单') else: - print(f' |- 下网格{"多单" if orderType == xtconstant.STOCK_BUY else "空单"}') + PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 下网格{"多单" if orderType == xtconstant.STOCK_BUY else "空单"}') self.tradeTarget.current_order_no = qmtv.orderAsync( str(self.tradeTarget.stock_code), self.tradeTarget.grid_volume, @@ -135,11 +144,10 @@ class SFGridStrategy: elif orderRemark == OrderTypeInit: orderTypeName = "建仓单" 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}') + PrintLog(LogLevel.INFO, f'|- {orderTypeName}委托[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 单号 {self.tradeTarget.current_order_no}, 网格基准价 {gridBasePrice:.3f}, 下单价 {orderPrice:.3f}, 下单量 {self.tradeTarget.grid_volume}') finally: self.saveProxy() self.dataUpdateLock.release() - PrintLog(LogLevel.INFO, f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}]: END') def onOrderCreateAsync(self, response:XtOrderResponse): self.dataUpdateLock.acquire() @@ -153,12 +161,11 @@ class SFGridStrategy: def onOrderTrade(self, trade:XtTrade): if trade.strategy_name != self.getName(): - print(f"委托回调 投资备注 {trade.stock_code}-{trade.instrument_name} {trade.strategy_name} 不匹配 {trade.order_remark}") + PrintLog(LogLevel.WARNING, f"|- 委托回调 投资备注 {trade.stock_code}-{trade.instrument_name} {trade.strategy_name} 不匹配 {trade.order_remark}") return - print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:START, {trade.order_id}') + PrintLog(LogLevel.INFO, f'|- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:START, {trade.order_id}') self.dataUpdateLock.acquire() - print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:LOCKED') try: type:str = "" if self.tradeTarget.status == 0 and trade.order_id == self.tradeTarget.current_order_no and trade.order_remark == constants.OrderTypeInit: @@ -186,16 +193,13 @@ class SFGridStrategy: self.refreshPlanPrice() self.printTradeReport(trade, type) finally: - print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:release lock') self.dataUpdateLock.release() - print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:END') def printTradeReport(self, trade:XtTrade, type:str): - PrintLog(LogLevel.INFO, f"打印交易报告[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}]:START") - PrintLog(LogLevel.INFO, f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} {type}: {self.tradeTarget.current_order_no}已成交 ") + 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' 当前持仓: {self.tradeTarget.current_position}') - PrintLog(LogLevel.INFO, f' 网格坐标: {self.tradeTarget.grid_index}') + PrintLog(LogLevel.INFO, f' 手续费 : {trade.commission:.3f}') def refreshPlanPrice(self): diff --git a/core/sfgrid/sfgrid_ui.py b/core/sfgrid/sfgrid_ui.py index 5e61ec1..b0e6bfe 100644 --- a/core/sfgrid/sfgrid_ui.py +++ b/core/sfgrid/sfgrid_ui.py @@ -38,6 +38,7 @@ class TradeTargetUI(ttk.Frame): eBus.event_bus.subscribe(eBus.MarketDataUpdate, self.onMarketDataUpdated) eBus.event_bus.subscribe(bus_events.EventTradeTargetUpdate, self.onStrategyUpdate) + eBus.event_bus.subscribe(bus_events.EventTradeTargetDeleted, self.onTradeTargetDeleted) def init_trade_target_pool(self): @@ -55,8 +56,8 @@ 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}-{qmtv.getInstrumentName(stock_code)}] 市场数据更新====') tradeTarget = self.tradeTargetData[id] + PrintLog(LogLevel.INFO, f'|- 市价更新[{tradeTarget.targetName()}] - {id}市场数据更新=======================') lastPrice = float("{:.3f}".format(tickData['lastPrice'])) tradeTarget.market_price = lastPrice # type: ignore self.updateTradeTarget(tradeTarget, False, True) # 市价更新 @@ -1055,20 +1056,17 @@ class TradeTargetUI(ttk.Frame): if result: id = target.get_id() - try: - - del self.tradeTargetData[id] - del self.strategy_ctrl[id] - del self.stockCodeIdMap[target.stock_code] # type: ignore - - # 从数据库中删除 - target.delete_instance() - # 添加日志 - PrintLog(LogLevel.INFO, f"交易标的已删除,ID: {id} {target.targetName()}") - except Exception as e: - PrintLog(LogLevel.ERROR, f"删除交易标的失败 ID {id}: {str(e)}") + # try: + ctrl = self.strategy_ctrl[id] + ctrl.deleteTradeTarget(target) PrintLog(LogLevel.INFO, f"已发送删除请求: {target.stock_code} - {target.stock_name}") + def onTradeTargetDeleted(self, target: SFGridTradeTarget): + id = target.get_id() + del self.tradeTargetData[id] + del self.strategy_ctrl[id] + del self.stockCodeIdMap[target.stock_code] # type: ignore + def btnHandlerAddTradeTarget(self): """添加新的交易标的""" # 获取顶层窗口