网格修正

This commit is contained in:
2025-11-10 10:57:21 +08:00
parent b7f9d29c54
commit 7733d6df32
2 changed files with 205 additions and 2 deletions
+7
View File
@@ -0,0 +1,7 @@
from core.strategy_db import TradeTarget
class GridFixData:
def __init__(self, grid_index, tradeTarget:TradeTarget):
self.grid_index = grid_index
self.tradeTarget = tradeTarget
+198 -2
View File
@@ -106,7 +106,8 @@ class TradeTargetUI:
command=self.add_trade_target, width=12).pack(side=tk.LEFT, padx=2)
ttk.Button(toolbar_frame, text="🗑 删除标的",
command=self.delete_selected_trade, width=12).pack(side=tk.LEFT, padx=2)
ttk.Button(toolbar_frame, text="🛠 网格修正", width=12).pack(side=tk.LEFT, padx=2)
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)
@@ -829,6 +830,201 @@ class TradeTargetUI:
ttk.Button(button_frame, text="💾 保存配置", command=save_settings, width=15).pack(side=tk.LEFT, padx=5)
ttk.Button(button_frame, text="❌ 取消", command=cancel_settings, width=15).pack(side=tk.LEFT, padx=5)
def grid_correction(self):
"""网格修正功能"""
target = self.get_selected_target()
if not target:
return
# 创建网格修正窗口
self.create_grid_correction_window(target)
def create_grid_correction_window(self, target: TradeTarget):
"""创建网格修正窗口"""
# 创建顶层窗口
correction_window = tk.Toplevel(self.root)
correction_window.title(f"网格修正 - {target.stock_code} ({target.stock_name})")
correction_window.geometry("500x400")
correction_window.resizable(False, False)
# 设置窗口模态
correction_window.transient(self.root)
correction_window.grab_set()
# 居中显示
self.root.update_idletasks()
x = self.root.winfo_x() + (self.root.winfo_width() // 2) - 250
y = self.root.winfo_y() + (self.root.winfo_height() // 2) - 200
correction_window.geometry(f"500x400+{x}+{y}")
# 创建主框架
main_frame = ttk.Frame(correction_window, padding=20)
main_frame.pack(fill=tk.BOTH, expand=True)
# 显示股票信息
info_frame = ttk.LabelFrame(main_frame, text="标的详情", padding=10)
info_frame.pack(fill=tk.X, pady=(0, 10))
ttk.Label(info_frame, text=f"股票代码: {target.stock_code}").grid(row=0, column=0, sticky=tk.W, pady=2)
ttk.Label(info_frame, text=f"股票名称: {target.stock_name}").grid(row=0, column=1, sticky=tk.W, padx=(20, 0), pady=2)
# 创建修正选项框架
options_frame = ttk.LabelFrame(main_frame, text="修正选项", padding=10)
options_frame.pack(fill=tk.X, pady=(0, 10))
# 网格序号
grid_index_frame = ttk.Frame(options_frame)
grid_index_frame.pack(fill=tk.X, pady=5)
ttk.Label(grid_index_frame, text="网格序号:", width=12).pack(side=tk.LEFT)
# 网格序号调整控件
grid_index_var = tk.IntVar(value=getattr(target, 'grid_index'))
# 当前持仓量
position_frame = ttk.Frame(options_frame)
position_frame.pack(fill=tk.X, pady=5)
current_position_value = getattr(target, 'current_position')
ttk.Label(position_frame, text="当前持仓量:", width=12).pack(side=tk.LEFT)
ttk.Label(position_frame, text=str(current_position_value), width=10, anchor=tk.CENTER).pack(side=tk.LEFT, padx=5)
# 需求持仓量
required_position_frame = ttk.Frame(options_frame)
required_position_frame.pack(fill=tk.X, pady=5)
grid_index_value = getattr(target, 'grid_index')
required_position = grid_index_value * sfgrid_constants.grid_volume
ttk.Label(required_position_frame, text="需求持仓量:", width=12).pack(side=tk.LEFT)
required_position_label = ttk.Label(required_position_frame, text=str(required_position), width=10, anchor=tk.CENTER)
required_position_label.pack(side=tk.LEFT, padx=5)
# 持仓量状态提示
position_status_frame = ttk.Frame(options_frame)
position_status_frame.pack(fill=tk.X, pady=5)
position_status_label = ttk.Label(position_status_frame, text="", foreground="red")
position_status_label.pack(side=tk.LEFT, padx=(12, 0))
# 初始化持仓量状态
self.update_position_status(current_position_value, required_position, position_status_label)
# 网格序号显示和按钮
grid_index_label = ttk.Label(grid_index_frame, textvariable=grid_index_var, width=10, anchor=tk.CENTER)
grid_index_label.pack(side=tk.LEFT, padx=5)
# 减少按钮
ttk.Button(grid_index_frame, text="-", width=3,
command=lambda: self.decrease_grid_index(grid_index_var, target, required_position_label, position_status_label)).pack(side=tk.LEFT, padx=(5, 5))
# 增加按钮
ttk.Button(grid_index_frame, text="+", width=3,
command=lambda: self.increase_grid_index(grid_index_var, len(sfgrid_constants.grid_price)-1, target, required_position_label, position_status_label)).pack(side=tk.LEFT, padx=(5, 0))
# 当前价格(实时更新)
price_frame = ttk.Frame(options_frame)
price_frame.pack(fill=tk.X, pady=5)
ttk.Label(price_frame, text="当前价格:", width=12).pack(side=tk.LEFT)
current_price_var = tk.StringVar(value="-")
current_price_label = ttk.Label(price_frame, textvariable=current_price_var, width=10, anchor=tk.CENTER)
current_price_label.pack(side=tk.LEFT, padx=5)
# 保存按钮框架
button_frame = ttk.Frame(main_frame)
button_frame.pack(fill=tk.X, pady=(10, 0))
# 保存按钮
ttk.Button(button_frame, text="确认修正",
command=lambda: self.save_grid_correction(correction_window, target, grid_index_var.get())).pack(side=tk.RIGHT, padx=5)
# 取消按钮
ttk.Button(button_frame, text="取消",
command=correction_window.destroy).pack(side=tk.RIGHT, padx=5)
# 监听市场数据更新
def on_market_data_update(updated_target: TradeTarget):
if updated_target.get_id() == target.get_id():
current_price_var.set(f"{updated_target.market_price:.3f}" if updated_target.market_price else "-")
# 订阅市场数据更新事件
eBus.event_bus.subscribe(eBus.MarketDataUpdate, on_market_data_update)
# 窗口关闭时取消订阅
def on_window_close():
if eBus.MarketDataUpdate in eBus.event_bus.listeners and on_market_data_update in eBus.event_bus.listeners[eBus.MarketDataUpdate]:
eBus.event_bus.listeners[eBus.MarketDataUpdate].remove(on_market_data_update)
correction_window.destroy()
correction_window.protocol("WM_DELETE_WINDOW", on_window_close)
# 初始化当前价格
if target.market_price is not None:
current_price_var.set(f"{target.market_price:.3f}")
def update_position_status(self, current_position: int, required_position: int, status_label: ttk.Label):
"""更新持仓量状态提示"""
if current_position >= required_position:
status_label.config(text="持仓量充足", foreground="green")
else:
shortage = required_position - current_position
status_label.config(text=f"还需补充 {shortage} 手仓位", foreground="red")
def save_grid_correction(self, window, target: TradeTarget, new_grid_index: int):
"""保存网格修正"""
# 更新网格序号
setattr(target, 'grid_index', new_grid_index)
# 重新计算需求持仓量
required_position = new_grid_index * sfgrid_constants.grid_volume
# 检查持仓量是否满足要求
current_position = getattr(target, 'current_position')
if current_position < required_position:
shortage = required_position - current_position
result = messagebox.askyesno(
"持仓量不足",
f"当前持仓量({current_position}手)小于需求持仓量({required_position}手)\n"
f"还需补充 {shortage} 手仓位,是否继续保存?"
)
if not result:
return
# 保存到数据库(这里需要发布事件让控制器处理)
# TODO: 发布保存事件到控制器
# 关闭窗口
window.destroy()
# 添加日志
self.add_log(LogLevel.INFO, f"网格修正已保存: {target.stock_code} - {target.stock_name}, 网格序号: {new_grid_index}")
def run(self):
"""运行程序"""
self.root.mainloop()
self.root.mainloop()
def decrease_grid_index(self, grid_index_var: tk.IntVar, target: TradeTarget, required_position_label: ttk.Label, position_status_label: ttk.Label):
"""减少网格序号"""
current_value = grid_index_var.get()
if current_value > 0:
grid_index_var.set(current_value - 1)
# 同步更新需求持仓量和持仓状态
self.update_required_position_and_status(grid_index_var.get(), target, required_position_label, position_status_label)
def increase_grid_index(self, grid_index_var: tk.IntVar, max_index: int, target: TradeTarget, required_position_label: ttk.Label, position_status_label: ttk.Label):
"""增加网格序号"""
current_value = grid_index_var.get()
if current_value < max_index:
grid_index_var.set(current_value + 1)
# 同步更新需求持仓量和持仓状态
self.update_required_position_and_status(grid_index_var.get(), target, required_position_label, position_status_label)
def update_required_position_and_status(self, grid_index: int, target: TradeTarget, required_position_label: ttk.Label, position_status_label: ttk.Label):
"""更新需求持仓量和持仓状态"""
# 计算需求持仓量
required_position = grid_index * sfgrid_constants.grid_volume
required_position_label.config(text=str(required_position))
# 更新持仓量状态
current_position = getattr(target, 'current_position')
self.update_position_status(current_position, required_position, position_status_label)