初步测试通过

This commit is contained in:
2025-11-06 14:39:09 +08:00
parent 88bd0b17c9
commit 1ee8f0426e
5 changed files with 274 additions and 174 deletions
+110 -36
View File
@@ -1,7 +1,9 @@
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from datetime import datetime
from core.eventbus import ActionDisableMarketData, ActionEnableMarketData, ActionEventDisableTrade, ActionEventEnableTrade, MarketDataUpdate, MarketDataEnabled, MarketDataDisabled, ResultEventTradeDisabled, ResultEventTradeEnabled, event_bus
import threading
import time
from core.eventbus import ActionDisableMarketData, ActionEnableMarketData, ActionEventDeleteTradeTarget, ActionEventDisableTrade, ActionEventEnableTrade, MarketDataUpdate, MarketDataEnabled, MarketDataDisabled, ResultEventTradeDisabled, ResultEventTradeEnabled, ResultEventTradeTargetDeleted, event_bus
from core.strategy_db import TradeTarget
import configparser
import sfgrid_constants
@@ -10,14 +12,20 @@ import sfgrid_constants
class TradeTargetUI:
def __init__(self):
self.data:dict[int, TradeTarget] = {}
self.market_data_enabled = True # 添加市场数据监听状态变量
self.market_data_enabled = False # 添加市场数据监听状态变量
self.ui_refresh_enabled = False # 添加UI刷新线程状态变量
self.registerEventHandler()
# 创建刷新线程标志
self.refresh_thread_running = False # 默认不启动刷新线程
self.root = tk.Tk()
self.root.title("三疯交易系统")
self.root.geometry("1200x700")
# 创建界面
self.create_ui()
# 不再自动启动刷新线程,由市场数据开关控制
def registerEventHandler(self):
event_bus.subscribe(MarketDataUpdate, self.onTradeTargetUpdated)
@@ -25,10 +33,42 @@ class TradeTargetUI:
event_bus.subscribe(ResultEventTradeDisabled, self.onTradeDisabled)
event_bus.subscribe(MarketDataEnabled, self.onMarketDataToggled)
event_bus.subscribe(MarketDataDisabled, self.onMarketDataToggled)
event_bus.subscribe(ResultEventTradeTargetDeleted, self.onTradeTargetDeleted)
def start_refresh_thread(self):
"""启动刷新线程"""
if not hasattr(self, 'refresh_thread') or not self.refresh_thread.is_alive():
self.refresh_thread = threading.Thread(target=self.refresh_loop, daemon=True)
self.refresh_thread.start()
def refresh_loop(self):
"""刷新循环"""
while self.refresh_thread_running:
# 在主线程中更新UI
if hasattr(self, 'root') and self.root:
self.root.after(0, self.refresh_table)
time.sleep(0.5) # 每0.5秒刷新一次
def stop_refresh_thread(self):
"""停止刷新线程"""
self.refresh_thread_running = False
def onTradeTargetDeleted(self, id: int):
"""处理交易标的删除完成事件"""
# 从本地数据中删除
if id in self.data:
del self.data[id]
# 添加日志
self.add_log("INFO", f"交易标的已删除,ID: {id}")
def onMarketDataToggled(self, data:bool):
self.market_data_enabled = self.market_data_switch_var.get()
self.add_log("INFO", "市场数据监听已" + ("启用" if data else "禁用"))
# 同步UI刷新线程状态
if data:
self.start_ui_refresh()
else:
self.stop_ui_refresh()
def onTradeEnabled(self, target:TradeTarget):
self.add_log("INFO", f"交易启用: {target.stock_code} - {target.stock_name}")
@@ -37,11 +77,10 @@ class TradeTargetUI:
self.add_log("INFO", f"交易禁用: {target.stock_code} - {target.stock_name}")
def onTradeTargetUpdated(self, target:TradeTarget):
def onTradeTargetUpdated(self, target: TradeTarget):
# 更新或添加数据到本地缓存
self.data[target.get_id()] = target
# 刷新表格显示
self.refresh_table()
# 不再直接刷新表格,由刷新线程统一处理
def create_ui(self):
"""创建UI界面"""
@@ -71,7 +110,7 @@ class TradeTargetUI:
ttk.Separator(toolbar_frame, orient='vertical').pack(side=tk.LEFT, fill=tk.Y, padx=10)
# 市场数据监听开关
self.market_data_switch_var = tk.BooleanVar(value=True)
self.market_data_switch_var = tk.BooleanVar(value=False)
self.market_data_switch = ttk.Checkbutton(
toolbar_frame,
text="📊 市场数据",
@@ -99,8 +138,26 @@ class TradeTargetUI:
self.market_data_enabled = self.market_data_switch_var.get()
if self.market_data_enabled:
event_bus.publish(ActionEnableMarketData, True)
# 同步开启UI刷新线程
self.start_ui_refresh()
else:
event_bus.publish(ActionDisableMarketData, True)
# 同步关闭UI刷新线程
self.stop_ui_refresh()
def start_ui_refresh(self):
"""启动UI刷新线程"""
if not self.refresh_thread_running:
self.refresh_thread_running = True
self.start_refresh_thread()
self.add_log("INFO", "UI刷新线程已启动")
def stop_ui_refresh(self):
"""停止UI刷新线程"""
if self.refresh_thread_running:
self.stop_refresh_thread()
self.refresh_thread_running = False
self.add_log("INFO", "UI刷新线程已停止")
def create_menu_bar(self):
"""创建菜单栏"""
@@ -112,7 +169,14 @@ class TradeTargetUI:
menubar.add_cascade(label="系统", menu=system_menu)
system_menu.add_command(label="系统设置", command=self.system_settings)
system_menu.add_separator()
system_menu.add_command(label="退出", command=self.root.destroy)
system_menu.add_command(label="退出", command=self.on_exit)
def on_exit(self):
"""退出程序"""
# 停止刷新线程
self.stop_refresh_thread()
# 关闭窗口
self.root.destroy()
def create_tables_area(self, parent):
"""创建表格区域"""
@@ -137,7 +201,7 @@ class TradeTargetUI:
columns = ("ID",
"股票代码", "股票名称", "市场价", "持仓数量", "网格索引",
"最新成交价", "计划买入价", "买入订单", "计划卖出价", "卖出订单号",
"最新成交价", "计划买入价", "计划卖出价", "当前订单", "当前订单号", "当前订单类型",
"启用状态", "交易状态"
)
@@ -147,17 +211,18 @@ class TradeTargetUI:
column_configs = {
"ID": (50, tk.CENTER),
"股票代码": (90, tk.CENTER),
"股票名称": (100, tk.CENTER),
"市场价": (60, tk.CENTER),
"持仓数量": (90, tk.CENTER),
"网格索引": (50, tk.CENTER),
"最新成交价": (60, tk.CENTER),
"计划买入价": (60, tk.CENTER),
"买入订单号": (100, tk.CENTER),
"计划卖出": (60, tk.CENTER),
"卖出订单号": (100, tk.CENTER),
"启用状态": (100, tk.CENTER),
"交易状态": (100, 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.CENTER)
}
for col in columns:
@@ -201,17 +266,18 @@ class TradeTargetUI:
for temp in self.data:
target: TradeTarget = self.data[temp]
values = [
target.id, # type: ignore
target.id, # type: ignore
target.stock_code,
target.stock_name,
f"{target.market_price:.3f}",
"-" if target.market_price is None else f"{target.market_price:.3f}",
target.current_position,
target.grid_index,
f"{target.last_trade_price:.2f}",
f"{target.plan_buy_price:.2f}",
target.current_buy_order_no,
f"{target.plan_sell_price:.2f}",
target.current_sell_order_no,
f"{target.last_trade_price:.3f}",
f"{target.plan_buy_price:.3f}",
f"{target.plan_sell_price:.3f}",
f"{target.current_order_price:.3f}",
target.current_order_no,
target.current_order_type,
self.get_status_indicator(target),
self.get_trade_enabled_indicator(target.enabled) # type: ignore
]
@@ -310,7 +376,6 @@ class TradeTargetUI:
target.enabled = True # type: ignore
event_bus.publish(ActionEventEnableTrade, target.get_id())
# self.add_log("INFO", f"已启动交易: {target.stock_code} - {target.stock_name}")
# self.refresh_table()
# messagebox.showinfo("启动成功", f"已启动 {target.stock_code} ({target.stock_name}) 的交易")
def on_trade_enabled(self, target: TradeTarget):
@@ -337,7 +402,6 @@ class TradeTargetUI:
target.enabled = False # type: ignore
event_bus.publish(ActionEventDisableTrade, target.get_id())
# self.add_log("INFO", f"已暂停交易: {target.stock_code} - {target.stock_name}")
# self.refresh_table()
# messagebox.showinfo("暂停成功", f"已暂停 {target.stock_code} ({target.stock_name}) 的交易")
def delete_selected_trade(self):
@@ -356,14 +420,9 @@ class TradeTargetUI:
)
if result:
try:
del self.data[target.get_id()]
self.add_log("WARNING", f"删除交易标的: {target.stock_code} - {target.stock_name}")
self.refresh_table()
messagebox.showinfo("删除成功", f"已删除 {target.stock_code} ({target.stock_name})")
except Exception as e:
self.add_log("ERROR", f"删除失败: {str(e)}")
messagebox.showerror("删除失败", f"删除交易标的时出错:{str(e)}")
# 通过事件总线发出删除动作
event_bus.publish(ActionEventDeleteTradeTarget, target.get_id())
self.add_log("INFO", f"发送删除请求: {target.stock_code} - {target.stock_name}")
def add_trade_target(self):
"""添加新的交易标的"""
@@ -434,12 +493,27 @@ class TradeTargetUI:
def refresh_table(self):
"""刷新表格数据"""
# 保存当前选中的项
selected_items = self.trade_table.selection()
selected_values = []
for item in selected_items:
values = self.trade_table.item(item)['values']
if values:
selected_values.append(values[0]) # 保存ID
# 清空表格
for item in self.trade_table.get_children():
self.trade_table.delete(item)
# 重新填充
self.populate_trade_table()
# 恢复之前选中的项
if selected_values:
for item in self.trade_table.get_children():
values = self.trade_table.item(item)['values']
if values and values[0] in selected_values:
self.trade_table.selection_add(item)
def add_log(self, level, message):
"""添加日志记录"""