update
This commit is contained in:
@@ -0,0 +1,4 @@
|
||||
import xtquant.xtconstant as xtconstant
|
||||
|
||||
HeatTypeUpStop = "UpStop" # 涨停
|
||||
HeatTypeDragonTiger = "DragonTiger" # 龙虎榜
|
||||
@@ -0,0 +1,11 @@
|
||||
from peewee import CharField, DateField
|
||||
|
||||
from core.database import BaseModel, db
|
||||
|
||||
class HeatStock(BaseModel):
|
||||
stock_code = CharField(unique=True)
|
||||
stock_name = CharField()
|
||||
heat_type = CharField()
|
||||
date = DateField()
|
||||
|
||||
db.create_tables([HeatStock])
|
||||
+46
-9
@@ -1,6 +1,6 @@
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from core.logger import LogLevel, PrintLog
|
||||
from core.logger import LogLevel
|
||||
from core.sfgrid.sfgrid_ui import TradeTargetUI
|
||||
|
||||
|
||||
@@ -35,16 +35,20 @@ class MainWindow:
|
||||
tab_bar_frame = ttk.Frame(content_area)
|
||||
tab_bar_frame.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 10))
|
||||
|
||||
# 创建自定义样式
|
||||
self.create_custom_styles()
|
||||
|
||||
# 创建Tab按钮(垂直排列,文字垂直显示)
|
||||
self.tab_buttons = []
|
||||
strategy_names = ["蒙派\n策略", "涨停\n分析"]
|
||||
strategy_names = ["蒙派\n策略", "涨停\n复盘"]
|
||||
|
||||
for idx, name in enumerate(strategy_names):
|
||||
btn = ttk.Button(
|
||||
tab_bar_frame,
|
||||
text=name,
|
||||
command=lambda i=idx: self.switch_strategy_tab(i),
|
||||
width=4
|
||||
width=4,
|
||||
style='Bookmark.TButton' # 使用自定义书签样式
|
||||
)
|
||||
btn.pack(side=tk.TOP, pady=2, fill=tk.X)
|
||||
self.tab_buttons.append(btn)
|
||||
@@ -98,6 +102,38 @@ class MainWindow:
|
||||
# 默认显示第一个策略
|
||||
self.switch_strategy_tab(0)
|
||||
|
||||
def create_custom_styles(self):
|
||||
"""创建自定义样式"""
|
||||
style = ttk.Style()
|
||||
|
||||
# 创建书签样式
|
||||
style.configure(
|
||||
'Bookmark.TButton',
|
||||
relief='flat',
|
||||
borderwidth=1,
|
||||
padding=(5, 10),
|
||||
foreground='black',
|
||||
background='#FFE599', # 浅黄色背景,类似便签纸
|
||||
font=('Arial', 10, 'bold')
|
||||
)
|
||||
|
||||
# 设置焦点样式(选中状态)
|
||||
style.map(
|
||||
'Bookmark.TButton',
|
||||
background=[('active', '#F1C232'), ('pressed', '#F1C232')],
|
||||
relief=[('pressed', 'sunken')]
|
||||
)
|
||||
|
||||
# 创建选中状态的书签样式
|
||||
style.configure(
|
||||
'SelectedBookmark.TButton',
|
||||
relief='flat',
|
||||
borderwidth=1,
|
||||
padding=(5, 10),
|
||||
background='#3D85C6', # 蓝色背景表示选中状态
|
||||
font=('Arial', 10, 'bold')
|
||||
)
|
||||
|
||||
def create_global_log_panel(self, parent):
|
||||
"""创建全局日志面板"""
|
||||
# 日志区域(默认隐藏)
|
||||
@@ -143,7 +179,6 @@ class MainWindow:
|
||||
# 删除所有日志项
|
||||
for item in self.log_table.get_children():
|
||||
self.log_table.delete(item)
|
||||
self.add_log(LogLevel.DEBUG, "日志已清空")
|
||||
|
||||
def create_strategy_frames(self, strategy_names):
|
||||
"""创建各个策略的Frame"""
|
||||
@@ -184,9 +219,12 @@ class MainWindow:
|
||||
|
||||
def update_tab_button_styles(self):
|
||||
"""更新Tab按钮的样式以显示选中状态"""
|
||||
# 注意:ttk.Button的样式需要通过ttk.Style来设置
|
||||
# 这里简化处理,仅作为接口预留
|
||||
pass
|
||||
# 重置所有按钮为普通书签样式
|
||||
for i, btn in enumerate(self.tab_buttons):
|
||||
if i == self.current_strategy_index:
|
||||
btn.configure(style='SelectedBookmark.TButton') # 选中状态
|
||||
else:
|
||||
btn.configure(style='Bookmark.TButton') # 普通状态
|
||||
|
||||
def toggle_log_panel(self):
|
||||
"""切换日志面板的显示/隐藏"""
|
||||
@@ -210,5 +248,4 @@ class MainWindow:
|
||||
|
||||
def run(self):
|
||||
"""运行程序"""
|
||||
self.root.mainloop()
|
||||
|
||||
self.root.mainloop()
|
||||
+281
-321
@@ -8,7 +8,6 @@ import time
|
||||
from core import constants
|
||||
import core.eventbus as eBus
|
||||
from core.logger import LogLevel, PrintLog
|
||||
from core.sfgrid.bus_events import ActionEventAddTradeTarget
|
||||
from core.sfgrid.model import SFGridTradeTarget
|
||||
import configparser
|
||||
import config
|
||||
@@ -27,9 +26,6 @@ class TradeTargetUI(ttk.Frame):
|
||||
self.init_trade_target_pool()
|
||||
eBus.event_bus.subscribe(eBus.MarketDataUpdate, self.onMarketDataUpdated)
|
||||
|
||||
# 创建刷新线程标志
|
||||
self.refresh_thread_running = False # 默认不启动刷新线程
|
||||
|
||||
# 市场监控数据
|
||||
self.marketData: dict[str, Any] = {} # 存储市场数据 {stock_code: {stock_name, last_price, time}}
|
||||
|
||||
@@ -39,7 +35,7 @@ class TradeTargetUI(ttk.Frame):
|
||||
# 创建界面
|
||||
self.create_ui()
|
||||
|
||||
self.start_ui_refresh()
|
||||
self.start_refresh_thread()
|
||||
|
||||
def onMarketDataUpdated(self, data):
|
||||
# 收集所有市场数据用于市场监控
|
||||
@@ -48,7 +44,7 @@ class TradeTargetUI(ttk.Frame):
|
||||
id:int = self.stockCodeIdMap[stock_code]
|
||||
tradeTarget = self.tradeTargetData[id]
|
||||
lastPrice = float("{:.3f}".format(tickData['lastPrice']))
|
||||
print(f'股票代码: {stock_code} {id}, 市场数据更新 {lastPrice}')
|
||||
PrintLog(LogLevel.INFO, f'股票代码: {stock_code} {id}, 市场数据更新 {lastPrice}')
|
||||
tradeTarget.market_price = lastPrice # type: ignore
|
||||
self.updateTradeTarget(tradeTarget)
|
||||
stock_controller: SFGridStrategy = self.strategy_ctrl[id]
|
||||
@@ -71,61 +67,41 @@ class TradeTargetUI(ttk.Frame):
|
||||
'last_price': tickData['lastPrice'],
|
||||
'time': current_time
|
||||
}
|
||||
|
||||
def refresh_targets(self):
|
||||
# 更新标的池
|
||||
results = SFGridTradeTarget.select()
|
||||
for temp in results:
|
||||
result :SFGridTradeTarget = temp
|
||||
self.tradeTargetData[result.get_id()] = result
|
||||
self.stockCodeIdMap[str(result.stock_code)] = result.get_id()
|
||||
|
||||
|
||||
def init_trade_target_pool(self):
|
||||
self.refresh_targets()
|
||||
results = SFGridTradeTarget.select()
|
||||
for temp in results:
|
||||
tradeTarget :SFGridTradeTarget = temp
|
||||
id = tradeTarget.get_id()
|
||||
|
||||
for id, tradeTarget in self.tradeTargetData.items():
|
||||
status = "新建" if tradeTarget.status == 0 else "已建初始仓"
|
||||
PrintLog(LogLevel.INFO, f' [序号-{id}] 股票代码: {tradeTarget.stock_code}-{tradeTarget.stock_name} 当前持仓: {qmtv.getStockPosition(tradeTarget.stock_code)} 网格索引: {tradeTarget.grid_index} 基准价格 {tradeTarget.getPriceGrid()[tradeTarget.grid_index]} 状态: {status} 启用交易线程: {'自动交易中' if tradeTarget.enabled else '交易已停止'}') # type: ignore
|
||||
|
||||
tradeTarget.current_position = qmtv.getStockPosition(tradeTarget.stock_code) # type: ignore
|
||||
result = tradeTarget.save()
|
||||
PrintLog(LogLevel.INFO, f' |- 同步[{tradeTarget.stock_code}-{tradeTarget.stock_name}]持仓信息[{'成功' if result == 1 else '失败'}]')
|
||||
tradeTarget.save()
|
||||
PrintLog(LogLevel.INFO, f' [序号-{id}] 股票代码: {tradeTarget.stock_code}-{tradeTarget.stock_name} 当前持仓: {qmtv.getStockPosition(tradeTarget.stock_code)} 网格索引: {tradeTarget.grid_index} 基准价格 {tradeTarget.getPriceGrid()[tradeTarget.grid_index]} 状态: {status} 启用交易线程: {'自动交易中' if tradeTarget.enabled else '交易已停止'}') # type: ignore
|
||||
stockTradeController = SFGridStrategy(tradeTarget) # type: ignore
|
||||
self.strategy_ctrl[id] = stockTradeController # pyright: ignore[reportArgumentType]
|
||||
self.updateTradeTarget(tradeTarget)
|
||||
|
||||
PrintLog(LogLevel.INFO, f'- [成功]交易标的信息初始化, 共 {len(self.tradeTargetData)} 个标的')
|
||||
|
||||
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
|
||||
self.after(0, self.refresh_table)
|
||||
self.after(0, self.populate_market_table)
|
||||
time.sleep(0.2) # 每0.5秒刷新一次
|
||||
|
||||
def stop_refresh_thread(self):
|
||||
"""停止刷新线程"""
|
||||
self.refresh_thread_running = False
|
||||
|
||||
|
||||
def onTradeEnabled(self, target:SFGridTradeTarget):
|
||||
PrintLog(LogLevel.INFO, f"交易启用: {target.stock_code} - {target.stock_name}")
|
||||
|
||||
def onTradeDisabled(self, target:SFGridTradeTarget):
|
||||
PrintLog(LogLevel.INFO, f"交易禁用: {target.stock_code} - {target.stock_name}")
|
||||
|
||||
def updateTradeTarget(self, target: SFGridTradeTarget):
|
||||
# 更新或添加数据到本地缓存
|
||||
self.tradeTargetData[target.get_id()] = target
|
||||
self.stockCodeIdMap[target.stock_code] = target.get_id() # type: ignore
|
||||
|
||||
def start_refresh_thread(self):
|
||||
"""启动刷新线程"""
|
||||
self.refresh_thread = threading.Thread(target=self.refresh_loop, daemon=True)
|
||||
self.refresh_thread.start()
|
||||
PrintLog(LogLevel.INFO, "UI刷新线程已启动")
|
||||
|
||||
def refresh_loop(self):
|
||||
"""刷新循环"""
|
||||
while True:
|
||||
self.after(0, self.refresh_table)
|
||||
self.after(0, self.populate_market_table)
|
||||
time.sleep(0.2) # 每0.5秒刷新一次
|
||||
|
||||
def create_ui(self):
|
||||
"""创建UI界面"""
|
||||
@@ -144,33 +120,16 @@ class TradeTargetUI(ttk.Frame):
|
||||
command=self.pause_selected_trade, width=12).pack(side=tk.LEFT, padx=2)
|
||||
ttk.Button(toolbar_frame, text="➕ 添加标的",
|
||||
command=self.add_trade_target, width=12).pack(side=tk.LEFT, padx=2)
|
||||
ttk.Button(toolbar_frame, text="🛠 网格配置",
|
||||
command=self.grid_settings, 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)
|
||||
|
||||
# 添加抽屉按钮到工具栏最右侧
|
||||
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)
|
||||
ttk.Button(toolbar_frame, text="🛠 交易设置",
|
||||
command=self.trade_settings, width=12).pack(side=tk.LEFT, padx=2)
|
||||
ttk.Button(toolbar_frame, text="▣ 实时监控",
|
||||
command=self.toggle_market_monitor, width=12).pack(side=tk.RIGHT, padx=2)
|
||||
|
||||
# 表格区域
|
||||
self.create_tables_area(main_frame)
|
||||
|
||||
def start_ui_refresh(self):
|
||||
"""启动UI刷新线程"""
|
||||
if not self.refresh_thread_running:
|
||||
self.refresh_thread_running = True
|
||||
self.start_refresh_thread()
|
||||
PrintLog(LogLevel.INFO, "UI刷新线程已启动")
|
||||
|
||||
def stop_ui_refresh(self):
|
||||
"""停止UI刷新线程"""
|
||||
if self.refresh_thread_running:
|
||||
self.stop_refresh_thread()
|
||||
self.refresh_thread_running = False
|
||||
PrintLog(LogLevel.INFO, "UI刷新线程已停止")
|
||||
|
||||
|
||||
def create_tables_area(self, parent):
|
||||
"""创建表格区域"""
|
||||
@@ -191,6 +150,19 @@ class TradeTargetUI(ttk.Frame):
|
||||
|
||||
# 创建市场监控表格
|
||||
self.create_market_monitor_table(self.market_frame)
|
||||
|
||||
|
||||
def toggle_market_monitor(self):
|
||||
"""切换市场监控窗口显示/隐藏"""
|
||||
if self.market_monitor_visible:
|
||||
# 隐藏市场监控窗口
|
||||
self.market_frame.pack_forget()
|
||||
self.market_monitor_visible = False
|
||||
else:
|
||||
# 显示市场监控窗口
|
||||
self.market_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(5, 0))
|
||||
self.market_monitor_visible = True
|
||||
|
||||
|
||||
def create_trade_target_table(self, parent):
|
||||
"""创建交易标的表格"""
|
||||
@@ -216,7 +188,7 @@ class TradeTargetUI(ttk.Frame):
|
||||
"当前订单价": (90, tk.E),
|
||||
"当前订单号": (90, tk.E),
|
||||
"当前订单类型": (90, tk.E),
|
||||
"交易状态": (80, tk.E)
|
||||
"交易状态": (80, tk.CENTER)
|
||||
}
|
||||
|
||||
for col in columns:
|
||||
@@ -343,14 +315,14 @@ class TradeTargetUI(ttk.Frame):
|
||||
|
||||
if result:
|
||||
# 发布事件通知主控制器添加标的
|
||||
self.onAddTradeTarget(stock_code)
|
||||
self.addTradeTarget(stock_code)
|
||||
|
||||
def get_trade_enabled_indicator(self, enabled: bool) -> str:
|
||||
"""获取交易状态指示器"""
|
||||
if enabled:
|
||||
return "🟢 策略运行"
|
||||
return "▶ 运行中"
|
||||
else:
|
||||
return "🟡 策略暂停"
|
||||
return "⏸ 已停止"
|
||||
|
||||
def populate_trade_table(self):
|
||||
"""填充交易标的表格数据"""
|
||||
@@ -495,9 +467,8 @@ class TradeTargetUI(ttk.Frame):
|
||||
icon='warning'
|
||||
)
|
||||
|
||||
id = target.get_id()
|
||||
if result:
|
||||
# 通过事件总线发出删除动作
|
||||
id = target.get_id()
|
||||
try:
|
||||
# 从数据库中删除
|
||||
target.delete_instance()
|
||||
@@ -553,7 +524,7 @@ class TradeTargetUI(ttk.Frame):
|
||||
return
|
||||
|
||||
# 发布事件通知主控制器添加标的
|
||||
eBus.event_bus.publish(ActionEventAddTradeTarget, stock_code)
|
||||
self.addTradeTarget(stock_code)
|
||||
add_window.destroy()
|
||||
|
||||
def cancel_add():
|
||||
@@ -595,143 +566,221 @@ class TradeTargetUI(ttk.Frame):
|
||||
# 刷新市场监控表格
|
||||
self.populate_market_table()
|
||||
|
||||
def system_settings(self):
|
||||
"""系统设置"""
|
||||
def trade_settings(self):
|
||||
"""网格配置功能"""
|
||||
target = self.get_selected_target()
|
||||
if not target:
|
||||
return
|
||||
|
||||
# 获取顶层窗口
|
||||
root = self.winfo_toplevel()
|
||||
|
||||
settings_window = tk.Toplevel(root)
|
||||
settings_window.title("网格交易系统配置")
|
||||
# 创建顶层窗口
|
||||
view_window = tk.Toplevel(root)
|
||||
view_window.title(f"网格配置查看 - {target.stock_code} ({target.stock_name})")
|
||||
view_window.geometry("500x450")
|
||||
view_window.resizable(False, False)
|
||||
|
||||
# 设置窗口大小
|
||||
window_width = 700
|
||||
window_height = 550
|
||||
# 检查标的的状态,status为1时仅可查看
|
||||
# if target.status == 1:
|
||||
# # 创建只读的网格配置查看窗口
|
||||
# self.create_grid_view_window(target)
|
||||
# else:
|
||||
# # 创建可编辑的网格配置窗口
|
||||
# self.create_grid_config_window(target)
|
||||
|
||||
def create_grid_view_window(self, target: SFGridTradeTarget):
|
||||
"""创建网格配置查看窗口(只读)"""
|
||||
# 获取顶层窗口
|
||||
root = self.winfo_toplevel()
|
||||
|
||||
# 先设置为模态窗口
|
||||
settings_window.transient(root)
|
||||
# 创建顶层窗口
|
||||
view_window = tk.Toplevel(root)
|
||||
view_window.title(f"网格配置查看 - {target.stock_code} ({target.stock_name})")
|
||||
view_window.geometry("500x450")
|
||||
view_window.resizable(False, False)
|
||||
|
||||
# 确保主窗口完全初始化
|
||||
# 设置窗口模态
|
||||
view_window.transient(root)
|
||||
view_window.grab_set()
|
||||
|
||||
# 居中显示
|
||||
root.update_idletasks()
|
||||
x = root.winfo_x() + (root.winfo_width() // 2) - 250
|
||||
y = root.winfo_y() + (root.winfo_height() // 2) - 225
|
||||
view_window.geometry(f"500x450+{x}+{y}")
|
||||
|
||||
# 获取主窗口的实际大小(包括边框)
|
||||
# 使用winfo_rootx/rooty获取窗口在屏幕上的绝对位置
|
||||
main_x = root.winfo_rootx()
|
||||
main_y = root.winfo_rooty()
|
||||
main_width = root.winfo_width()
|
||||
main_height = root.winfo_height()
|
||||
# 创建主框架
|
||||
main_frame = ttk.Frame(view_window, padding=20)
|
||||
main_frame.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
# 计算设置窗口相对于主窗口的居中位置
|
||||
x = main_x + (main_width - window_width) // 2
|
||||
y = main_y + (main_height - window_height) // 2
|
||||
# 显示股票信息
|
||||
info_frame = ttk.LabelFrame(main_frame, text="标的详情", padding=10)
|
||||
info_frame.pack(fill=tk.X, pady=(0, 10))
|
||||
|
||||
# 设置窗口大小和位置
|
||||
settings_window.geometry(f"{window_width}x{window_height}+{x}+{y}")
|
||||
settings_window.resizable(False, False)
|
||||
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)
|
||||
ttk.Label(info_frame, text=f"状态: 已建初始仓(仅查看模式)").grid(row=1, column=0, columnspan=2, sticky=tk.W, pady=2)
|
||||
|
||||
# 设置为模态窗口
|
||||
settings_window.grab_set()
|
||||
# 创建网格配置查看框架
|
||||
config_frame = ttk.LabelFrame(main_frame, text="网格配置", padding=10)
|
||||
config_frame.pack(fill=tk.X, pady=(0, 10))
|
||||
|
||||
# 添加底部按钮区域(先创建,确保固定在底部)
|
||||
button_frame = ttk.Frame(settings_window)
|
||||
button_frame.pack(side=tk.BOTTOM, fill=tk.X, padx=20, pady=10)
|
||||
# 基准价格
|
||||
base_price_frame = ttk.Frame(config_frame)
|
||||
base_price_frame.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(base_price_frame, text="基准价格:", width=15).pack(side=tk.LEFT)
|
||||
ttk.Label(base_price_frame, text=f"{target.grid_start_price:.3f}", width=15, anchor=tk.W).pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(base_price_frame, text="元", foreground='gray').pack(side=tk.LEFT)
|
||||
|
||||
# 创建选项卡(在按钮之后创建,填充剩余空间)
|
||||
notebook = ttk.Notebook(settings_window)
|
||||
notebook.pack(fill=tk.BOTH, expand=True, padx=10, pady=(10, 0))
|
||||
# 网格大小
|
||||
grid_size_frame = ttk.Frame(config_frame)
|
||||
grid_size_frame.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(grid_size_frame, text="网格大小:", width=15).pack(side=tk.LEFT)
|
||||
ttk.Label(grid_size_frame, text=f"{target.grid_size:.3f}", width=15, anchor=tk.W).pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(grid_size_frame, text="元", foreground='gray').pack(side=tk.LEFT)
|
||||
|
||||
# 基础设置
|
||||
basic_frame = ttk.Frame(notebook)
|
||||
notebook.add(basic_frame, text="基础设置")
|
||||
# 网格交易量
|
||||
grid_volume_frame = ttk.Frame(config_frame)
|
||||
grid_volume_frame.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(grid_volume_frame, text="网格交易量:", width=15).pack(side=tk.LEFT)
|
||||
ttk.Label(grid_volume_frame, text=str(target.grid_volume), width=15, anchor=tk.W).pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(grid_volume_frame, text="股", foreground='gray').pack(side=tk.LEFT)
|
||||
|
||||
# 高级设置
|
||||
advanced_frame = ttk.Frame(notebook)
|
||||
notebook.add(advanced_frame, text="高级设置")
|
||||
# 上方网格数量
|
||||
upper_count_frame = ttk.Frame(config_frame)
|
||||
upper_count_frame.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(upper_count_frame, text="上方网格数量:", width=15).pack(side=tk.LEFT)
|
||||
ttk.Label(upper_count_frame, text=str(target.grid_upper_count), width=15, anchor=tk.W).pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(upper_count_frame, text="格", foreground='gray').pack(side=tk.LEFT)
|
||||
|
||||
# 读取当前配置
|
||||
config = configparser.ConfigParser()
|
||||
config_path = config.get('config', 'config_path')
|
||||
config.read(config_path, encoding='utf-8')
|
||||
# 下方网格数量
|
||||
lower_count_frame = ttk.Frame(config_frame)
|
||||
lower_count_frame.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(lower_count_frame, text="下方网格数量:", width=15).pack(side=tk.LEFT)
|
||||
ttk.Label(lower_count_frame, text=str(target.grid_lower_count), width=15, anchor=tk.W).pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(lower_count_frame, text="格", foreground='gray').pack(side=tk.LEFT)
|
||||
|
||||
# 生成网格价格序列
|
||||
price_grid_frame = ttk.LabelFrame(main_frame, text="网格价格序列", padding=10)
|
||||
price_grid_frame.pack(fill=tk.X, pady=(0, 10))
|
||||
|
||||
# 计算并显示网格价格序列
|
||||
price_list = target.getPriceGrid()
|
||||
price_text = ", ".join([f"{price:.3f}" for price in price_list])
|
||||
|
||||
# 创建文本框显示网格价格序列
|
||||
text_frame = ttk.Frame(price_grid_frame)
|
||||
text_frame.pack(fill=tk.BOTH, expand=True)
|
||||
|
||||
text_widget = tk.Text(text_frame, height=4, wrap=tk.WORD)
|
||||
text_widget.insert(tk.END, price_text)
|
||||
text_widget.config(state=tk.DISABLED) # 只读
|
||||
|
||||
scrollbar = ttk.Scrollbar(text_frame, orient=tk.VERTICAL, command=text_widget.yview)
|
||||
text_widget.configure(yscrollcommand=scrollbar.set)
|
||||
|
||||
text_widget.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
|
||||
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
|
||||
|
||||
# 关闭按钮
|
||||
button_frame = ttk.Frame(main_frame)
|
||||
button_frame.pack(fill=tk.X, pady=(10, 0))
|
||||
ttk.Button(button_frame, text="关闭", command=view_window.destroy).pack(side=tk.RIGHT, padx=5)
|
||||
|
||||
def create_grid_config_window(self, target: SFGridTradeTarget):
|
||||
"""创建网格配置窗口(可编辑)"""
|
||||
# 获取顶层窗口
|
||||
root = self.winfo_toplevel()
|
||||
|
||||
# 创建顶层窗口
|
||||
config_window = tk.Toplevel(root)
|
||||
config_window.title(f"网格配置 - {target.stock_code} ({target.stock_name})")
|
||||
config_window.geometry("550x550")
|
||||
config_window.resizable(False, False)
|
||||
|
||||
# 设置窗口模态
|
||||
config_window.transient(root)
|
||||
config_window.grab_set()
|
||||
|
||||
# 居中显示
|
||||
root.update_idletasks()
|
||||
x = root.winfo_x() + (root.winfo_width() // 2) - 275
|
||||
y = root.winfo_y() + (root.winfo_height() // 2) - 275
|
||||
config_window.geometry(f"550x550+{x}+{y}")
|
||||
|
||||
# 创建主框架
|
||||
main_frame = ttk.Frame(config_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)
|
||||
ttk.Label(info_frame, text=f"状态: 新标的(可配置模式)").grid(row=1, column=0, columnspan=2, sticky=tk.W, pady=2)
|
||||
|
||||
# 创建网格配置框架
|
||||
config_frame = ttk.LabelFrame(main_frame, text="网格配置", padding=15)
|
||||
config_frame.pack(fill=tk.X, pady=(0, 10))
|
||||
|
||||
# 创建输入框字典用于保存引用
|
||||
entries = {}
|
||||
|
||||
# 网格价格计算参数
|
||||
grid_params = {}
|
||||
|
||||
# 添加网格价格设置(特殊处理)
|
||||
grid_price_frame = ttk.LabelFrame(basic_frame, text="网格价格设置", padding=15)
|
||||
grid_price_frame.pack(fill=tk.X, padx=20, pady=10)
|
||||
|
||||
# 基准价格
|
||||
base_price_row = ttk.Frame(grid_price_frame)
|
||||
base_price_row.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(base_price_row, text="基准价格:", width=15, font=('Arial', 10)).pack(side=tk.LEFT)
|
||||
base_price_entry = ttk.Entry(base_price_row, width=15, font=('Arial', 10))
|
||||
base_price_entry.insert(0, "10.0")
|
||||
base_price_frame = ttk.Frame(config_frame)
|
||||
base_price_frame.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(base_price_frame, text="基准价格:", width=15).pack(side=tk.LEFT)
|
||||
base_price_entry = ttk.Entry(base_price_frame, width=15)
|
||||
base_price_entry.insert(0, str(target.grid_start_price))
|
||||
base_price_entry.pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(base_price_row, text="元", foreground='gray', font=('Arial', 9)).pack(side=tk.LEFT)
|
||||
grid_params['base_price'] = base_price_entry
|
||||
|
||||
# 网格类型
|
||||
grid_type_row = ttk.Frame(grid_price_frame)
|
||||
grid_type_row.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(grid_type_row, text="网格类型:", width=15, font=('Arial', 10)).pack(side=tk.LEFT)
|
||||
|
||||
grid_type_var = tk.StringVar(value="金额差")
|
||||
ttk.Radiobutton(grid_type_row, text="百分比", variable=grid_type_var,
|
||||
value="百分比", command=lambda: on_grid_type_change()).pack(side=tk.LEFT, padx=5)
|
||||
ttk.Radiobutton(grid_type_row, text="金额差", variable=grid_type_var,
|
||||
value="金额差", command=lambda: on_grid_type_change()).pack(side=tk.LEFT, padx=5)
|
||||
|
||||
grid_params['grid_type'] = grid_type_var
|
||||
ttk.Label(base_price_frame, text="元", foreground='gray').pack(side=tk.LEFT)
|
||||
entries['grid_start_price'] = base_price_entry
|
||||
|
||||
# 网格大小
|
||||
grid_size_row = ttk.Frame(grid_price_frame)
|
||||
grid_size_row.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(grid_size_row, text="网格大小:", width=15, font=('Arial', 10)).pack(side=tk.LEFT)
|
||||
grid_size_entry = ttk.Entry(grid_size_row, width=15, font=('Arial', 10))
|
||||
grid_size_entry.insert(0, "1.0")
|
||||
grid_size_frame = ttk.Frame(config_frame)
|
||||
grid_size_frame.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(grid_size_frame, text="网格大小:", width=15).pack(side=tk.LEFT)
|
||||
grid_size_entry = ttk.Entry(grid_size_frame, width=15)
|
||||
grid_size_entry.insert(0, str(target.grid_size))
|
||||
grid_size_entry.pack(side=tk.LEFT, padx=5)
|
||||
grid_size_unit_label = ttk.Label(grid_size_row, text="元", foreground='gray', font=('Arial', 9))
|
||||
grid_size_unit_label.pack(side=tk.LEFT)
|
||||
grid_params['grid_size'] = grid_size_entry
|
||||
grid_params['grid_size_unit_label'] = grid_size_unit_label
|
||||
ttk.Label(grid_size_frame, text="元", foreground='gray').pack(side=tk.LEFT)
|
||||
entries['grid_size'] = grid_size_entry
|
||||
|
||||
# 网格类型改变时更新单位
|
||||
def on_grid_type_change():
|
||||
if grid_type_var.get() == "百分比":
|
||||
grid_size_unit_label.config(text="%")
|
||||
grid_size_entry.delete(0, tk.END)
|
||||
grid_size_entry.insert(0, "1.0")
|
||||
else:
|
||||
grid_size_unit_label.config(text="元")
|
||||
grid_size_entry.delete(0, tk.END)
|
||||
grid_size_entry.insert(0, "1.0")
|
||||
update_preview()
|
||||
# 网格交易量
|
||||
grid_volume_frame = ttk.Frame(config_frame)
|
||||
grid_volume_frame.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(grid_volume_frame, text="网格交易量:", width=15).pack(side=tk.LEFT)
|
||||
grid_volume_entry = ttk.Entry(grid_volume_frame, width=15)
|
||||
grid_volume_entry.insert(0, str(target.grid_volume))
|
||||
grid_volume_entry.pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(grid_volume_frame, text="手", foreground='gray').pack(side=tk.LEFT)
|
||||
entries['grid_volume'] = grid_volume_entry
|
||||
|
||||
# 上方网格数量
|
||||
upper_grid_row = ttk.Frame(grid_price_frame)
|
||||
upper_grid_row.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(upper_grid_row, text="上方网格数量:", width=15, font=('Arial', 10)).pack(side=tk.LEFT)
|
||||
upper_grid_entry = ttk.Entry(upper_grid_row, width=15, font=('Arial', 10))
|
||||
upper_grid_entry.insert(0, "1")
|
||||
upper_grid_entry.pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(upper_grid_row, text="格", foreground='gray', font=('Arial', 9)).pack(side=tk.LEFT)
|
||||
grid_params['upper_count'] = upper_grid_entry
|
||||
upper_count_frame = ttk.Frame(config_frame)
|
||||
upper_count_frame.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(upper_count_frame, text="上方网格数量:", width=15).pack(side=tk.LEFT)
|
||||
upper_count_entry = ttk.Entry(upper_count_frame, width=15)
|
||||
upper_count_entry.insert(0, str(target.grid_upper_count))
|
||||
upper_count_entry.pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(upper_count_frame, text="格", foreground='gray').pack(side=tk.LEFT)
|
||||
entries['grid_upper_count'] = upper_count_entry
|
||||
|
||||
# 下方网格数量
|
||||
lower_grid_row = ttk.Frame(grid_price_frame)
|
||||
lower_grid_row.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(lower_grid_row, text="下方网格数量:", width=15, font=('Arial', 10)).pack(side=tk.LEFT)
|
||||
lower_grid_entry = ttk.Entry(lower_grid_row, width=15, font=('Arial', 10))
|
||||
lower_grid_entry.insert(0, "10")
|
||||
lower_grid_entry.pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(lower_grid_row, text="格", foreground='gray', font=('Arial', 9)).pack(side=tk.LEFT)
|
||||
grid_params['lower_count'] = lower_grid_entry
|
||||
lower_count_frame = ttk.Frame(config_frame)
|
||||
lower_count_frame.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(lower_count_frame, text="下方网格数量:", width=15).pack(side=tk.LEFT)
|
||||
lower_count_entry = ttk.Entry(lower_count_frame, width=15)
|
||||
lower_count_entry.insert(0, str(target.grid_lower_count))
|
||||
lower_count_entry.pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(lower_count_frame, text="格", foreground='gray').pack(side=tk.LEFT)
|
||||
entries['grid_lower_count'] = lower_count_entry
|
||||
|
||||
# 预览按钮和结果显示
|
||||
preview_row = ttk.Frame(grid_price_frame)
|
||||
preview_row.pack(fill=tk.X, pady=10)
|
||||
preview_frame = ttk.LabelFrame(main_frame, text="网格价格序列预览", padding=10)
|
||||
preview_frame.pack(fill=tk.X, pady=(0, 10))
|
||||
|
||||
preview_result = tk.StringVar(value="点击'预览'查看生成的网格价格序列")
|
||||
|
||||
@@ -740,18 +789,14 @@ class TradeTargetUI(ttk.Frame):
|
||||
try:
|
||||
base_price = float(base_price_entry.get())
|
||||
grid_size = float(grid_size_entry.get())
|
||||
upper_count = int(upper_grid_entry.get())
|
||||
lower_count = int(lower_grid_entry.get())
|
||||
grid_type = grid_type_var.get()
|
||||
upper_count = int(upper_count_entry.get())
|
||||
lower_count = int(lower_count_entry.get())
|
||||
|
||||
prices = []
|
||||
|
||||
# 计算上方网格价格
|
||||
for i in range(upper_count, 0, -1):
|
||||
if grid_type == "百分比":
|
||||
price = base_price * (1 + grid_size / 100 * i)
|
||||
else: # 金额差
|
||||
price = base_price + grid_size * i
|
||||
price = base_price + grid_size * i
|
||||
prices.append(round(price, 3))
|
||||
|
||||
# 添加基准价格
|
||||
@@ -759,10 +804,7 @@ class TradeTargetUI(ttk.Frame):
|
||||
|
||||
# 计算下方网格价格
|
||||
for i in range(1, lower_count + 1):
|
||||
if grid_type == "百分比":
|
||||
price = base_price * (1 - grid_size / 100 * i)
|
||||
else: # 金额差
|
||||
price = base_price - grid_size * i
|
||||
price = base_price - grid_size * i
|
||||
# 确保价格不为负
|
||||
if price >= 0:
|
||||
prices.append(round(price, 3))
|
||||
@@ -770,145 +812,75 @@ class TradeTargetUI(ttk.Frame):
|
||||
break
|
||||
|
||||
return prices
|
||||
except ValueError as e:
|
||||
except ValueError:
|
||||
return None
|
||||
|
||||
def update_preview():
|
||||
"""自动更新网格价格序列预览"""
|
||||
"""更新网格价格序列预览"""
|
||||
prices = calculate_grid_prices()
|
||||
if prices:
|
||||
price_str = ",".join([str(p) for p in prices])
|
||||
price_str = ", ".join([str(p) for p in prices])
|
||||
preview_result.set(f"网格价格序列: {price_str}")
|
||||
else:
|
||||
preview_result.set("参数错误,请检查!")
|
||||
preview_result.set("参数错误,请检查输入!")
|
||||
|
||||
# 绑定输入变化自动预览
|
||||
for entry_widget in (base_price_entry, grid_size_entry, upper_grid_entry, lower_grid_entry):
|
||||
for entry_widget in entries.values():
|
||||
entry_widget.bind("<KeyRelease>", lambda e: update_preview())
|
||||
entry_widget.bind("<FocusOut>", lambda e: update_preview())
|
||||
|
||||
# 预览按钮
|
||||
preview_button_frame = ttk.Frame(preview_frame)
|
||||
preview_button_frame.pack(fill=tk.X, pady=5)
|
||||
# ttk.Button(preview_button_frame, text="预览", command=update_preview).pack(side=tk.LEFT)
|
||||
|
||||
# 预览结果显示
|
||||
preview_label = ttk.Label(preview_button_frame, textvariable=preview_result, foreground='blue')
|
||||
preview_label.pack(side=tk.LEFT, padx=10)
|
||||
|
||||
# 初始预览
|
||||
update_preview()
|
||||
ttk.Label(preview_row, textvariable=preview_result,
|
||||
font=('Arial', 10)).pack(side=tk.LEFT, padx=10)
|
||||
|
||||
# 添加其他基础配置选项
|
||||
other_basic_frame = ttk.LabelFrame(basic_frame, text="交易设置", padding=15)
|
||||
other_basic_frame.pack(fill=tk.X, padx=20, pady=10)
|
||||
# 按钮框架
|
||||
button_frame = ttk.Frame(main_frame)
|
||||
button_frame.pack(fill=tk.X, pady=(10, 0))
|
||||
|
||||
other_basic_settings = [
|
||||
("网格交易手数", "grid_volume", config.get('config', 'grid_volume'), "每个网格的交易手数")
|
||||
]
|
||||
|
||||
for i, (label, key, default, tooltip) in enumerate(other_basic_settings):
|
||||
frame = ttk.Frame(other_basic_frame)
|
||||
frame.pack(fill=tk.X, pady=5)
|
||||
|
||||
label_widget = ttk.Label(frame, text=label + ":", width=15, font=('Arial', 10))
|
||||
label_widget.pack(side=tk.LEFT)
|
||||
|
||||
entry = ttk.Entry(frame, width=15, font=('Arial', 10))
|
||||
entry.insert(0, default)
|
||||
entry.pack(side=tk.LEFT, padx=5)
|
||||
entries[key] = entry
|
||||
|
||||
# 添加提示信息
|
||||
tip_label = ttk.Label(frame, text=tooltip, font=('Arial', 9), foreground='gray')
|
||||
tip_label.pack(side=tk.LEFT, padx=5)
|
||||
|
||||
# 添加高级设置选项
|
||||
account_frame = ttk.LabelFrame(advanced_frame, text="账号设置", padding=15)
|
||||
account_frame.pack(fill=tk.X, padx=20, pady=10)
|
||||
|
||||
# 交易账号
|
||||
account_row = ttk.Frame(account_frame)
|
||||
account_row.pack(fill=tk.X, pady=5)
|
||||
ttk.Label(account_row, text="交易账号:", width=15, font=('Arial', 10)).pack(side=tk.LEFT)
|
||||
account_entry = ttk.Entry(account_row, width=15, font=('Arial', 10))
|
||||
account_entry.insert(0, config.get('config', 'account_no'))
|
||||
account_entry.pack(side=tk.LEFT, padx=5)
|
||||
entries['account_no'] = account_entry
|
||||
ttk.Label(account_row, text="QMT交易账号", font=('Arial', 9), foreground='gray').pack(side=tk.LEFT, padx=5)
|
||||
|
||||
# QMT路径特殊处理 - 使用文件浏览器
|
||||
qmt_path_frame = ttk.LabelFrame(advanced_frame, text="软件路径", padding=15)
|
||||
qmt_path_frame.pack(fill=tk.X, padx=20, pady=10)
|
||||
|
||||
qmt_row = ttk.Frame(qmt_path_frame)
|
||||
qmt_row.pack(fill=tk.X, pady=5)
|
||||
|
||||
ttk.Label(qmt_row, text="QMT路径:", width=15, font=('Arial', 10)).pack(side=tk.LEFT)
|
||||
|
||||
qmt_entry = ttk.Entry(qmt_row, width=30, font=('Arial', 10))
|
||||
qmt_entry.insert(0, config.get('config', 'miniQMTPath'))
|
||||
qmt_entry.pack(side=tk.LEFT, padx=5)
|
||||
entries['miniQMTPath'] = qmt_entry
|
||||
|
||||
def browse_qmt_path():
|
||||
"""打开文件夹浏览器选择QMT路径"""
|
||||
initial_dir = qmt_entry.get() if qmt_entry.get() else "/"
|
||||
folder_path = filedialog.askdirectory(
|
||||
title="选择miniQMT安装路径",
|
||||
initialdir=initial_dir
|
||||
)
|
||||
if folder_path:
|
||||
qmt_entry.delete(0, tk.END)
|
||||
qmt_entry.insert(0, folder_path)
|
||||
|
||||
ttk.Button(qmt_row, text="📁 浏览...", command=browse_qmt_path, width=10).pack(side=tk.LEFT, padx=5)
|
||||
ttk.Label(qmt_row, text="miniQMT软件安装路径", font=('Arial', 9), foreground='gray').pack(side=tk.LEFT, padx=5)
|
||||
|
||||
# 定义保存和取消按钮的功能(button_frame已在上方创建)
|
||||
def save_settings():
|
||||
def save_config():
|
||||
"""保存配置"""
|
||||
# try:
|
||||
# # 计算网格价格序列
|
||||
# grid_prices = calculate_grid_prices()
|
||||
# if not grid_prices:
|
||||
# messagebox.showerror("错误", "网格价格参数有误,请检查输入!")
|
||||
# return
|
||||
try:
|
||||
# 获取输入值
|
||||
grid_start_price = float(base_price_entry.get())
|
||||
grid_size = float(grid_size_entry.get())
|
||||
grid_volume = int(grid_volume_entry.get())
|
||||
grid_upper_count = int(upper_count_entry.get())
|
||||
grid_lower_count = int(lower_count_entry.get())
|
||||
|
||||
# grid_price_str = ",".join([str(p) for p in grid_prices])
|
||||
# 更新target对象(使用setattr来正确设置Peewee字段的值)
|
||||
setattr(target, 'grid_start_price', grid_start_price)
|
||||
setattr(target, 'grid_size', grid_size)
|
||||
setattr(target, 'grid_volume', grid_volume)
|
||||
setattr(target, 'grid_upper_count', grid_upper_count)
|
||||
setattr(target, 'grid_lower_count', grid_lower_count)
|
||||
|
||||
# # 更新配置对象
|
||||
# config.set('config', 'miniQMTPath', entries['miniQMTPath'].get())
|
||||
# config.set('config', 'grid_price', grid_price_str)
|
||||
# config.set('config', 'grid_volume', entries['grid_volume'].get())
|
||||
# config.set('config', 'account_no', entries['account_no'].get())
|
||||
# 保存到数据库
|
||||
target.save()
|
||||
|
||||
# # 写入配置文件
|
||||
# config_path = config.get_config_path()
|
||||
# with open(config_path, 'w', encoding='utf-8') as configfile:
|
||||
# config.write(configfile)
|
||||
# 关闭窗口
|
||||
config_window.destroy()
|
||||
|
||||
# # 重新加载配置到内存中
|
||||
# config.initConfig()
|
||||
# 添加日志
|
||||
PrintLog(LogLevel.INFO, f"网格配置已保存: {target.stock_code} - {target.stock_name}")
|
||||
messagebox.showinfo("成功", "网格配置已保存!")
|
||||
|
||||
# messagebox.showinfo("成功", f"配置已保存!\n网格价格序列: {grid_price_str}\n部分配置可能需要重启程序后生效。")
|
||||
# self.add_log(LogLevel.INFO, f"系统配置已更新 - 网格数量: {len(grid_prices)}")
|
||||
# settings_window.destroy()
|
||||
|
||||
# except Exception as e:
|
||||
# messagebox.showerror("错误", f"保存配置失败:{str(e)}")
|
||||
# self.add_log(LogLevel.ERROR, f"保存配置失败: {str(e)}")
|
||||
pass
|
||||
except ValueError:
|
||||
messagebox.showerror("错误", "输入参数有误,请检查!")
|
||||
except Exception as e:
|
||||
messagebox.showerror("错误", f"保存配置失败:{str(e)}")
|
||||
PrintLog(LogLevel.ERROR, f"保存网格配置失败: {str(e)}")
|
||||
|
||||
def cancel_settings():
|
||||
"""取消设置"""
|
||||
# settings_window.destroy()
|
||||
pass
|
||||
|
||||
# 在button_frame中添加按钮
|
||||
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_settings(self):
|
||||
"""网格修正功能"""
|
||||
target = self.get_selected_target()
|
||||
if not target:
|
||||
return
|
||||
|
||||
# 创建网格修正窗口
|
||||
self.create_grid_correction_window(target)
|
||||
# 保存和取消按钮
|
||||
ttk.Button(button_frame, text="保存", command=save_config).pack(side=tk.RIGHT, padx=5)
|
||||
ttk.Button(button_frame, text="取消", command=config_window.destroy).pack(side=tk.RIGHT, padx=5)
|
||||
|
||||
def create_grid_correction_window(self, target: SFGridTradeTarget):
|
||||
"""创建网格修正窗口"""
|
||||
@@ -1099,13 +1071,14 @@ class TradeTargetUI(ttk.Frame):
|
||||
self.update_position_status(current_position, required_position, position_status_label)
|
||||
|
||||
|
||||
def onAddTradeTarget(self, stock_code: str):
|
||||
def addTradeTarget(self, stock_code: str, gridIndex: int = 1):
|
||||
"""处理添加交易标的事件"""
|
||||
try:
|
||||
stock_name = qmtv.getInstrumentName(stock_code)
|
||||
if not stock_name:
|
||||
PrintLog(LogLevel.ERROR, f'无法获取股票代码 {stock_code} 的名称,请检查代码是否正确')
|
||||
return
|
||||
PrintLog(LogLevel.DEBUG, f'添加交易标的: {stock_code} {stock_name}')
|
||||
|
||||
# 检查是否已存在该标的
|
||||
existing_target = SFGridTradeTarget.get_or_none(SFGridTradeTarget.stock_code == stock_code)
|
||||
@@ -1120,7 +1093,7 @@ class TradeTargetUI(ttk.Frame):
|
||||
stock_code=stock_code,
|
||||
market_price=0.0,
|
||||
current_position=pos,
|
||||
grid_index=0,
|
||||
grid_index=gridIndex,
|
||||
last_trade_price=0.0,
|
||||
plan_buy_price=0.0,
|
||||
plan_sell_price=0.0,
|
||||
@@ -1148,16 +1121,3 @@ 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)}")
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user