市场数据跟踪
This commit is contained in:
+133
-21
@@ -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)
|
||||
Reference in New Issue
Block a user