市场数据跟踪

This commit is contained in:
2025-11-10 14:43:14 +08:00
parent 7733d6df32
commit 3a137b6aee
4 changed files with 192 additions and 41 deletions
+133 -21
View File
@@ -1,3 +1,6 @@
from typing import Any
import tkinter as tk
from tkinter import ttk, messagebox, filedialog
from datetime import datetime
@@ -8,11 +11,13 @@ from core.logger import LogData, LogLevel
from core.strategy_db import TradeTarget
import configparser
import sfgrid_constants
from core.objects import GridFixData
from core.util import getInstrumentName
class TradeTargetUI:
def __init__(self):
self.data:dict[int, TradeTarget] = {}
self.tradeTargetData:dict[int, TradeTarget] = {}
self.market_data_enabled = False # 添加市场数据监听状态变量
self.ui_refresh_enabled = False # 添加UI刷新线程状态变量
self.registerEventHandler()
@@ -20,16 +25,20 @@ class TradeTargetUI:
# 创建刷新线程标志
self.refresh_thread_running = False # 默认不启动刷新线程
# 市场监控数据
self.marketData: dict[str, Any] = {} # 存储市场数据 {stock_code: {stock_name, last_price, time}}
self.root = tk.Tk()
self.root.title("三疯交易系统")
self.root.geometry("1200x700")
self.root.geometry("1400x700")
# 创建界面
self.create_ui()
# 不再自动启动刷新线程,由市场数据开关控制
def registerEventHandler(self):
eBus.event_bus.subscribe(eBus.MarketDataUpdate, self.onTradeTargetUpdated)
eBus.event_bus.subscribe(eBus.EventTradeTargetUpdate, self.onTradeTargetUpdated)
eBus.event_bus.subscribe(eBus.MarketDataUpdate, self.onMarketDataUpdated)
eBus.event_bus.subscribe(eBus.ResultEventTradeEnabled, self.onTradeEnabled)
eBus.event_bus.subscribe(eBus.ResultEventTradeDisabled, self.onTradeDisabled)
eBus.event_bus.subscribe(eBus.MarketDataEnabled, self.onMarketDataToggled)
@@ -58,8 +67,8 @@ class TradeTargetUI:
def onTradeTargetDeleted(self, id: int):
"""处理交易标的删除完成事件"""
# 从本地数据中删除
if id in self.data:
del self.data[id]
if id in self.tradeTargetData:
del self.tradeTargetData[id]
# 添加日志
self.add_log(LogLevel.INFO, f"交易标的已删除,ID: {id}")
@@ -81,8 +90,17 @@ class TradeTargetUI:
def onTradeTargetUpdated(self, target: TradeTarget):
# 更新或添加数据到本地缓存
self.data[target.get_id()] = target
# 不再直接刷新表格,由刷新线程统一处理
self.tradeTargetData[target.get_id()] = target
def onMarketDataUpdated(self, target: TradeTarget):
# 更新市场监控数据
current_time = datetime.now().strftime("%H:%M:%S")
self.marketData[str(target.stock_code)] = {
'stock_name': target.stock_name,
'last_price': target.market_price if target.market_price is not None else 0.0,
'time': current_time
}
def create_ui(self):
"""创建UI界面"""
@@ -183,13 +201,24 @@ class TradeTargetUI:
def create_tables_area(self, parent):
"""创建表格区域"""
# 上方交易标的区域
trade_frame = ttk.LabelFrame(parent, text="交易标的详情", padding=10)
trade_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 5))
# 创建主表格框架(水平排列)
tables_frame = ttk.Frame(parent)
tables_frame.pack(fill=tk.BOTH, expand=True, pady=(0, 5))
# 左侧交易标的区域
trade_frame = ttk.LabelFrame(tables_frame, text="交易标的详情", padding=10)
trade_frame.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 5))
# 创建交易标的表格
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.create_market_monitor_table(market_frame)
# 下方操作日志区域(默认隐藏)
self.log_frame = ttk.LabelFrame(parent, text="操作日志", padding=10)
# 默认不显示,通过工具栏按钮控制
@@ -246,6 +275,85 @@ class TradeTargetUI:
# 绑定双击事件
self.trade_table.bind("<Double-1>", self.on_table_double_click)
def create_market_monitor_table(self, parent):
"""创建市场监控表格"""
columns = ("时间", "股票代码", "股票名称", "最新价格")
self.market_table = ttk.Treeview(parent, columns=columns, show='headings', height=15)
# 列配置
column_configs = {
"时间": (120, "center"),
"股票代码": (90, "center"),
"股票名称": (80, "center"),
"最新价格": (80, "center")
}
for col in columns:
width, anchor = column_configs[col]
self.market_table.heading(col, text=col)
self.market_table.column(col, width=width, anchor=anchor) # type: ignore
# 滚动条
scrollbar = ttk.Scrollbar(parent, orient=tk.VERTICAL, command=self.market_table.yview)
self.market_table.configure(yscrollcommand=scrollbar.set)
self.market_table.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
# 绑定双击事件
self.market_table.bind("<Double-1>", self.on_market_table_double_click)
# 填充初始数据
self.populate_market_table()
def populate_market_table(self):
"""填充市场监控表格数据"""
pass
# 清空现有数据
for item in self.market_table.get_children():
self.market_table.delete(item)
# 填充市场数据
tmp = self.marketData.copy()
for stock_code, data in tmp.items():
values = [
data['time'],
stock_code,
data['stock_name'],
f"{data['last_price']:.3f}"
]
self.market_table.insert('', tk.END, values=values)
def on_market_table_double_click(self, event):
"""市场监控表格双击事件"""
selected = self.market_table.selection()
if selected:
item = selected[0]
values = self.market_table.item(item)['values']
stock_code = values[1]
stock_name = values[2]
last_price = values[3]
# 检查是否已在交易池中
is_in_trade_pool = any(target.stock_code == stock_code for target in self.tradeTargetData.values())
if is_in_trade_pool:
messagebox.showinfo("提示", f"{stock_code} ({stock_name}) 已在交易池中")
else:
result = messagebox.askyesno(
"添加交易标的",
f"确定要将以下股票添加到交易池吗?\n\n"
f"股票代码: {stock_code}\n"
f"股票名称: {stock_name}\n"
f"最新价格: {last_price}"
)
if result:
# 发布事件通知主控制器添加标的
eBus.event_bus.publish(eBus.ActionEventAddTradeTarget, stock_code)
self.add_log(LogLevel.INFO, f"已发送添加请求: {stock_code} - {stock_name}")
def get_status_indicator(self, target: TradeTarget) -> str:
"""获取状态指示器(带颜色色块的文本)"""
if target.status == 1:
@@ -266,8 +374,8 @@ class TradeTargetUI:
def populate_trade_table(self):
"""填充交易标的表格数据"""
for temp in self.data:
target: TradeTarget = self.data[temp]
for temp in self.tradeTargetData:
target: TradeTarget = self.tradeTargetData[temp]
values = [
target.id, # type: ignore
target.stock_code,
@@ -275,10 +383,10 @@ class TradeTargetUI:
"-" if target.market_price is None else f"{target.market_price:.3f}",
target.current_position,
target.grid_index,
f"{target.last_trade_price:.3f}",
f"{target.plan_buy_price:.3f}",
f"{target.plan_sell_price:.3f}",
f"{target.current_order_price:.3f}",
'-' 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}",
'-' if target.current_order_price is None else f"{target.current_order_price:.3f}",
target.current_order_no,
target.current_order_type,
self.get_status_indicator(target),
@@ -348,9 +456,9 @@ class TradeTargetUI:
target_id = values[0]
# 从列表中找到对应的target对象
for id in self.data:
for id in self.tradeTargetData:
if int(target_id) == id: # type: ignore
return self.data[id]
return self.tradeTargetData[id]
return None
@@ -513,6 +621,9 @@ class TradeTargetUI:
values = self.trade_table.item(item)['values']
if values and values[0] in selected_values:
self.trade_table.selection_add(item)
# 刷新市场监控表格
self.populate_market_table()
def onLog(self, data:LogData):
self.add_log(data.level, data.message)
@@ -990,8 +1101,9 @@ class TradeTargetUI:
if not result:
return
# 保存到数据库(这里需要发布事件让控制器处理)
# TODO: 发布保存事件到控制器
# 发布网格修正事件,传递GridFixData对象
grid_fix_data = GridFixData(new_grid_index, target)
eBus.event_bus.publish(eBus.ActionEventGridFix, grid_fix_data)
# 关闭窗口
window.destroy()
@@ -1027,4 +1139,4 @@ class TradeTargetUI:
# 更新持仓量状态
current_position = getattr(target, 'current_position')
self.update_position_status(current_position, required_position, position_status_label)
self.update_position_status(current_position, required_position, position_status_label)