diff --git a/core/main_ui.py b/core/main_ui.py index 7a9a828..2df1df6 100644 --- a/core/main_ui.py +++ b/core/main_ui.py @@ -36,7 +36,7 @@ class MainWindow: # 创建Tab按钮(垂直排列,文字垂直显示) self.tab_buttons = [] - strategy_names = ["三疯\n网格", "通用\n网格", "涨停\n分析"] + strategy_names = ["蒙派\n策略", "涨停\n分析"] for idx, name in enumerate(strategy_names): btn = ttk.Button( diff --git a/core/sfgrid/sfgrid_strategy.py b/core/sfgrid/sfgrid_strategy.py index 9ff22d1..8cc8065 100644 --- a/core/sfgrid/sfgrid_strategy.py +++ b/core/sfgrid/sfgrid_strategy.py @@ -56,16 +56,14 @@ class SFGridStrategy: return bool(self.tradeTarget.enabled) # 修复返回类型问题 def onDataUpdate(self, inTradeTarget:model.SFGridTradeTarget): - print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - START') if not is_trading_time(): - print(f"|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 非交易时间,不进行自动交易") return if not self.tradeTarget.enabled: # 未建仓,自动交易暂停 - print(f"|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 未建仓或交易监控暂停,不进行自动交易") return + print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - START') self.dataUpdateLock.acquire() print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - LOCKED') diff --git a/core/sfgrid/sfgrid_ui.py b/core/sfgrid/sfgrid_ui.py index f3463cd..2cc9a62 100644 --- a/core/sfgrid/sfgrid_ui.py +++ b/core/sfgrid/sfgrid_ui.py @@ -32,6 +32,9 @@ class TradeTargetUI(ttk.Frame): # 市场监控数据 self.marketData: dict[str, Any] = {} # 存储市场数据 {stock_code: {stock_name, last_price, time}} + # 市场监控窗口显示状态 + self.market_monitor_visible = True + # 创建界面 self.create_ui() @@ -40,20 +43,18 @@ class TradeTargetUI(ttk.Frame): def onMarketDataUpdated(self, data): # 收集所有市场数据用于市场监控 for stock_code, tickData in data.items(): - id = self.stockCodeIdMap.get(stock_code) - if id is not None and stock_code in self.tradeTargetData: + if stock_code in self.stockCodeIdMap: + id:int = self.stockCodeIdMap[stock_code] tradeTarget = self.tradeTargetData[id] - PrintLog(LogLevel.INFO, f' [市价更新 序号-{id}] {stock_code} - {tickData}') - lastPrice = float("{:.3f}".format(tickData['lastPrice'])) tradeTarget.market_price = lastPrice # type: ignore + self.updateTradeTarget(tradeTarget) stock_controller: SFGridStrategy = self.strategy_ctrl[id] stock_controller.onDataUpdate(tradeTarget) else: # 非目标交易,发布市场数据更新事件用于市场监控 lastPrice = tickData['lastPrice'] if lastPrice == 10 or stock_code in self.listening_stock: - PrintLog(LogLevel.INFO, f' [市价更新 序号-X] {stock_code} - {lastPrice}') # 发布市场数据更新事件用于市场监控 market_target = SFGridTradeTarget() market_target.stock_code = stock_code @@ -61,7 +62,13 @@ class TradeTargetUI(ttk.Frame): market_target.market_price = lastPrice # type: ignore if stock_code not in self.listening_stock: self.listening_stock.append(stock_code) - + # 更新市场监控数据用于UI显示 + current_time = datetime.now().strftime("%H:%M:%S") + self.marketData[str(stock_code)] = { + 'stock_name': qmtv.getInstrumentName(stock_code), + 'last_price': tickData['lastPrice'], + 'time': current_time + } def refresh_targets(self): # 更新标的池 @@ -84,7 +91,6 @@ class TradeTargetUI(ttk.Frame): PrintLog(LogLevel.INFO, f' |- 同步[{tradeTarget.stock_code}-{tradeTarget.stock_name}]持仓信息[{'成功' if result == 1 else '失败'}]') stockTradeController = SFGridStrategy(tradeTarget) # type: ignore self.strategy_ctrl[id] = stockTradeController # pyright: ignore[reportArgumentType] - # eBus.event_bus.publish(eBus.EventTradeTargetUpdate, tradeTarget) self.updateTradeTarget(tradeTarget) PrintLog(LogLevel.INFO, f'- [成功]交易标的信息初始化, 共 {len(self.tradeTargetData)} 个标的') @@ -99,9 +105,9 @@ class TradeTargetUI(ttk.Frame): """刷新循环""" while self.refresh_thread_running: # 在主线程中更新UI - PrintLog(LogLevel.INFO, "刷新UI") self.after(0, self.refresh_table) - time.sleep(0.5) # 每0.5秒刷新一次 + self.after(0, self.populate_market_table) + time.sleep(0.2) # 每0.5秒刷新一次 def stop_refresh_thread(self): """停止刷新线程""" @@ -113,7 +119,6 @@ class TradeTargetUI(ttk.Frame): def onTradeDisabled(self, target:SFGridTradeTarget): PrintLog(LogLevel.INFO, f"交易禁用: {target.stock_code} - {target.stock_name}") - def updateTradeTarget(self, target: SFGridTradeTarget): # 更新或添加数据到本地缓存 @@ -142,8 +147,10 @@ class TradeTargetUI(ttk.Frame): ttk.Button(toolbar_frame, text="🛠 网格修正", command=self.grid_correction, width=12).pack(side=tk.LEFT, padx=2) - # 添加分隔符 - ttk.Separator(toolbar_frame, orient='vertical').pack(side=tk.LEFT, fill=tk.Y, padx=10) + # 添加抽屉按钮到工具栏最右侧 + self.toggle_market_monitor_btn = ttk.Button(toolbar_frame, text="◀▶", + command=self.toggle_market_monitor, width=3) + self.toggle_market_monitor_btn.pack(side=tk.RIGHT, padx=2) # 表格区域 self.create_tables_area(main_frame) @@ -163,7 +170,6 @@ class TradeTargetUI(ttk.Frame): PrintLog(LogLevel.INFO, "UI刷新线程已停止") - def create_tables_area(self, parent): """创建表格区域""" # 创建主表格框架(水平排列) @@ -178,17 +184,17 @@ class TradeTargetUI(ttk.Frame): self.create_trade_target_table(trade_frame) # 右侧市场监控区域 - market_frame = ttk.LabelFrame(tables_frame, text="市场监控", padding=10) - market_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(5, 0)) + self.market_frame = ttk.LabelFrame(tables_frame, text="市场监控", padding=10) + self.market_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(5, 0)) # 创建市场监控表格 - self.create_market_monitor_table(market_frame) + self.create_market_monitor_table(self.market_frame) def create_trade_target_table(self, parent): """创建交易标的表格""" columns = ("ID", - "股票代码", "股票名称", "市场价", "持仓数量", "网格索引", + "股票代码", "股票名称", "市场价", "持仓数量", "最新成交价", "计划买入价", "计划卖出价", "当前订单价", "当前订单号", "当前订单类型", "交易状态" ) @@ -199,17 +205,16 @@ class TradeTargetUI(ttk.Frame): column_configs = { "ID": (50, tk.CENTER), "股票代码": (90, tk.CENTER), - "股票名称": (80, tk.CENTER), - "市场价": (70, tk.CENTER), - "持仓数量": (80, tk.CENTER), - "网格索引": (80, tk.CENTER), - "最新成交价": (90, tk.CENTER), - "计划买入价": (90, tk.CENTER), - "计划卖出价": (90, tk.CENTER), - "当前订单价": (90, tk.CENTER), - "当前订单号": (90, tk.CENTER), - "当前订单类型": (90, tk.CENTER), - "交易状态": (80, tk.CENTER) + "股票名称": (80, tk.E), + "市场价": (70, tk.E), + "持仓数量": (80, tk.E), + "最新成交价": (90, tk.E), + "计划买入价": (90, tk.E), + "计划卖出价": (90, tk.E), + "当前订单价": (90, tk.E), + "当前订单号": (90, tk.E), + "当前订单类型": (90, tk.E), + "交易状态": (80, tk.E) } for col in columns: @@ -232,16 +237,15 @@ class TradeTargetUI(ttk.Frame): def create_market_monitor_table(self, parent): """创建市场监控表格""" - columns = ("时间", "股票代码", "股票名称", "最新价格") + columns = ("时间", "股票名称", "最新价格") self.market_table = ttk.Treeview(parent, columns=columns, show='headings', height=15) # 列配置 column_configs = { - "时间": (120, "center"), - "股票代码": (90, "center"), - "股票名称": (80, "center"), - "最新价格": (80, "center") + "时间": (50, tk.CENTER), + "股票名称": (80, tk.CENTER), + "最新价格": (80, tk.CENTER) } for col in columns: @@ -264,7 +268,14 @@ class TradeTargetUI(ttk.Frame): def populate_market_table(self): """填充市场监控表格数据""" - pass + # 保存当前选中的项 + selected_items = self.market_table.selection() + selected_values = [] + for item in selected_items: + values = self.market_table.item(item)['values'] + if values: + selected_values.append(values[1]) # 保存股票代码 + # 清空现有数据 for item in self.market_table.get_children(): self.market_table.delete(item) @@ -272,13 +283,35 @@ class TradeTargetUI(ttk.Frame): # 填充市场数据 tmp = self.marketData.copy() for stock_code, data in tmp.items(): + # 处理时间格式,仅显示 hh:mm:ss + time_str = data['time'] + # 如果时间字符串包含空格,说明包含日期和时间,只取时间部分 + if ' ' in time_str: + time_str = time_str.split(' ')[1] + + # 确保时间格式为 hh:mm:ss,如果只有 hh:mm 则补充 :00 + if ':' in time_str: + time_components = time_str.split(':') + if len(time_components) == 2: + # 只有小时和分钟,补充秒 + time_str = f"{time_components[0]}:{time_components[1]}:00" + elif len(time_components) >= 3: + # 有小时、分钟和秒,只取前三个部分 + time_str = f"{time_components[0]}:{time_components[1]}:{time_components[2]}" + values = [ - data['time'], - stock_code, - data['stock_name'], + time_str, + data['stock_name']+f"{stock_code}", f"{data['last_price']:.3f}" ] self.market_table.insert('', tk.END, values=values) + + # 恢复之前选中的项 + if selected_values: + for item in self.market_table.get_children(): + values = self.market_table.item(item)['values'] + if values and values[1] in selected_values: # 比较股票代码 + self.market_table.selection_add(item) def on_market_table_double_click(self, event): """市场监控表格双击事件""" @@ -324,7 +357,6 @@ class TradeTargetUI(ttk.Frame): target.stock_name, "-" if target.market_price is None else f"{target.market_price:.3f}", target.current_position, - target.grid_index, '-' if target.last_trade_price is None else f"{target.last_trade_price:.3f}", '-' if target.plan_buy_price is None else f"{target.plan_buy_price:.3f}", '-' if target.plan_sell_price is None else f"{target.plan_sell_price:.3f}", @@ -1105,4 +1137,17 @@ class TradeTargetUI(ttk.Frame): PrintLog(LogLevel.INFO, f"网格修正已应用: {target.stock_code} - {target.stock_name}, 网格索引: {grid_index}") except Exception as e: - PrintLog(LogLevel.ERROR, f"网格修正更新失败: {str(e)}") \ No newline at end of file + PrintLog(LogLevel.ERROR, f"网格修正更新失败: {str(e)}") + + def toggle_market_monitor(self): + """切换市场监控窗口显示/隐藏""" + if self.market_monitor_visible: + # 隐藏市场监控窗口 + self.market_frame.pack_forget() + self.toggle_market_monitor_btn.config(text="▶") + self.market_monitor_visible = False + else: + # 显示市场监控窗口 + self.market_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(5, 0)) + self.toggle_market_monitor_btn.config(text="◀▶") + self.market_monitor_visible = True