独立配置
This commit is contained in:
@@ -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:
|
||||
|
||||
+15
-16
@@ -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
|
||||
@@ -47,7 +47,8 @@ class TradeTargetUI(ttk.Frame):
|
||||
if stock_code in self.stockCodeIdMap:
|
||||
id:int = self.stockCodeIdMap[stock_code]
|
||||
tradeTarget = self.tradeTargetData[id]
|
||||
lastPrice = float("{:.3f}".format(tickData['lastPrice']))
|
||||
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