update
This commit is contained in:
+1
-1
@@ -36,7 +36,7 @@ class MainWindow:
|
|||||||
|
|
||||||
# 创建Tab按钮(垂直排列,文字垂直显示)
|
# 创建Tab按钮(垂直排列,文字垂直显示)
|
||||||
self.tab_buttons = []
|
self.tab_buttons = []
|
||||||
strategy_names = ["三疯\n网格", "通用\n网格", "涨停\n分析"]
|
strategy_names = ["蒙派\n策略", "涨停\n分析"]
|
||||||
|
|
||||||
for idx, name in enumerate(strategy_names):
|
for idx, name in enumerate(strategy_names):
|
||||||
btn = ttk.Button(
|
btn = ttk.Button(
|
||||||
|
|||||||
@@ -56,16 +56,14 @@ class SFGridStrategy:
|
|||||||
return bool(self.tradeTarget.enabled) # 修复返回类型问题
|
return bool(self.tradeTarget.enabled) # 修复返回类型问题
|
||||||
|
|
||||||
def onDataUpdate(self, inTradeTarget:model.SFGridTradeTarget):
|
def onDataUpdate(self, inTradeTarget:model.SFGridTradeTarget):
|
||||||
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - START')
|
|
||||||
|
|
||||||
if not is_trading_time():
|
if not is_trading_time():
|
||||||
print(f"|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 非交易时间,不进行自动交易")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self.tradeTarget.enabled: # 未建仓,自动交易暂停
|
if not self.tradeTarget.enabled: # 未建仓,自动交易暂停
|
||||||
print(f"|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 未建仓或交易监控暂停,不进行自动交易")
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - START')
|
||||||
self.dataUpdateLock.acquire()
|
self.dataUpdateLock.acquire()
|
||||||
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - LOCKED')
|
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - LOCKED')
|
||||||
|
|
||||||
|
|||||||
+83
-38
@@ -32,6 +32,9 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
# 市场监控数据
|
# 市场监控数据
|
||||||
self.marketData: dict[str, Any] = {} # 存储市场数据 {stock_code: {stock_name, last_price, time}}
|
self.marketData: dict[str, Any] = {} # 存储市场数据 {stock_code: {stock_name, last_price, time}}
|
||||||
|
|
||||||
|
# 市场监控窗口显示状态
|
||||||
|
self.market_monitor_visible = True
|
||||||
|
|
||||||
# 创建界面
|
# 创建界面
|
||||||
self.create_ui()
|
self.create_ui()
|
||||||
|
|
||||||
@@ -40,20 +43,18 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
def onMarketDataUpdated(self, data):
|
def onMarketDataUpdated(self, data):
|
||||||
# 收集所有市场数据用于市场监控
|
# 收集所有市场数据用于市场监控
|
||||||
for stock_code, tickData in data.items():
|
for stock_code, tickData in data.items():
|
||||||
id = self.stockCodeIdMap.get(stock_code)
|
if stock_code in self.stockCodeIdMap:
|
||||||
if id is not None and stock_code in self.tradeTargetData:
|
id:int = self.stockCodeIdMap[stock_code]
|
||||||
tradeTarget = self.tradeTargetData[id]
|
tradeTarget = self.tradeTargetData[id]
|
||||||
PrintLog(LogLevel.INFO, f' [市价更新 序号-{id}] {stock_code} - {tickData}')
|
|
||||||
|
|
||||||
lastPrice = float("{:.3f}".format(tickData['lastPrice']))
|
lastPrice = float("{:.3f}".format(tickData['lastPrice']))
|
||||||
tradeTarget.market_price = lastPrice # type: ignore
|
tradeTarget.market_price = lastPrice # type: ignore
|
||||||
|
self.updateTradeTarget(tradeTarget)
|
||||||
stock_controller: SFGridStrategy = self.strategy_ctrl[id]
|
stock_controller: SFGridStrategy = self.strategy_ctrl[id]
|
||||||
stock_controller.onDataUpdate(tradeTarget)
|
stock_controller.onDataUpdate(tradeTarget)
|
||||||
else:
|
else:
|
||||||
# 非目标交易,发布市场数据更新事件用于市场监控
|
# 非目标交易,发布市场数据更新事件用于市场监控
|
||||||
lastPrice = tickData['lastPrice']
|
lastPrice = tickData['lastPrice']
|
||||||
if lastPrice == 10 or stock_code in self.listening_stock:
|
if lastPrice == 10 or stock_code in self.listening_stock:
|
||||||
PrintLog(LogLevel.INFO, f' [市价更新 序号-X] {stock_code} - {lastPrice}')
|
|
||||||
# 发布市场数据更新事件用于市场监控
|
# 发布市场数据更新事件用于市场监控
|
||||||
market_target = SFGridTradeTarget()
|
market_target = SFGridTradeTarget()
|
||||||
market_target.stock_code = stock_code
|
market_target.stock_code = stock_code
|
||||||
@@ -61,7 +62,13 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
market_target.market_price = lastPrice # type: ignore
|
market_target.market_price = lastPrice # type: ignore
|
||||||
if stock_code not in self.listening_stock:
|
if stock_code not in self.listening_stock:
|
||||||
self.listening_stock.append(stock_code)
|
self.listening_stock.append(stock_code)
|
||||||
|
# 更新市场监控数据用于UI显示
|
||||||
|
current_time = datetime.now().strftime("%H:%M:%S")
|
||||||
|
self.marketData[str(stock_code)] = {
|
||||||
|
'stock_name': qmtv.getInstrumentName(stock_code),
|
||||||
|
'last_price': tickData['lastPrice'],
|
||||||
|
'time': current_time
|
||||||
|
}
|
||||||
|
|
||||||
def refresh_targets(self):
|
def refresh_targets(self):
|
||||||
# 更新标的池
|
# 更新标的池
|
||||||
@@ -84,7 +91,6 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
PrintLog(LogLevel.INFO, f' |- 同步[{tradeTarget.stock_code}-{tradeTarget.stock_name}]持仓信息[{'成功' if result == 1 else '失败'}]')
|
PrintLog(LogLevel.INFO, f' |- 同步[{tradeTarget.stock_code}-{tradeTarget.stock_name}]持仓信息[{'成功' if result == 1 else '失败'}]')
|
||||||
stockTradeController = SFGridStrategy(tradeTarget) # type: ignore
|
stockTradeController = SFGridStrategy(tradeTarget) # type: ignore
|
||||||
self.strategy_ctrl[id] = stockTradeController # pyright: ignore[reportArgumentType]
|
self.strategy_ctrl[id] = stockTradeController # pyright: ignore[reportArgumentType]
|
||||||
# eBus.event_bus.publish(eBus.EventTradeTargetUpdate, tradeTarget)
|
|
||||||
self.updateTradeTarget(tradeTarget)
|
self.updateTradeTarget(tradeTarget)
|
||||||
|
|
||||||
PrintLog(LogLevel.INFO, f'- [成功]交易标的信息初始化, 共 {len(self.tradeTargetData)} 个标的')
|
PrintLog(LogLevel.INFO, f'- [成功]交易标的信息初始化, 共 {len(self.tradeTargetData)} 个标的')
|
||||||
@@ -99,9 +105,9 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
"""刷新循环"""
|
"""刷新循环"""
|
||||||
while self.refresh_thread_running:
|
while self.refresh_thread_running:
|
||||||
# 在主线程中更新UI
|
# 在主线程中更新UI
|
||||||
PrintLog(LogLevel.INFO, "刷新UI")
|
|
||||||
self.after(0, self.refresh_table)
|
self.after(0, self.refresh_table)
|
||||||
time.sleep(0.5) # 每0.5秒刷新一次
|
self.after(0, self.populate_market_table)
|
||||||
|
time.sleep(0.2) # 每0.5秒刷新一次
|
||||||
|
|
||||||
def stop_refresh_thread(self):
|
def stop_refresh_thread(self):
|
||||||
"""停止刷新线程"""
|
"""停止刷新线程"""
|
||||||
@@ -114,7 +120,6 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
def onTradeDisabled(self, target:SFGridTradeTarget):
|
def onTradeDisabled(self, target:SFGridTradeTarget):
|
||||||
PrintLog(LogLevel.INFO, f"交易禁用: {target.stock_code} - {target.stock_name}")
|
PrintLog(LogLevel.INFO, f"交易禁用: {target.stock_code} - {target.stock_name}")
|
||||||
|
|
||||||
|
|
||||||
def updateTradeTarget(self, target: SFGridTradeTarget):
|
def updateTradeTarget(self, target: SFGridTradeTarget):
|
||||||
# 更新或添加数据到本地缓存
|
# 更新或添加数据到本地缓存
|
||||||
self.tradeTargetData[target.get_id()] = target
|
self.tradeTargetData[target.get_id()] = target
|
||||||
@@ -142,8 +147,10 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
ttk.Button(toolbar_frame, text="🛠 网格修正",
|
ttk.Button(toolbar_frame, text="🛠 网格修正",
|
||||||
command=self.grid_correction, width=12).pack(side=tk.LEFT, padx=2)
|
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)
|
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)
|
||||||
|
|
||||||
# 表格区域
|
# 表格区域
|
||||||
self.create_tables_area(main_frame)
|
self.create_tables_area(main_frame)
|
||||||
@@ -163,7 +170,6 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
PrintLog(LogLevel.INFO, "UI刷新线程已停止")
|
PrintLog(LogLevel.INFO, "UI刷新线程已停止")
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def create_tables_area(self, parent):
|
def create_tables_area(self, parent):
|
||||||
"""创建表格区域"""
|
"""创建表格区域"""
|
||||||
# 创建主表格框架(水平排列)
|
# 创建主表格框架(水平排列)
|
||||||
@@ -178,17 +184,17 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
self.create_trade_target_table(trade_frame)
|
self.create_trade_target_table(trade_frame)
|
||||||
|
|
||||||
# 右侧市场监控区域
|
# 右侧市场监控区域
|
||||||
market_frame = ttk.LabelFrame(tables_frame, text="市场监控", padding=10)
|
self.market_frame = ttk.LabelFrame(tables_frame, text="市场监控", padding=10)
|
||||||
market_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(5, 0))
|
self.market_frame.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True, padx=(5, 0))
|
||||||
|
|
||||||
# 创建市场监控表格
|
# 创建市场监控表格
|
||||||
self.create_market_monitor_table(market_frame)
|
self.create_market_monitor_table(self.market_frame)
|
||||||
|
|
||||||
def create_trade_target_table(self, parent):
|
def create_trade_target_table(self, parent):
|
||||||
"""创建交易标的表格"""
|
"""创建交易标的表格"""
|
||||||
|
|
||||||
columns = ("ID",
|
columns = ("ID",
|
||||||
"股票代码", "股票名称", "市场价", "持仓数量", "网格索引",
|
"股票代码", "股票名称", "市场价", "持仓数量",
|
||||||
"最新成交价", "计划买入价", "计划卖出价", "当前订单价", "当前订单号", "当前订单类型",
|
"最新成交价", "计划买入价", "计划卖出价", "当前订单价", "当前订单号", "当前订单类型",
|
||||||
"交易状态"
|
"交易状态"
|
||||||
)
|
)
|
||||||
@@ -199,17 +205,16 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
column_configs = {
|
column_configs = {
|
||||||
"ID": (50, tk.CENTER),
|
"ID": (50, tk.CENTER),
|
||||||
"股票代码": (90, tk.CENTER),
|
"股票代码": (90, tk.CENTER),
|
||||||
"股票名称": (80, tk.CENTER),
|
"股票名称": (80, tk.E),
|
||||||
"市场价": (70, tk.CENTER),
|
"市场价": (70, tk.E),
|
||||||
"持仓数量": (80, tk.CENTER),
|
"持仓数量": (80, tk.E),
|
||||||
"网格索引": (80, tk.CENTER),
|
"最新成交价": (90, tk.E),
|
||||||
"最新成交价": (90, tk.CENTER),
|
"计划买入价": (90, tk.E),
|
||||||
"计划买入价": (90, tk.CENTER),
|
"计划卖出价": (90, tk.E),
|
||||||
"计划卖出价": (90, tk.CENTER),
|
"当前订单价": (90, tk.E),
|
||||||
"当前订单价": (90, tk.CENTER),
|
"当前订单号": (90, tk.E),
|
||||||
"当前订单号": (90, tk.CENTER),
|
"当前订单类型": (90, tk.E),
|
||||||
"当前订单类型": (90, tk.CENTER),
|
"交易状态": (80, tk.E)
|
||||||
"交易状态": (80, tk.CENTER)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for col in columns:
|
for col in columns:
|
||||||
@@ -232,16 +237,15 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
|
|
||||||
def create_market_monitor_table(self, parent):
|
def create_market_monitor_table(self, parent):
|
||||||
"""创建市场监控表格"""
|
"""创建市场监控表格"""
|
||||||
columns = ("时间", "股票代码", "股票名称", "最新价格")
|
columns = ("时间", "股票名称", "最新价格")
|
||||||
|
|
||||||
self.market_table = ttk.Treeview(parent, columns=columns, show='headings', height=15)
|
self.market_table = ttk.Treeview(parent, columns=columns, show='headings', height=15)
|
||||||
|
|
||||||
# 列配置
|
# 列配置
|
||||||
column_configs = {
|
column_configs = {
|
||||||
"时间": (120, "center"),
|
"时间": (50, tk.CENTER),
|
||||||
"股票代码": (90, "center"),
|
"股票名称": (80, tk.CENTER),
|
||||||
"股票名称": (80, "center"),
|
"最新价格": (80, tk.CENTER)
|
||||||
"最新价格": (80, "center")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for col in columns:
|
for col in columns:
|
||||||
@@ -264,7 +268,14 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
|
|
||||||
def populate_market_table(self):
|
def populate_market_table(self):
|
||||||
"""填充市场监控表格数据"""
|
"""填充市场监控表格数据"""
|
||||||
pass
|
# 保存当前选中的项
|
||||||
|
selected_items = self.market_table.selection()
|
||||||
|
selected_values = []
|
||||||
|
for item in selected_items:
|
||||||
|
values = self.market_table.item(item)['values']
|
||||||
|
if values:
|
||||||
|
selected_values.append(values[1]) # 保存股票代码
|
||||||
|
|
||||||
# 清空现有数据
|
# 清空现有数据
|
||||||
for item in self.market_table.get_children():
|
for item in self.market_table.get_children():
|
||||||
self.market_table.delete(item)
|
self.market_table.delete(item)
|
||||||
@@ -272,14 +283,36 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
# 填充市场数据
|
# 填充市场数据
|
||||||
tmp = self.marketData.copy()
|
tmp = self.marketData.copy()
|
||||||
for stock_code, data in tmp.items():
|
for stock_code, data in tmp.items():
|
||||||
|
# 处理时间格式,仅显示 hh:mm:ss
|
||||||
|
time_str = data['time']
|
||||||
|
# 如果时间字符串包含空格,说明包含日期和时间,只取时间部分
|
||||||
|
if ' ' in time_str:
|
||||||
|
time_str = time_str.split(' ')[1]
|
||||||
|
|
||||||
|
# 确保时间格式为 hh:mm:ss,如果只有 hh:mm 则补充 :00
|
||||||
|
if ':' in time_str:
|
||||||
|
time_components = time_str.split(':')
|
||||||
|
if len(time_components) == 2:
|
||||||
|
# 只有小时和分钟,补充秒
|
||||||
|
time_str = f"{time_components[0]}:{time_components[1]}:00"
|
||||||
|
elif len(time_components) >= 3:
|
||||||
|
# 有小时、分钟和秒,只取前三个部分
|
||||||
|
time_str = f"{time_components[0]}:{time_components[1]}:{time_components[2]}"
|
||||||
|
|
||||||
values = [
|
values = [
|
||||||
data['time'],
|
time_str,
|
||||||
stock_code,
|
data['stock_name']+f"{stock_code}",
|
||||||
data['stock_name'],
|
|
||||||
f"{data['last_price']:.3f}"
|
f"{data['last_price']:.3f}"
|
||||||
]
|
]
|
||||||
self.market_table.insert('', tk.END, values=values)
|
self.market_table.insert('', tk.END, values=values)
|
||||||
|
|
||||||
|
# 恢复之前选中的项
|
||||||
|
if selected_values:
|
||||||
|
for item in self.market_table.get_children():
|
||||||
|
values = self.market_table.item(item)['values']
|
||||||
|
if values and values[1] in selected_values: # 比较股票代码
|
||||||
|
self.market_table.selection_add(item)
|
||||||
|
|
||||||
def on_market_table_double_click(self, event):
|
def on_market_table_double_click(self, event):
|
||||||
"""市场监控表格双击事件"""
|
"""市场监控表格双击事件"""
|
||||||
selected = self.market_table.selection()
|
selected = self.market_table.selection()
|
||||||
@@ -324,7 +357,6 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
target.stock_name,
|
target.stock_name,
|
||||||
"-" if target.market_price is None else f"{target.market_price:.3f}",
|
"-" if target.market_price is None else f"{target.market_price:.3f}",
|
||||||
target.current_position,
|
target.current_position,
|
||||||
target.grid_index,
|
|
||||||
'-' if target.last_trade_price is None else f"{target.last_trade_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_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.plan_sell_price is None else f"{target.plan_sell_price:.3f}",
|
||||||
@@ -1106,3 +1138,16 @@ class TradeTargetUI(ttk.Frame):
|
|||||||
PrintLog(LogLevel.INFO, f"网格修正已应用: {target.stock_code} - {target.stock_name}, 网格索引: {grid_index}")
|
PrintLog(LogLevel.INFO, f"网格修正已应用: {target.stock_code} - {target.stock_name}, 网格索引: {grid_index}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
PrintLog(LogLevel.ERROR, f"网格修正更新失败: {str(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