独立配置
This commit is contained in:
@@ -3,15 +3,10 @@ import configparser
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
# miniQMTPath = r'D:\\Programs\\DTQMT_MN\\userdata_mini' # miniQMT软件的安装路径
|
||||
miniQMTPath = r'D:\\Programs\\DTQMT\\userdata_mini' # miniQMT软件的安装路径
|
||||
# miniQMTPath = ''
|
||||
# grid_price = [11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1] # 网格价格设置,从高到低
|
||||
grid_price:List[float] = [] # 网格价格设置,从高到低
|
||||
grid_volume:int = 100 # 每个网格的交易手数
|
||||
account_no:str = '99082560'
|
||||
console_log = True
|
||||
# account_no:str = '89009170' # 交易账号
|
||||
|
||||
def get_config_path() -> Path:
|
||||
"""获取配置文件的正确路径(兼容开发环境和打包后的可执行文件)"""
|
||||
@@ -31,8 +26,6 @@ def create_default_config():
|
||||
config = configparser.ConfigParser()
|
||||
config['config'] = {
|
||||
'miniQMTPath': r'D:/Programs/QMT/userdata_mini',
|
||||
'grid_price': '11.0,10.0,9.0,8.0,7.0,6.0,5.0,4.0,3.0,2.0,1.0,0.0',
|
||||
'grid_volume': '100',
|
||||
'account_no': '00000000'
|
||||
}
|
||||
config_path = get_config_path()
|
||||
@@ -53,7 +46,4 @@ def initConfig():
|
||||
config = configparser.ConfigParser()
|
||||
config.read(config_path, encoding='utf-8')
|
||||
miniQMTPath = config.get('config','miniQMTPath')
|
||||
str_list = config.get('config','grid_price').split(',')
|
||||
grid_price = [float(item) for item in str_list]
|
||||
grid_volume = config.getint('config','grid_volume')
|
||||
account_no = config.get('config','account_no')
|
||||
|
||||
+2
-10
@@ -1,8 +1,7 @@
|
||||
import tkinter as tk
|
||||
from tkinter import ttk
|
||||
from core.logger import LogLevel, PrintLog, LogData
|
||||
from core.logger import LogLevel, PrintLog
|
||||
from core.sfgrid.sfgrid_ui import TradeTargetUI
|
||||
from core.eventbus import event_bus, EventPrintLog
|
||||
|
||||
|
||||
class MainWindow:
|
||||
@@ -17,13 +16,10 @@ class MainWindow:
|
||||
self.strategy_frames = {}
|
||||
# 日志面板可见性标志
|
||||
self.log_visible = False
|
||||
|
||||
# 创建界面
|
||||
print(f'创建界面')
|
||||
self.create_ui()
|
||||
|
||||
# 订阅日志事件
|
||||
event_bus.subscribe(EventPrintLog, self.on_log_event)
|
||||
|
||||
|
||||
def create_ui(self):
|
||||
"""创建UI界面"""
|
||||
@@ -212,10 +208,6 @@ class MainWindow:
|
||||
if result:
|
||||
self.root.destroy()
|
||||
|
||||
def on_log_event(self, log_data: LogData):
|
||||
"""处理日志事件"""
|
||||
self.add_log(log_data.level, log_data.message)
|
||||
|
||||
def run(self):
|
||||
"""运行程序"""
|
||||
self.root.mainloop()
|
||||
|
||||
@@ -131,6 +131,8 @@ class QmtV(XtQuantTraderCallback):
|
||||
def startMarketDataSubscription(self):
|
||||
self.subscriptionId = xtdata.subscribe_whole_quote(['SH', 'SZ'], self.onDataUpdate)
|
||||
|
||||
PrintLog(LogLevel.INFO, f'- [市场数据订阅成功-{self.subscriptionId}]')
|
||||
|
||||
def stopMarketDataSubscription(self):
|
||||
PrintLog(LogLevel.INFO, '- 停止市场数据订阅')
|
||||
|
||||
|
||||
@@ -4,8 +4,6 @@ ActionEventAddTradeTarget = "add_trade_target"
|
||||
ResultEventTradeTargetAdded = "trade_target_added"
|
||||
ActionEventDeleteTradeTarget = "delete_trade_target"
|
||||
ResultEventTradeTargetDeleted = "trade_target_deleted"
|
||||
# 网格修正事件
|
||||
ActionEventGridFix = "grid_fix"
|
||||
|
||||
# 定义事件处理函数
|
||||
ActionEventEnableTrade = "enable_trade"
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
GridTypePercentage = "Percentage"
|
||||
GridTypeFixed = "PriceBreak"
|
||||
@@ -19,8 +19,30 @@ class SFGridTradeTarget(BaseModel):
|
||||
status = IntegerField(default=0) # 0表示新标的,1表示已建初始仓,正常交易中
|
||||
enabled = BooleanField(default=False) # 是否启动交易线程
|
||||
|
||||
grid_start_price = FloatField(default=10.0) # 基线价格
|
||||
grid_size = FloatField(default=0.1) # 网格价位差
|
||||
grid_volume = IntegerField(default=100) # 网格交易量
|
||||
grid_upper_count = IntegerField(default=1) # 基线价格上方网格数
|
||||
grid_lower_count = IntegerField(default=10) # 基线价格下方网格数
|
||||
|
||||
def targetName(self):
|
||||
return f'{self.stock_name}[{self.stock_code}]'
|
||||
|
||||
def getPriceGrid(self) -> list:
|
||||
self.priceGrid: list = []
|
||||
# 网格大小,数量
|
||||
if self.priceGrid is None or len(self.priceGrid) == 0:
|
||||
for i in range(self.grid_upper_count): # type: ignore
|
||||
upperPrice = self.grid_start_price + (self.grid_upper_count - i) * self.grid_size
|
||||
self.priceGrid.append(upperPrice)
|
||||
|
||||
self.priceGrid.append(self.grid_start_price)
|
||||
|
||||
for i in range(self.grid_lower_count): # type: ignore 5
|
||||
lowerPrice = self.grid_start_price - (i + 1) * self.grid_size
|
||||
self.priceGrid.append(lowerPrice)
|
||||
|
||||
return self.priceGrid
|
||||
|
||||
|
||||
db.create_tables([SFGridTradeTarget])
|
||||
@@ -40,7 +40,7 @@ class SFGridStrategy:
|
||||
else: # 已建仓
|
||||
# 交易阶段,检查仓位,检查现有订单
|
||||
print(f" |- 标的{self.tradeTarget.targetName()}已有仓位或非初始状态 无需建初始仓 当前仓位: {self.tradeTarget.current_position} 状态: {self.tradeTarget.status}")
|
||||
minRequirePosition:int = config.grid_volume * int(self.tradeTarget.grid_index) # type: ignore
|
||||
minRequirePosition:int = self.tradeTarget.grid_volume * int(self.tradeTarget.grid_index) # type: ignore
|
||||
if minRequirePosition <= int(self.tradeTarget.current_position): # type: ignore
|
||||
print(f' |- 仓位检查: 持仓需求充足, (gridVolume*gridIndex)={minRequirePosition}, 当前持仓:{self.tradeTarget.current_position}')
|
||||
else:
|
||||
@@ -74,16 +74,16 @@ class SFGridStrategy:
|
||||
index: int = self.tradeTarget.grid_index # pyright: ignore[reportAssignmentType]
|
||||
orderRemark= ""
|
||||
|
||||
gridBasePrice = -1 if index>=len(config.grid_price) or index < 0 else config.grid_price[int(index)] # pyright: ignore[reportArgumentType]
|
||||
gridBasePrice = -1 if index>=len(inTradeTarget.getPriceGrid()) or index < 0 else inTradeTarget.getPriceGrid()[int(index)] # pyright: ignore[reportArgumentType]
|
||||
|
||||
if self.tradeTarget.enabled and self.tradeTarget.status == 0 and lastPrice <= config.grid_price[1]: # 已启用,未建仓,建仓
|
||||
orderPrice = config.grid_price[index]
|
||||
orderPrice = inTradeTarget.getPriceGrid()[index]
|
||||
orderType = xtconstant.STOCK_BUY
|
||||
orderRemark = OrderTypeInit
|
||||
|
||||
if self.tradeTarget.enabled and self.tradeTarget.status == 1: # 已启用,已建仓,网格单
|
||||
lowPrice = -1 if index+1>=len(config.grid_price) else config.grid_price[int(index) + 1] # pyright: ignore[reportArgumentType]
|
||||
highPrice = config.grid_price[index - 1]
|
||||
lowPrice = -1 if index+1>=len(inTradeTarget.getPriceGrid()) else inTradeTarget.getPriceGrid()[int(index) + 1] # pyright: ignore[reportArgumentType]
|
||||
highPrice = inTradeTarget.getPriceGrid()[index - 1]
|
||||
|
||||
if lastPrice <= lowPrice: # 下下方多单
|
||||
orderPrice = lowPrice
|
||||
@@ -196,11 +196,11 @@ class SFGridStrategy:
|
||||
buyIdx: int = self.tradeTarget.grid_index + 1 # pyright: ignore[reportAssignmentType]
|
||||
sellIdx: int = self.tradeTarget.grid_index - 1
|
||||
if self.tradeTarget.grid_index > 0: # 可以下空单
|
||||
self.tradeTarget.plan_sell_price = float(config.grid_price[sellIdx]) # pyright: ignore[reportAttributeAccessIssue]
|
||||
self.tradeTarget.plan_sell_price = float(self.tradeTarget.getPriceGrid()[sellIdx]) # pyright: ignore[reportAttributeAccessIssue]
|
||||
else:
|
||||
self.tradeTarget.plan_sell_price = -1.0 # type: ignore
|
||||
if self.tradeTarget.grid_index < len(config.grid_price) - 1:
|
||||
self.tradeTarget.plan_buy_price = float(config.grid_price[buyIdx]) # pyright: ignore[reportAttributeAccessIssue]
|
||||
if self.tradeTarget.grid_index < len(self.tradeTarget.getPriceGrid()) - 1:
|
||||
self.tradeTarget.plan_buy_price = float(self.tradeTarget.getPriceGrid()[buyIdx]) # pyright: ignore[reportAttributeAccessIssue]
|
||||
else:
|
||||
self.tradeTarget.plan_buy_price = -1.0 # pyright: ignore[reportAttributeAccessIssue]
|
||||
else:
|
||||
|
||||
+14
-15
@@ -8,7 +8,7 @@ import time
|
||||
from core import constants
|
||||
import core.eventbus as eBus
|
||||
from core.logger import LogLevel, PrintLog
|
||||
from core.sfgrid.bus_events import ActionEventAddTradeTarget, ActionEventDeleteTradeTarget, ActionEventDisableTrade, ActionEventEnableTrade, ActionEventGridFix, EventTradeTargetUpdate, ResultEventTradeTargetAdded, ResultEventTradeTargetDeleted
|
||||
from core.sfgrid.bus_events import ActionEventAddTradeTarget
|
||||
from core.sfgrid.model import SFGridTradeTarget
|
||||
import configparser
|
||||
import config
|
||||
@@ -48,6 +48,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}')
|
||||
tradeTarget.market_price = lastPrice # type: ignore
|
||||
self.updateTradeTarget(tradeTarget)
|
||||
stock_controller: SFGridStrategy = self.strategy_ctrl[id]
|
||||
@@ -85,7 +86,7 @@ class TradeTargetUI(ttk.Frame):
|
||||
|
||||
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} 基准价格 {config.grid_price[tradeTarget.grid_index]} 状态: {status} 启用交易线程: {'自动交易中' if tradeTarget.enabled else '交易已停止'}') # type: ignore
|
||||
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()
|
||||
@@ -143,10 +144,10 @@ 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)
|
||||
ttk.Button(toolbar_frame, text="🛠 网格修正",
|
||||
command=self.grid_correction, width=12).pack(side=tk.LEFT, padx=2)
|
||||
|
||||
# 添加抽屉按钮到工具栏最右侧
|
||||
self.toggle_market_monitor_btn = ttk.Button(toolbar_frame, text="◀▶",
|
||||
@@ -246,7 +247,7 @@ class TradeTargetUI(ttk.Frame):
|
||||
column_configs = {
|
||||
"时间": (50, tk.CENTER),
|
||||
"股票名称": (80, tk.CENTER),
|
||||
"最新价格": (80, tk.CENTER)
|
||||
"最新价格": (50, tk.CENTER)
|
||||
}
|
||||
|
||||
for col in columns:
|
||||
@@ -303,7 +304,8 @@ class TradeTargetUI(ttk.Frame):
|
||||
values = [
|
||||
time_str,
|
||||
data['stock_name']+f"{stock_code}",
|
||||
f"{data['last_price']:.3f}"
|
||||
f"{data['last_price']:.3f}",
|
||||
stock_code
|
||||
]
|
||||
self.market_table.insert('', tk.END, values=values)
|
||||
|
||||
@@ -320,9 +322,10 @@ class TradeTargetUI(ttk.Frame):
|
||||
if selected:
|
||||
item = selected[0]
|
||||
values = self.market_table.item(item)['values']
|
||||
stock_code = values[1]
|
||||
stock_name = values[2]
|
||||
last_price = values[3]
|
||||
print(values)
|
||||
stock_name = values[1]
|
||||
last_price = values[2]
|
||||
stock_code = values[3]
|
||||
|
||||
# 检查是否已在交易池中
|
||||
is_in_trade_pool = any(target.stock_code == stock_code for target in self.tradeTargetData.values())
|
||||
@@ -501,7 +504,7 @@ class TradeTargetUI(ttk.Frame):
|
||||
|
||||
del self.tradeTargetData[id]
|
||||
del self.strategy_ctrl[id]
|
||||
del self.stockCodeIdMap[str(target.stock_code)]
|
||||
del self.stockCodeIdMap[target.stock_code] # type: ignore
|
||||
# 添加日志
|
||||
PrintLog(LogLevel.INFO, f"交易标的已删除,ID: {id} {target.targetName()}")
|
||||
except Exception as e:
|
||||
@@ -898,7 +901,7 @@ class TradeTargetUI(ttk.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_correction(self):
|
||||
def grid_settings(self):
|
||||
"""网格修正功能"""
|
||||
target = self.get_selected_target()
|
||||
if not target:
|
||||
@@ -1061,10 +1064,6 @@ class TradeTargetUI(ttk.Frame):
|
||||
if not result:
|
||||
return
|
||||
|
||||
# 发布网格修正事件,传递GridFixData对象
|
||||
grid_fix_data = GridFixData(new_grid_index, target)
|
||||
eBus.event_bus.publish(ActionEventGridFix, grid_fix_data)
|
||||
|
||||
# 关闭窗口
|
||||
window.destroy()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user