完善UI操作逻辑
This commit is contained in:
@@ -10,8 +10,12 @@ ActionDisableMarketData = "disable_market_data"
|
|||||||
MarketDataEnabled = "market_data_enabled"
|
MarketDataEnabled = "market_data_enabled"
|
||||||
MarketDataDisabled = "market_data_disabled"
|
MarketDataDisabled = "market_data_disabled"
|
||||||
# 删除交易标的事件
|
# 删除交易标的事件
|
||||||
|
ActionEventAddTradeTarget = "add_trade_target"
|
||||||
|
ResultEventTradeTargetAdded = "trade_target_added"
|
||||||
ActionEventDeleteTradeTarget = "delete_trade_target"
|
ActionEventDeleteTradeTarget = "delete_trade_target"
|
||||||
ResultEventTradeTargetDeleted = "trade_target_deleted"
|
ResultEventTradeTargetDeleted = "trade_target_deleted"
|
||||||
|
# Pring Log
|
||||||
|
EventPrintLog = "print_log"
|
||||||
|
|
||||||
|
|
||||||
class EventBus:
|
class EventBus:
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
from enum import Enum
|
||||||
|
|
||||||
|
from core.eventbus import EventPrintLog, event_bus
|
||||||
|
|
||||||
|
class LogLevel(Enum):
|
||||||
|
DEBUG = "DEBUG"
|
||||||
|
INFO = "INFO"
|
||||||
|
WARNING = "WARNING"
|
||||||
|
ERROR = "ERROR"
|
||||||
|
CRITICAL = "CRITICAL"
|
||||||
|
|
||||||
|
class LogData:
|
||||||
|
def __init__(self, level:LogLevel, message:str):
|
||||||
|
self.level = level
|
||||||
|
self.message = message
|
||||||
|
|
||||||
|
def PrintLog(level:LogLevel, message:str):
|
||||||
|
data = LogData(level, message)
|
||||||
|
event_bus.publish(EventPrintLog, data)
|
||||||
+51
-51
@@ -1,6 +1,6 @@
|
|||||||
# coding:utf-8
|
# coding:utf-8
|
||||||
from core.strategy_db import TradeTarget
|
from core.strategy_db import TradeTarget
|
||||||
from core.eventbus import ActionDisableMarketData, ActionEnableMarketData, ActionEventDeleteTradeTarget, ActionEventDisableTrade, ActionEventEnableTrade, MarketDataUpdate, MarketDataEnabled, MarketDataDisabled, ResultEventTradeDisabled, ResultEventTradeEnabled, ResultEventTradeTargetDeleted, event_bus
|
from core.eventbus import ActionDisableMarketData, ActionEnableMarketData, ActionEventAddTradeTarget, ActionEventDeleteTradeTarget, ActionEventDisableTrade, ActionEventEnableTrade, MarketDataUpdate, MarketDataEnabled, MarketDataDisabled, ResultEventTradeDisabled, ResultEventTradeEnabled, ResultEventTradeTargetDeleted, event_bus
|
||||||
from xtquant.xttrader import XtQuantTrader
|
from xtquant.xttrader import XtQuantTrader
|
||||||
import time
|
import time
|
||||||
from peewee import ModelSelect
|
from peewee import ModelSelect
|
||||||
@@ -15,6 +15,7 @@ from xtquant import xtdata
|
|||||||
from xtquant.xttrader import XtQuantTraderCallback
|
from xtquant.xttrader import XtQuantTraderCallback
|
||||||
import datetime
|
import datetime
|
||||||
import core.ui as ui
|
import core.ui as ui
|
||||||
|
from core.logger import PrintLog, LogLevel
|
||||||
|
|
||||||
# 量化核心控制对象
|
# 量化核心控制对象
|
||||||
class SFGridController(XtQuantTraderCallback):
|
class SFGridController(XtQuantTraderCallback):
|
||||||
@@ -31,8 +32,8 @@ class SFGridController(XtQuantTraderCallback):
|
|||||||
self.xt_trader: XtQuantTrader = XtQuantTrader(miniQmtPath, session_id)
|
self.xt_trader: XtQuantTrader = XtQuantTrader(miniQmtPath, session_id)
|
||||||
self.xt_trader.register_callback(self)
|
self.xt_trader.register_callback(self)
|
||||||
self.xt_trader.start()
|
self.xt_trader.start()
|
||||||
connect_result = self.xt_trader.connect()
|
self.xt_trader.connect()
|
||||||
print(f'- [{'成功' if self.xt_trader.connected else '失败'}]市场交易连接{connect_result}--: {miniQmtPath}')
|
PrintLog(LogLevel.INFO, f'- [{'成功' if self.xt_trader.connected else '失败'}]市场交易连接: {miniQmtPath}')
|
||||||
if self.xt_trader.connected == False:
|
if self.xt_trader.connected == False:
|
||||||
self.inited: bool = False
|
self.inited: bool = False
|
||||||
return
|
return
|
||||||
@@ -40,9 +41,9 @@ class SFGridController(XtQuantTraderCallback):
|
|||||||
self.inited = True
|
self.inited = True
|
||||||
|
|
||||||
self.account= StockAccount(account_no, 'STOCK')
|
self.account= StockAccount(account_no, 'STOCK')
|
||||||
print(f'- [成功]交易账号对象初始化完成, 账号: {self.account.account_id}') # pyright: ignore[reportAttributeAccessIssue]
|
PrintLog(LogLevel.INFO, f'- [成功]交易账号对象初始化完成, 账号: {self.account.account_id}') # pyright: ignore[reportAttributeAccessIssue]
|
||||||
subscribe_result = self.xt_trader.subscribe(self.account)
|
subscribe_result = self.xt_trader.subscribe(self.account)
|
||||||
print(f'- [{'成功' if subscribe_result == 0 else '失败'}:{subscribe_result}]交易状态订阅')
|
PrintLog(LogLevel.INFO, f'- [{'成功' if subscribe_result == 0 else '失败'}:{subscribe_result}]交易状态订阅')
|
||||||
if subscribe_result == 0:
|
if subscribe_result == 0:
|
||||||
self.inited = True
|
self.inited = True
|
||||||
else:
|
else:
|
||||||
@@ -52,15 +53,15 @@ class SFGridController(XtQuantTraderCallback):
|
|||||||
self.init_instrument_pool(self.xt_trader, self.account) # type: ignore
|
self.init_instrument_pool(self.xt_trader, self.account) # type: ignore
|
||||||
|
|
||||||
self.seq = None
|
self.seq = None
|
||||||
print('- [成功]三疯交易系统初始化完成')
|
PrintLog(LogLevel.INFO, '- [成功]三疯交易系统初始化完成')
|
||||||
# self.startMarketData()
|
self.startMarketData()
|
||||||
|
|
||||||
def registerEventHandler(self):
|
def registerEventHandler(self):
|
||||||
event_bus.subscribe(ActionEventEnableTrade, self.onEnableTrade)
|
event_bus.subscribe(ActionEventEnableTrade, self.onEnableTrade)
|
||||||
event_bus.subscribe(ActionEventDisableTrade, self.onDisableTrade)
|
event_bus.subscribe(ActionEventDisableTrade, self.onDisableTrade)
|
||||||
event_bus.subscribe(ActionEnableMarketData, self.onMarketDataEnabled)
|
event_bus.subscribe(ActionEnableMarketData, self.onMarketDataEnabled)
|
||||||
event_bus.subscribe(ActionDisableMarketData, self.onMarketDataDisabled)
|
event_bus.subscribe(ActionDisableMarketData, self.onMarketDataDisabled)
|
||||||
event_bus.subscribe("add_trade_target", self.onAddTradeTarget)
|
event_bus.subscribe(ActionEventAddTradeTarget, self.onAddTradeTarget)
|
||||||
event_bus.subscribe(ActionEventDeleteTradeTarget, self.onDeleteTradeTarget)
|
event_bus.subscribe(ActionEventDeleteTradeTarget, self.onDeleteTradeTarget)
|
||||||
|
|
||||||
def onDeleteTradeTarget(self, id: int):
|
def onDeleteTradeTarget(self, id: int):
|
||||||
@@ -91,17 +92,20 @@ class SFGridController(XtQuantTraderCallback):
|
|||||||
self.appUi.run()
|
self.appUi.run()
|
||||||
|
|
||||||
def startMarketData(self):
|
def startMarketData(self):
|
||||||
print('- 启动市场数据订阅')
|
PrintLog(LogLevel.INFO, '- 启动市场数据订阅')
|
||||||
|
|
||||||
self.seq = xtdata.subscribe_whole_quote(['SH', 'SZ'], callback=self.onDataUpdate)
|
self.seq = xtdata.subscribe_whole_quote(['SH', 'SZ'], callback=self.onDataUpdate)
|
||||||
if self.seq == -1:
|
if self.seq == -1:
|
||||||
print('- 市场数据订阅失败')
|
PrintLog(LogLevel.ERROR, '- 市场数据订阅失败')
|
||||||
else:
|
else:
|
||||||
event_bus.publish(MarketDataEnabled, True)
|
event_bus.publish(MarketDataEnabled, True)
|
||||||
print(f'- 市场数据订阅成功, 订阅号={self.seq}')
|
PrintLog(LogLevel.INFO, f'- 市场数据订阅成功, 订阅号={self.seq}')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def stopMarketData(self):
|
def stopMarketData(self):
|
||||||
print('- 停止市场数据订阅')
|
PrintLog(LogLevel.INFO, '- 停止市场数据订阅')
|
||||||
|
|
||||||
if self.seq is not None and self.seq > 0:
|
if self.seq is not None and self.seq > 0:
|
||||||
xtdata.unsubscribe_quote(self.seq)
|
xtdata.unsubscribe_quote(self.seq)
|
||||||
event_bus.publish(MarketDataDisabled, False)
|
event_bus.publish(MarketDataDisabled, False)
|
||||||
@@ -111,13 +115,13 @@ class SFGridController(XtQuantTraderCallback):
|
|||||||
try:
|
try:
|
||||||
stock_name = getInstrumentName(stock_code)
|
stock_name = getInstrumentName(stock_code)
|
||||||
if not stock_name:
|
if not stock_name:
|
||||||
print(f'无法获取股票代码 {stock_code} 的名称,请检查代码是否正确')
|
PrintLog(LogLevel.ERROR, f'无法获取股票代码 {stock_code} 的名称,请检查代码是否正确')
|
||||||
return
|
return
|
||||||
|
|
||||||
# 检查是否已存在该标的
|
# 检查是否已存在该标的
|
||||||
existing_target = strategy_db.TradeTarget.get_or_none(strategy_db.TradeTarget.stock_code == stock_code)
|
existing_target = strategy_db.TradeTarget.get_or_none(strategy_db.TradeTarget.stock_code == stock_code)
|
||||||
if existing_target:
|
if existing_target:
|
||||||
print(f'交易标的 {stock_code} {stock_name} 已存在')
|
PrintLog(LogLevel.INFO, f'交易标的 {stock_code} {stock_name} 已存在')
|
||||||
return
|
return
|
||||||
|
|
||||||
new_target = strategy_db.TradeTarget.create(
|
new_target = strategy_db.TradeTarget.create(
|
||||||
@@ -134,7 +138,7 @@ class SFGridController(XtQuantTraderCallback):
|
|||||||
current_order_type=''
|
current_order_type=''
|
||||||
)
|
)
|
||||||
new_target.save()
|
new_target.save()
|
||||||
print(f'新增交易标的 {stock_code} {stock_name}, {new_target.id}')
|
PrintLog(LogLevel.INFO, f'新增交易标的 {stock_code} {stock_name}, {new_target.id}')
|
||||||
# 刷新标的持仓
|
# 刷新标的持仓
|
||||||
pos = getStockPosition(stock_code, self.xt_trader, self.account) # type: ignore
|
pos = getStockPosition(stock_code, self.xt_trader, self.account) # type: ignore
|
||||||
strategy_db.TradeTarget.update(current_position=pos).where(strategy_db.TradeTarget.stock_code == stock_code).execute()
|
strategy_db.TradeTarget.update(current_position=pos).where(strategy_db.TradeTarget.stock_code == stock_code).execute()
|
||||||
@@ -145,14 +149,14 @@ class SFGridController(XtQuantTraderCallback):
|
|||||||
self.stock_trade_ctrl[stock_code] = stockTradeController
|
self.stock_trade_ctrl[stock_code] = stockTradeController
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f'新增交易标的失败 {stock_code} {e}')
|
PrintLog(LogLevel.ERROR, f'新增交易标的失败 {stock_code} {e}')
|
||||||
|
|
||||||
|
|
||||||
def del_trade_target(self, id:int):
|
def del_trade_target(self, id:int):
|
||||||
try:
|
try:
|
||||||
# 检查标的是否存在
|
# 检查标的是否存在
|
||||||
if id not in self.instrument_pool:
|
if id not in self.instrument_pool:
|
||||||
print(f"交易标的 ID {id} 不存在")
|
PrintLog(LogLevel.ERROR, f"交易标的 ID {id} 不存在")
|
||||||
return
|
return
|
||||||
|
|
||||||
target: strategy_db.TradeTarget = self.instrument_pool[id]
|
target: strategy_db.TradeTarget = self.instrument_pool[id]
|
||||||
@@ -171,23 +175,27 @@ class SFGridController(XtQuantTraderCallback):
|
|||||||
# 刷新标的池
|
# 刷新标的池
|
||||||
self.refresh_targets()
|
self.refresh_targets()
|
||||||
|
|
||||||
print(f"已删除交易标的: {target.stock_code} - {target.stock_name}")
|
PrintLog(LogLevel.INFO, f"已删除交易标的: {target.stock_code} - {target.stock_name}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"删除交易标的失败 ID {id}: {str(e)}")
|
PrintLog(LogLevel.ERROR, f"删除交易标的失败 ID {id}: {str(e)}")
|
||||||
|
|
||||||
def init_instrument_pool(self, xtTrader:XtQuantTrader, account:StockAccount):
|
def init_instrument_pool(self, xtTrader:XtQuantTrader, account:StockAccount):
|
||||||
self.refresh_targets()
|
self.refresh_targets()
|
||||||
|
|
||||||
for id in self.instrument_pool:
|
for id in self.instrument_pool:
|
||||||
|
target:TradeTarget = self.instrument_pool[id]
|
||||||
|
status = "新建" if target.status == 0 else "已建初始仓"
|
||||||
|
PrintLog(LogLevel.INFO, f' [序号-{id}] 股票代码: {target.stock_code}-{target.stock_name} 当前持仓: {getStockPosition(target.stock_code, self.xt_trader, self.account)} 网格索引: {target.grid_index} 基准价格 {sfgrid_constants.grid_price[target.grid_index]} 状态: {status} 启用交易线程: {'自动交易中' if target.enabled else '交易已停止'}') # type: ignore
|
||||||
|
|
||||||
tradeTarget:strategy_db.TradeTarget = self.instrument_pool[id]
|
tradeTarget:strategy_db.TradeTarget = self.instrument_pool[id]
|
||||||
tradeTarget.current_position = getStockPosition(tradeTarget.stock_code, xtTrader, account) # type: ignore
|
tradeTarget.current_position = getStockPosition(tradeTarget.stock_code, xtTrader, account) # type: ignore
|
||||||
result = tradeTarget.save()
|
result = tradeTarget.save()
|
||||||
print(f' |- 同步当前持仓信息 {tradeTarget.stock_code}, {tradeTarget.current_position}, result = {result}')
|
PrintLog(LogLevel.INFO, f' |- 同步[{target.stock_code}-{target.stock_name}]持仓信息[{'成功' if result == 1 else '失败'}]')
|
||||||
stockTradeController = SFGridStrategy(tradeTarget, self.xt_trader, self.account) # type: ignore
|
stockTradeController = SFGridStrategy(tradeTarget, self.xt_trader, self.account) # type: ignore
|
||||||
self.stock_trade_ctrl[tradeTarget.stock_code] = stockTradeController
|
self.stock_trade_ctrl[tradeTarget.stock_code] = stockTradeController
|
||||||
event_bus.publish(MarketDataUpdate, tradeTarget)
|
event_bus.publish(MarketDataUpdate, tradeTarget)
|
||||||
|
|
||||||
print(f'- [成功]交易标的信息初始化, 共 {len(self.instrument_pool)} 个标的')
|
PrintLog(LogLevel.INFO, f'- [成功]交易标的信息初始化, 共 {len(self.instrument_pool)} 个标的')
|
||||||
|
|
||||||
|
|
||||||
def refresh_targets(self):
|
def refresh_targets(self):
|
||||||
@@ -197,55 +205,47 @@ class SFGridController(XtQuantTraderCallback):
|
|||||||
for temp in results:
|
for temp in results:
|
||||||
result :strategy_db.TradeTarget = temp
|
result :strategy_db.TradeTarget = temp
|
||||||
self.instrument_pool[result.get_id()] = result
|
self.instrument_pool[result.get_id()] = result
|
||||||
self.print_pool()
|
|
||||||
|
|
||||||
def print_pool(self):
|
|
||||||
print("- [信息]标的池信息")
|
|
||||||
for id in self.instrument_pool:
|
|
||||||
target: strategy_db.TradeTarget = self.instrument_pool[id]
|
|
||||||
status = "新建" if target.status == 0 else "已建初始仓"
|
|
||||||
print(f' [序号-{id}] 股票代码: {target.stock_code}-{target.stock_name} 当前持仓: {getStockPosition(target.stock_code, self.xt_trader, self.account)} 网格索引: {target.grid_index} 基准价格 {sfgrid_constants.grid_price[target.grid_index]} 状态: {status} 启用交易线程: {'自动交易中' if target.enabled else '交易已停止'}') # type: ignore
|
|
||||||
|
|
||||||
def print_position_info(self):
|
def print_position_info(self):
|
||||||
positions:list[XtPosition] = self.xt_trader.query_stock_positions(self.account)
|
positions:list[XtPosition] = self.xt_trader.query_stock_positions(self.account)
|
||||||
if positions:
|
if positions:
|
||||||
print("\n- 持仓信息")
|
PrintLog(LogLevel.INFO, "\n- 持仓信息")
|
||||||
for temp in positions:
|
for temp in positions:
|
||||||
pos : XtPosition = temp
|
pos : XtPosition = temp
|
||||||
if pos.volume <=0:
|
if pos.volume <=0:
|
||||||
continue
|
continue
|
||||||
print(f"股票代码: {pos.stock_code}-{getInstrumentName(pos.stock_code)}")
|
PrintLog(LogLevel.INFO, f"股票代码: {pos.stock_code}-{getInstrumentName(pos.stock_code)}")
|
||||||
print(f"总持仓: {pos.volume}")
|
PrintLog(LogLevel.INFO, f"总持仓: {pos.volume}")
|
||||||
print(f"可用持仓: {pos.can_use_volume}")
|
PrintLog(LogLevel.INFO, f"可用持仓: {pos.can_use_volume}")
|
||||||
print(f"持仓成本: {pos.avg_price}")
|
PrintLog(LogLevel.INFO, f"持仓成本: {pos.avg_price}")
|
||||||
print("---")
|
PrintLog(LogLevel.INFO, "---")
|
||||||
else:
|
else:
|
||||||
print("\n当前无持仓")
|
PrintLog(LogLevel.INFO, "\n当前无持仓")
|
||||||
|
|
||||||
def print_account_info(self):
|
def print_account_info(self):
|
||||||
temp = self.xt_trader.query_stock_asset(self.account)
|
temp = self.xt_trader.query_stock_asset(self.account)
|
||||||
asset: XtAsset = temp # type: ignore
|
asset: XtAsset = temp # type: ignore
|
||||||
|
|
||||||
print(f"=== 账户信息 {self.account.account_id} ===") # type: ignore
|
PrintLog(LogLevel.INFO, f"=== 账户信息 {self.account.account_id} ===") # type: ignore
|
||||||
print(f"可用资金: {asset.cash}")
|
PrintLog(LogLevel.INFO, f"可用资金: {asset.cash}")
|
||||||
print(f"总资产: {asset.total_asset}")
|
PrintLog(LogLevel.INFO, f"总资产: {asset.total_asset}")
|
||||||
print(f"证券市值: {asset.market_value}")
|
PrintLog(LogLevel.INFO, f"证券市值: {asset.market_value}")
|
||||||
|
|
||||||
def print_stock_orders(self):
|
def print_stock_orders(self):
|
||||||
orders = self.xt_trader.query_stock_orders(self.account, cancelable_only=True)
|
orders = self.xt_trader.query_stock_orders(self.account, cancelable_only=True)
|
||||||
if orders:
|
if orders:
|
||||||
print("\n=== 委托信息 ===")
|
PrintLog(LogLevel.INFO, "\n=== 委托信息 ===")
|
||||||
for order in orders:
|
for order in orders:
|
||||||
print(f"委托编号: {order.order_id}")
|
PrintLog(LogLevel.INFO, f"委托编号: {order.order_id}")
|
||||||
print(f"股票代码: {order.stock_code} {getInstrumentName(order.stock_code)}")
|
PrintLog(LogLevel.INFO, f"股票代码: {order.stock_code} {getInstrumentName(order.stock_code)}")
|
||||||
print(f"委托方向: {order.offset_flag} ")
|
PrintLog(LogLevel.INFO, f"委托方向: {order.offset_flag} ")
|
||||||
print(f"委托价格: {order.price}")
|
PrintLog(LogLevel.INFO, f"委托价格: {order.price}")
|
||||||
print(f"委托数量: {order.order_volume}")
|
PrintLog(LogLevel.INFO, f"委托数量: {order.order_volume}")
|
||||||
print(f"已成交数量: {order.traded_volume}")
|
PrintLog(LogLevel.INFO, f"已成交数量: {order.traded_volume}")
|
||||||
print(f"委托状态: {order.order_status} ")
|
PrintLog(LogLevel.INFO, f"委托状态: {order.order_status} ")
|
||||||
print("---")
|
PrintLog(LogLevel.INFO, "---")
|
||||||
else:
|
else:
|
||||||
print("\n当前无委托记录")
|
PrintLog(LogLevel.INFO, "\n当前无委托记录")
|
||||||
|
|
||||||
|
|
||||||
# 初始化指定标的交易控制器
|
# 初始化指定标的交易控制器
|
||||||
@@ -259,7 +259,7 @@ class SFGridController(XtQuantTraderCallback):
|
|||||||
self.instrument_pool[id] = tradeTarget
|
self.instrument_pool[id] = tradeTarget
|
||||||
event_bus.publish(ResultEventTradeEnabled, tradeTarget)
|
event_bus.publish(ResultEventTradeEnabled, tradeTarget)
|
||||||
else:
|
else:
|
||||||
print(f"\t创建标的交易控制器 {tradeTarget.stock_code} {getInstrumentName(tradeTarget.stock_code)}")
|
PrintLog(LogLevel.INFO, f"\t创建标的交易控制器 {tradeTarget.stock_code} {getInstrumentName(tradeTarget.stock_code)}")
|
||||||
|
|
||||||
|
|
||||||
def pause_stock_trade(self, id: int):
|
def pause_stock_trade(self, id: int):
|
||||||
|
|||||||
+72
-53
@@ -1,10 +1,13 @@
|
|||||||
|
from peewee import IntegerField
|
||||||
|
|
||||||
|
|
||||||
from core import strategy_db
|
from core import strategy_db
|
||||||
from core.eventbus import MarketDataUpdate, event_bus
|
from core.eventbus import MarketDataUpdate, event_bus
|
||||||
from core.strategy_db import TradeTarget
|
from core.strategy_db import OrderTypeBuy, OrderTypeInit, OrderTypeSell, TradeTarget
|
||||||
from core.util import queryPendingOrder
|
from core.util import queryPendingOrder
|
||||||
|
|
||||||
from xtquant import xttrader, xtconstant
|
from xtquant import xttrader, xtconstant
|
||||||
from xtquant.xttype import StockAccount, XtOrder, XtOrderResponse, XtTrade
|
from xtquant.xttype import StockAccount, XtOrder, XtTrade
|
||||||
import sfgrid_constants
|
import sfgrid_constants
|
||||||
import threading
|
import threading
|
||||||
|
|
||||||
@@ -16,8 +19,9 @@ class SFGridStrategy:
|
|||||||
self.xt_trader: xttrader.XtQuantTrader = xt_trader
|
self.xt_trader: xttrader.XtQuantTrader = xt_trader
|
||||||
self.account:StockAccount = account
|
self.account:StockAccount = account
|
||||||
self.enabledTrading(bool(tradeTarget.enabled)) # 修复类型兼容性问题
|
self.enabledTrading(bool(tradeTarget.enabled)) # 修复类型兼容性问题
|
||||||
|
|
||||||
|
event_bus.publish(MarketDataUpdate, self.tradeTarget)
|
||||||
self.dataUpdateLock = threading.Lock()
|
self.dataUpdateLock = threading.Lock()
|
||||||
print(f'标的{self.tradeTarget.targetName()}交易启动状态 {self.tradeTarget.enabled}')
|
|
||||||
|
|
||||||
|
|
||||||
def enabledTrading(self, enabled: bool) -> TradeTarget:
|
def enabledTrading(self, enabled: bool) -> TradeTarget:
|
||||||
@@ -25,26 +29,11 @@ class SFGridStrategy:
|
|||||||
self.saveProxy()
|
self.saveProxy()
|
||||||
|
|
||||||
if enabled:
|
if enabled:
|
||||||
|
self.refreshPlanPrice()
|
||||||
print(f" |- 标的{self.tradeTarget.targetName()}交易启动, 持仓量:{self.tradeTarget.current_position}")
|
print(f" |- 标的{self.tradeTarget.targetName()}交易启动, 持仓量:{self.tradeTarget.current_position}")
|
||||||
if self.tradeTarget.status == 0: # 未建仓
|
if self.tradeTarget.status == 0: # 未建仓
|
||||||
print(f" |- 标的{self.tradeTarget.targetName()}初始状态,检查订单")
|
print(f" |- 标的{self.tradeTarget.targetName()}初始状态, 设置网格序号 1")
|
||||||
orders = queryPendingOrder(str(self.tradeTarget.stock_code),self.getName(), self.xt_trader,self.account)
|
|
||||||
if len([order for order in orders if order.order_type == xtconstant.STOCK_BUY and order.price == sfgrid_constants.grid_price[1]]) > 0:
|
|
||||||
# 已存在未交易的多单
|
|
||||||
order = [order for order in orders if order.order_type == xtconstant.STOCK_BUY and order.price == sfgrid_constants.grid_price[1]][0]
|
|
||||||
print(f' |- 已存在未交易的建仓单,不重复下单:{order.order_id}')
|
|
||||||
else:
|
|
||||||
# 建仓
|
|
||||||
self.tradeTarget.grid_index = 1 # pyright: ignore[reportAttributeAccessIssue]
|
self.tradeTarget.grid_index = 1 # pyright: ignore[reportAttributeAccessIssue]
|
||||||
self.tradeTarget.current_order_no = self.xt_trader.order_stock_async(
|
|
||||||
self.account,
|
|
||||||
str(self.tradeTarget.stock_code),
|
|
||||||
xtconstant.STOCK_BUY,
|
|
||||||
sfgrid_constants.grid_volume,
|
|
||||||
xtconstant.FIX_PRICE,
|
|
||||||
sfgrid_constants.grid_price[int(self.tradeTarget.grid_index)], # type: ignore
|
|
||||||
self.getName(), strategy_db.OrderTypeInit)
|
|
||||||
print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 建初始仓 买单已发出 InitBuyOrderSeq: {self.tradeTarget.current_order_no} Price: {sfgrid_constants.grid_price[int(self.tradeTarget.grid_index)]} Volume: {sfgrid_constants.grid_volume}\n") # type: ignore
|
|
||||||
else: # 已建仓
|
else: # 已建仓
|
||||||
# 交易阶段,检查仓位,检查现有订单
|
# 交易阶段,检查仓位,检查现有订单
|
||||||
print(f" |- 标的{self.tradeTarget.targetName()}已有仓位或非初始状态 无需建初始仓 当前仓位: {self.tradeTarget.current_position} 状态: {self.tradeTarget.status}")
|
print(f" |- 标的{self.tradeTarget.targetName()}已有仓位或非初始状态 无需建初始仓 当前仓位: {self.tradeTarget.current_position} 状态: {self.tradeTarget.status}")
|
||||||
@@ -52,7 +41,9 @@ class SFGridStrategy:
|
|||||||
if minRequirePosition <= int(self.tradeTarget.current_position): # type: ignore
|
if minRequirePosition <= int(self.tradeTarget.current_position): # type: ignore
|
||||||
print(f' |- 仓位检查: 持仓需求充足, (gridVolume*gridIndex)={minRequirePosition}, 当前持仓:{self.tradeTarget.current_position}')
|
print(f' |- 仓位检查: 持仓需求充足, (gridVolume*gridIndex)={minRequirePosition}, 当前持仓:{self.tradeTarget.current_position}')
|
||||||
else:
|
else:
|
||||||
print(f' |- 仓位检查: 持仓需求不足, (gridVolume*gridIndex)={minRequirePosition}, 当前持仓:{self.tradeTarget.current_position}')
|
print(f' |- 仓位检查: 持仓需求不足, (gridVolume*gridIndex)={minRequirePosition}, 当前持仓:{self.tradeTarget.current_position}, 交易启动失败')
|
||||||
|
self.tradeTarget.enabled = False # type: ignore
|
||||||
|
self.saveProxy()
|
||||||
else:
|
else:
|
||||||
print(f" |- 标的{self.tradeTarget.targetName()}交易监控暂停")
|
print(f" |- 标的{self.tradeTarget.targetName()}交易监控暂停")
|
||||||
return self.tradeTarget
|
return self.tradeTarget
|
||||||
@@ -68,61 +59,72 @@ class SFGridStrategy:
|
|||||||
self.tradeTarget.market_price = lastPrice # type: ignore
|
self.tradeTarget.market_price = lastPrice # type: ignore
|
||||||
self.saveProxy()
|
self.saveProxy()
|
||||||
|
|
||||||
if not(self.tradeTarget.enabled and self.tradeTarget.status == 1): # 已建仓,常规自动交易中
|
if not self.tradeTarget.enabled: # 未建仓,自动交易暂停
|
||||||
print(f"|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 未建仓或交易监控暂停,不进行自动交易")
|
print(f"|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 未建仓或交易监控暂停,不进行自动交易")
|
||||||
return
|
return
|
||||||
|
|
||||||
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')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
index = self.tradeTarget.grid_index
|
orderPrice:float = -1
|
||||||
price = -1 if index>=len(sfgrid_constants.grid_price) else sfgrid_constants.grid_price[int(index)] # pyright: ignore[reportArgumentType]
|
orderType = -1
|
||||||
|
index: int = self.tradeTarget.grid_index # pyright: ignore[reportAssignmentType]
|
||||||
|
orderRemark= ""
|
||||||
|
|
||||||
|
gridBasePrice = -1 if index>=len(sfgrid_constants.grid_price) or index < 0 else sfgrid_constants.grid_price[int(index)] # pyright: ignore[reportArgumentType]
|
||||||
|
|
||||||
|
if self.tradeTarget.enabled and self.tradeTarget.status == 0: # 已启用,未建仓,建仓
|
||||||
|
orderPrice = sfgrid_constants.grid_price[index]
|
||||||
|
orderType = xtconstant.STOCK_BUY
|
||||||
|
orderRemark = OrderTypeInit
|
||||||
|
|
||||||
|
if self.tradeTarget.enabled and self.tradeTarget.status == 1: # 已启用,已建仓,网格单
|
||||||
lowPrice = -1 if index+1>=len(sfgrid_constants.grid_price) else sfgrid_constants.grid_price[int(index) + 1] # pyright: ignore[reportArgumentType]
|
lowPrice = -1 if index+1>=len(sfgrid_constants.grid_price) else sfgrid_constants.grid_price[int(index) + 1] # pyright: ignore[reportArgumentType]
|
||||||
highPrice = sfgrid_constants.grid_price[int(index) - 1] # pyright: ignore[reportArgumentType]
|
highPrice = sfgrid_constants.grid_price[index - 1]
|
||||||
|
|
||||||
if lastPrice <= lowPrice: # 下下方多单
|
if lastPrice <= lowPrice: # 下下方多单
|
||||||
|
orderPrice = lowPrice
|
||||||
|
orderType = xtconstant.STOCK_BUY
|
||||||
|
orderRemark = OrderTypeBuy
|
||||||
|
|
||||||
|
elif lastPrice >= highPrice: # 下上方空单
|
||||||
|
orderPrice = highPrice
|
||||||
|
orderType = xtconstant.STOCK_SELL
|
||||||
|
orderRemark = OrderTypeSell
|
||||||
|
|
||||||
|
if orderType != -1:
|
||||||
orders = queryPendingOrder(str(self.tradeTarget.stock_code), self.getName(), self.xt_trader, self.account)
|
orders = queryPendingOrder(str(self.tradeTarget.stock_code), self.getName(), self.xt_trader, self.account)
|
||||||
if len([order for order in orders if order.order_type == xtconstant.STOCK_BUY and order.price == lowPrice]) > 0:
|
if len([order for order in orders if order.order_type == orderType and order.price == orderPrice]) > 0:
|
||||||
# 已存在未交易的多单
|
# 已存在未交易的多单
|
||||||
print(f' |- 已存在未交易的多单,不重复下单')
|
print(f' |- 已存在未交易的{"多单" if orderType == xtconstant.STOCK_BUY else "空单"},不重复下单')
|
||||||
else:
|
else:
|
||||||
print(f' |- 下网格多单')
|
print(f' |- 下网格{"多单" if orderType == xtconstant.STOCK_BUY else "空单"}')
|
||||||
self.tradeTarget.current_order_no = self.xt_trader.order_stock_async(
|
self.tradeTarget.current_order_no = self.xt_trader.order_stock_async(
|
||||||
self.account,
|
self.account,
|
||||||
str(self.tradeTarget.stock_code),
|
str(self.tradeTarget.stock_code),
|
||||||
xtconstant.STOCK_BUY,
|
orderType,
|
||||||
sfgrid_constants.grid_volume,
|
sfgrid_constants.grid_volume,
|
||||||
xtconstant.FIX_PRICE,
|
xtconstant.FIX_PRICE,
|
||||||
lowPrice,
|
orderPrice,
|
||||||
self.getName(), # strategy_name
|
self.getName(), # strategy_name
|
||||||
strategy_db.OrderTypeBuy # remark # type: ignore
|
orderRemark # remark # type: ignore
|
||||||
)
|
)
|
||||||
self.tradeTarget.plan_buy_price = float(lowPrice) # type: ignore
|
orderTypeName = ""
|
||||||
print(f' |- 下网格多单号 {self.tradeTarget.current_order_no}, 网格基准价 {price}, 下单价 {lowPrice}, 下单量 {sfgrid_constants.grid_volume}')
|
if orderRemark == OrderTypeBuy:
|
||||||
elif lastPrice == highPrice: # 下上方空单
|
orderTypeName = "多单"
|
||||||
orders = queryPendingOrder(str(self.tradeTarget.stock_code), self.getName(), self.xt_trader, self.account)
|
elif orderRemark == OrderTypeSell:
|
||||||
if len([order for order in orders if order.order_type == xtconstant.STOCK_SELL and order.price == highPrice]) > 0:
|
orderTypeName = "空单"
|
||||||
# 已存在未交易的空单
|
elif orderRemark == OrderTypeInit:
|
||||||
print(f' |- 已存在未交易的空单,不重复下单')
|
orderTypeName = "建仓单"
|
||||||
else:
|
print(f' |- {orderTypeName}委托, 单号 {self.tradeTarget.current_order_no}, 网格基准价 {gridBasePrice}, 下单价 {orderPrice}, 下单量 {sfgrid_constants.grid_volume}')
|
||||||
print(f' |- 下网格空单')
|
|
||||||
self.tradeTarget.current_order_no = self.xt_trader.order_stock_async(
|
|
||||||
self.account,
|
|
||||||
str(self.tradeTarget.stock_code),
|
|
||||||
xtconstant.STOCK_SELL,
|
|
||||||
sfgrid_constants.grid_volume,
|
|
||||||
xtconstant.FIX_PRICE,
|
|
||||||
highPrice,
|
|
||||||
self.getName(),
|
|
||||||
strategy_db.OrderTypeBuy) # type: ignore
|
|
||||||
self.tradeTarget.plan_sell_price = float(highPrice) # type: ignore
|
|
||||||
print(f' |- 下网格空单号 {self.tradeTarget.current_order_no}, 网格基准价 {price}, 下单价 {highPrice}, 下单量 {sfgrid_constants.grid_volume}')
|
|
||||||
finally:
|
finally:
|
||||||
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - release lock')
|
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - release lock')
|
||||||
self.saveProxy()
|
self.saveProxy()
|
||||||
self.dataUpdateLock.release()
|
self.dataUpdateLock.release()
|
||||||
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - END')
|
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - END')
|
||||||
|
|
||||||
|
|
||||||
def onAsyncOrderResponse(self, order:XtOrder):
|
def onAsyncOrderResponse(self, order:XtOrder):
|
||||||
print(f' |- 委托回调[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{order.order_id}]:START')
|
print(f' |- 委托回调[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{order.order_id}]:START')
|
||||||
self.dataUpdateLock.acquire()
|
self.dataUpdateLock.acquire()
|
||||||
@@ -153,6 +155,8 @@ class SFGridStrategy:
|
|||||||
self.tradeTarget.current_position = int(self.tradeTarget.current_position) + trade.traded_volume # 当前持仓数,账户原有持仓不在策略范围内 # type: ignore
|
self.tradeTarget.current_position = int(self.tradeTarget.current_position) + trade.traded_volume # 当前持仓数,账户原有持仓不在策略范围内 # type: ignore
|
||||||
self.tradeTarget.last_trade_price = float(trade.traded_price) # type: ignore
|
self.tradeTarget.last_trade_price = float(trade.traded_price) # type: ignore
|
||||||
self.tradeTarget.grid_index = 1 # type: ignore
|
self.tradeTarget.grid_index = 1 # type: ignore
|
||||||
|
self.tradeTarget.plan_buy_price = float(sfgrid_constants.grid_price[2]) # type: ignore
|
||||||
|
self.tradeTarget.plan_sell_price = float(sfgrid_constants.grid_price[0]) # type: ignore
|
||||||
self.tradeTarget.status = 1 # type: ignore
|
self.tradeTarget.status = 1 # type: ignore
|
||||||
self.saveProxy()
|
self.saveProxy()
|
||||||
print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 建初始仓订单ID: {self.tradeTarget.current_order_no}已成交 ")
|
print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 建初始仓订单ID: {self.tradeTarget.current_order_no}已成交 ")
|
||||||
@@ -164,7 +168,6 @@ class SFGridStrategy:
|
|||||||
self.tradeTarget.current_position = int(self.tradeTarget.current_position) - trade.traded_volume # type: ignore
|
self.tradeTarget.current_position = int(self.tradeTarget.current_position) - trade.traded_volume # type: ignore
|
||||||
self.tradeTarget.last_trade_price = float(trade.traded_price) # type: ignore
|
self.tradeTarget.last_trade_price = float(trade.traded_price) # type: ignore
|
||||||
self.tradeTarget.grid_index = int(self.tradeTarget.grid_index) - 1 # type: ignore
|
self.tradeTarget.grid_index = int(self.tradeTarget.grid_index) - 1 # type: ignore
|
||||||
self.saveProxy()
|
|
||||||
print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 上涨 卖单已成交 订单ID: {self.tradeTarget.current_order_no} Price: {sfgrid_constants.grid_price[int(self.tradeTarget.grid_index)]} Volume: {sfgrid_constants.grid_volume} 手续费: {trade.commission}\n") # type: ignore
|
print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 上涨 卖单已成交 订单ID: {self.tradeTarget.current_order_no} Price: {sfgrid_constants.grid_price[int(self.tradeTarget.grid_index)]} Volume: {sfgrid_constants.grid_volume} 手续费: {trade.commission}\n") # type: ignore
|
||||||
print(f' 成交价: {trade.traded_price} 成交量: {trade.traded_volume}')
|
print(f' 成交价: {trade.traded_price} 成交量: {trade.traded_volume}')
|
||||||
print(f' 当前持仓: {self.tradeTarget.current_position}')
|
print(f' 当前持仓: {self.tradeTarget.current_position}')
|
||||||
@@ -174,7 +177,6 @@ class SFGridStrategy:
|
|||||||
self.tradeTarget.current_position = int(self.tradeTarget.current_position) + trade.traded_volume # type: ignore
|
self.tradeTarget.current_position = int(self.tradeTarget.current_position) + trade.traded_volume # type: ignore
|
||||||
self.tradeTarget.last_trade_price = float(trade.traded_price) # type: ignore
|
self.tradeTarget.last_trade_price = float(trade.traded_price) # type: ignore
|
||||||
self.tradeTarget.grid_index = int(self.tradeTarget.grid_index) + 1 # type: ignore
|
self.tradeTarget.grid_index = int(self.tradeTarget.grid_index) + 1 # type: ignore
|
||||||
self.saveProxy()
|
|
||||||
print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 下跌 买单已成交 订单ID: {self.tradeTarget.current_order_no} Price: {trade.traded_price} Volume: {sfgrid_constants.grid_volume} 手续费: {trade.commission}")
|
print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 下跌 买单已成交 订单ID: {self.tradeTarget.current_order_no} Price: {trade.traded_price} Volume: {sfgrid_constants.grid_volume} 手续费: {trade.commission}")
|
||||||
print(f' 成交价: {trade.traded_price} 成交量: {trade.traded_volume}')
|
print(f' 成交价: {trade.traded_price} 成交量: {trade.traded_volume}')
|
||||||
print(f' 当前持仓: {self.tradeTarget.current_position}')
|
print(f' 当前持仓: {self.tradeTarget.current_position}')
|
||||||
@@ -183,10 +185,27 @@ class SFGridStrategy:
|
|||||||
# 打印订单信息和订单状态
|
# 打印订单信息和订单状态
|
||||||
print(f'|- 非策略内部订单,或订单状态不满足监控条件 {trade.order_id} {trade.stock_code}-{trade.instrument_name} {trade.commission}')
|
print(f'|- 非策略内部订单,或订单状态不满足监控条件 {trade.order_id} {trade.stock_code}-{trade.instrument_name} {trade.commission}')
|
||||||
finally:
|
finally:
|
||||||
|
self.refreshPlanPrice()
|
||||||
print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:release lock')
|
print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:release lock')
|
||||||
self.dataUpdateLock.release()
|
self.dataUpdateLock.release()
|
||||||
print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:END')
|
print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:END')
|
||||||
|
|
||||||
|
def refreshPlanPrice(self):
|
||||||
|
if self.tradeTarget.status == 1:
|
||||||
|
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(sfgrid_constants.grid_price[sellIdx]) # pyright: ignore[reportAttributeAccessIssue]
|
||||||
|
else:
|
||||||
|
self.tradeTarget.plan_sell_price = -1.0 # type: ignore
|
||||||
|
if self.tradeTarget.grid_index < len(sfgrid_constants.grid_price) - 1:
|
||||||
|
self.tradeTarget.plan_buy_price = float(sfgrid_constants.grid_price[buyIdx]) # pyright: ignore[reportAttributeAccessIssue]
|
||||||
|
else:
|
||||||
|
self.tradeTarget.plan_buy_price = -1.0 # pyright: ignore[reportAttributeAccessIssue]
|
||||||
|
else:
|
||||||
|
self.tradeTarget.plan_buy_price = 10.0 # type: ignore
|
||||||
|
self.tradeTarget.plan_sell_price = -1.0 # type: ignore
|
||||||
|
self.saveProxy()
|
||||||
|
|
||||||
def getName(self):
|
def getName(self):
|
||||||
return "SFGRID"
|
return "SFGRID"
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ class BaseModel(Model):
|
|||||||
OrderTypeBuy = f'{xtconstant.STOCK_BUY}' # 买
|
OrderTypeBuy = f'{xtconstant.STOCK_BUY}' # 买
|
||||||
OrderTypeSell = f'{xtconstant.STOCK_SELL}' # 卖
|
OrderTypeSell = f'{xtconstant.STOCK_SELL}' # 卖
|
||||||
OrderTypeInit = "0" # 建仓
|
OrderTypeInit = "0" # 建仓
|
||||||
OrderTypeNone = "None" # 建仓
|
OrderTypeNone = "None"
|
||||||
|
|
||||||
# 定义Target类,对应targets表
|
# 定义Target类,对应targets表
|
||||||
class TradeTarget(BaseModel):
|
class TradeTarget(BaseModel):
|
||||||
|
|||||||
+33
-32
@@ -3,7 +3,8 @@ from tkinter import ttk, messagebox, filedialog
|
|||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
import threading
|
import threading
|
||||||
import time
|
import time
|
||||||
from core.eventbus import ActionDisableMarketData, ActionEnableMarketData, ActionEventDeleteTradeTarget, ActionEventDisableTrade, ActionEventEnableTrade, MarketDataUpdate, MarketDataEnabled, MarketDataDisabled, ResultEventTradeDisabled, ResultEventTradeEnabled, ResultEventTradeTargetDeleted, event_bus
|
import core.eventbus as eBus
|
||||||
|
from core.logger import LogData, LogLevel
|
||||||
from core.strategy_db import TradeTarget
|
from core.strategy_db import TradeTarget
|
||||||
import configparser
|
import configparser
|
||||||
import sfgrid_constants
|
import sfgrid_constants
|
||||||
@@ -28,12 +29,13 @@ class TradeTargetUI:
|
|||||||
# 不再自动启动刷新线程,由市场数据开关控制
|
# 不再自动启动刷新线程,由市场数据开关控制
|
||||||
|
|
||||||
def registerEventHandler(self):
|
def registerEventHandler(self):
|
||||||
event_bus.subscribe(MarketDataUpdate, self.onTradeTargetUpdated)
|
eBus.event_bus.subscribe(eBus.MarketDataUpdate, self.onTradeTargetUpdated)
|
||||||
event_bus.subscribe(ResultEventTradeEnabled, self.onTradeEnabled)
|
eBus.event_bus.subscribe(eBus.ResultEventTradeEnabled, self.onTradeEnabled)
|
||||||
event_bus.subscribe(ResultEventTradeDisabled, self.onTradeDisabled)
|
eBus.event_bus.subscribe(eBus.ResultEventTradeDisabled, self.onTradeDisabled)
|
||||||
event_bus.subscribe(MarketDataEnabled, self.onMarketDataToggled)
|
eBus.event_bus.subscribe(eBus.MarketDataEnabled, self.onMarketDataToggled)
|
||||||
event_bus.subscribe(MarketDataDisabled, self.onMarketDataToggled)
|
eBus.event_bus.subscribe(eBus.MarketDataDisabled, self.onMarketDataToggled)
|
||||||
event_bus.subscribe(ResultEventTradeTargetDeleted, self.onTradeTargetDeleted)
|
eBus.event_bus.subscribe(eBus.ResultEventTradeTargetDeleted, self.onTradeTargetDeleted)
|
||||||
|
eBus.event_bus.subscribe(eBus.EventPrintLog, self.onLog)
|
||||||
|
|
||||||
def start_refresh_thread(self):
|
def start_refresh_thread(self):
|
||||||
"""启动刷新线程"""
|
"""启动刷新线程"""
|
||||||
@@ -59,11 +61,11 @@ class TradeTargetUI:
|
|||||||
if id in self.data:
|
if id in self.data:
|
||||||
del self.data[id]
|
del self.data[id]
|
||||||
# 添加日志
|
# 添加日志
|
||||||
self.add_log("INFO", f"交易标的已删除,ID: {id}")
|
self.add_log(LogLevel.INFO, f"交易标的已删除,ID: {id}")
|
||||||
|
|
||||||
def onMarketDataToggled(self, data:bool):
|
def onMarketDataToggled(self, data:bool):
|
||||||
self.market_data_enabled = self.market_data_switch_var.get()
|
self.market_data_enabled = self.market_data_switch_var.get()
|
||||||
self.add_log("INFO", "市场数据监听已" + ("启用" if data else "禁用"))
|
self.add_log(LogLevel.INFO, "市场数据监听已" + ("启用" if data else "禁用"))
|
||||||
# 同步UI刷新线程状态
|
# 同步UI刷新线程状态
|
||||||
if data:
|
if data:
|
||||||
self.start_ui_refresh()
|
self.start_ui_refresh()
|
||||||
@@ -71,10 +73,10 @@ class TradeTargetUI:
|
|||||||
self.stop_ui_refresh()
|
self.stop_ui_refresh()
|
||||||
|
|
||||||
def onTradeEnabled(self, target:TradeTarget):
|
def onTradeEnabled(self, target:TradeTarget):
|
||||||
self.add_log("INFO", f"交易启用: {target.stock_code} - {target.stock_name}")
|
self.add_log(LogLevel.INFO, f"交易启用: {target.stock_code} - {target.stock_name}")
|
||||||
|
|
||||||
def onTradeDisabled(self, target:TradeTarget):
|
def onTradeDisabled(self, target:TradeTarget):
|
||||||
self.add_log("INFO", f"交易禁用: {target.stock_code} - {target.stock_name}")
|
self.add_log(LogLevel.INFO, f"交易禁用: {target.stock_code} - {target.stock_name}")
|
||||||
|
|
||||||
|
|
||||||
def onTradeTargetUpdated(self, target: TradeTarget):
|
def onTradeTargetUpdated(self, target: TradeTarget):
|
||||||
@@ -137,11 +139,11 @@ class TradeTargetUI:
|
|||||||
print(f'市场数据监听开关')
|
print(f'市场数据监听开关')
|
||||||
self.market_data_enabled = self.market_data_switch_var.get()
|
self.market_data_enabled = self.market_data_switch_var.get()
|
||||||
if self.market_data_enabled:
|
if self.market_data_enabled:
|
||||||
event_bus.publish(ActionEnableMarketData, True)
|
eBus.event_bus.publish(eBus.ActionEnableMarketData, True)
|
||||||
# 同步开启UI刷新线程
|
# 同步开启UI刷新线程
|
||||||
self.start_ui_refresh()
|
self.start_ui_refresh()
|
||||||
else:
|
else:
|
||||||
event_bus.publish(ActionDisableMarketData, True)
|
eBus.event_bus.publish(eBus.ActionDisableMarketData, True)
|
||||||
# 同步关闭UI刷新线程
|
# 同步关闭UI刷新线程
|
||||||
self.stop_ui_refresh()
|
self.stop_ui_refresh()
|
||||||
|
|
||||||
@@ -150,14 +152,14 @@ class TradeTargetUI:
|
|||||||
if not self.refresh_thread_running:
|
if not self.refresh_thread_running:
|
||||||
self.refresh_thread_running = True
|
self.refresh_thread_running = True
|
||||||
self.start_refresh_thread()
|
self.start_refresh_thread()
|
||||||
self.add_log("INFO", "UI刷新线程已启动")
|
self.add_log(LogLevel.INFO, "UI刷新线程已启动")
|
||||||
|
|
||||||
def stop_ui_refresh(self):
|
def stop_ui_refresh(self):
|
||||||
"""停止UI刷新线程"""
|
"""停止UI刷新线程"""
|
||||||
if self.refresh_thread_running:
|
if self.refresh_thread_running:
|
||||||
self.stop_refresh_thread()
|
self.stop_refresh_thread()
|
||||||
self.refresh_thread_running = False
|
self.refresh_thread_running = False
|
||||||
self.add_log("INFO", "UI刷新线程已停止")
|
self.add_log(LogLevel.INFO, "UI刷新线程已停止")
|
||||||
|
|
||||||
def create_menu_bar(self):
|
def create_menu_bar(self):
|
||||||
"""创建菜单栏"""
|
"""创建菜单栏"""
|
||||||
@@ -330,7 +332,7 @@ class TradeTargetUI:
|
|||||||
if selected:
|
if selected:
|
||||||
item = selected[0]
|
item = selected[0]
|
||||||
values = self.trade_table.item(item)['values']
|
values = self.trade_table.item(item)['values']
|
||||||
self.add_log("DEBUG", f"双击查看详情: {values[0]} - {values[1]}")
|
self.add_log(LogLevel.DEBUG, f"双击查看详情: {values[0]} - {values[1]}")
|
||||||
|
|
||||||
def get_selected_target(self):
|
def get_selected_target(self):
|
||||||
"""获取选中的交易标的"""
|
"""获取选中的交易标的"""
|
||||||
@@ -351,10 +353,6 @@ class TradeTargetUI:
|
|||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def onLog(self, level: str, message: str):
|
|
||||||
"""接收外部日志消息并显示在日志组件中"""
|
|
||||||
self.add_log(level, message)
|
|
||||||
|
|
||||||
def start_selected_trade(self):
|
def start_selected_trade(self):
|
||||||
"""启动选中的交易"""
|
"""启动选中的交易"""
|
||||||
target = self.get_selected_target()
|
target = self.get_selected_target()
|
||||||
@@ -374,12 +372,12 @@ class TradeTargetUI:
|
|||||||
|
|
||||||
if result:
|
if result:
|
||||||
target.enabled = True # type: ignore
|
target.enabled = True # type: ignore
|
||||||
event_bus.publish(ActionEventEnableTrade, target.get_id())
|
eBus.event_bus.publish(eBus.ActionEventEnableTrade, target.get_id())
|
||||||
# self.add_log("INFO", f"已启动交易: {target.stock_code} - {target.stock_name}")
|
# self.add_log("INFO", f"已启动交易: {target.stock_code} - {target.stock_name}")
|
||||||
# messagebox.showinfo("启动成功", f"已启动 {target.stock_code} ({target.stock_name}) 的交易")
|
# messagebox.showinfo("启动成功", f"已启动 {target.stock_code} ({target.stock_name}) 的交易")
|
||||||
|
|
||||||
def on_trade_enabled(self, target: TradeTarget):
|
def on_trade_enabled(self, target: TradeTarget):
|
||||||
event_bus.publish(ActionEventEnableTrade, target)
|
eBus.event_bus.publish(eBus.ActionEventEnableTrade, target)
|
||||||
|
|
||||||
def pause_selected_trade(self):
|
def pause_selected_trade(self):
|
||||||
"""暂停选中的交易"""
|
"""暂停选中的交易"""
|
||||||
@@ -400,7 +398,7 @@ class TradeTargetUI:
|
|||||||
|
|
||||||
if result:
|
if result:
|
||||||
target.enabled = False # type: ignore
|
target.enabled = False # type: ignore
|
||||||
event_bus.publish(ActionEventDisableTrade, target.get_id())
|
eBus.event_bus.publish(eBus.ActionEventDisableTrade, target.get_id())
|
||||||
# self.add_log("INFO", f"已暂停交易: {target.stock_code} - {target.stock_name}")
|
# self.add_log("INFO", f"已暂停交易: {target.stock_code} - {target.stock_name}")
|
||||||
# messagebox.showinfo("暂停成功", f"已暂停 {target.stock_code} ({target.stock_name}) 的交易")
|
# messagebox.showinfo("暂停成功", f"已暂停 {target.stock_code} ({target.stock_name}) 的交易")
|
||||||
|
|
||||||
@@ -421,8 +419,8 @@ class TradeTargetUI:
|
|||||||
|
|
||||||
if result:
|
if result:
|
||||||
# 通过事件总线发出删除动作
|
# 通过事件总线发出删除动作
|
||||||
event_bus.publish(ActionEventDeleteTradeTarget, target.get_id())
|
eBus.event_bus.publish(eBus.ActionEventDeleteTradeTarget, target.get_id())
|
||||||
self.add_log("INFO", f"已发送删除请求: {target.stock_code} - {target.stock_name}")
|
self.add_log(LogLevel.INFO, f"已发送删除请求: {target.stock_code} - {target.stock_name}")
|
||||||
|
|
||||||
def add_trade_target(self):
|
def add_trade_target(self):
|
||||||
"""添加新的交易标的"""
|
"""添加新的交易标的"""
|
||||||
@@ -463,7 +461,7 @@ class TradeTargetUI:
|
|||||||
return
|
return
|
||||||
|
|
||||||
# 发布事件通知主控制器添加标的
|
# 发布事件通知主控制器添加标的
|
||||||
event_bus.publish("add_trade_target", stock_code)
|
eBus.event_bus.publish(eBus.ActionEventAddTradeTarget, stock_code)
|
||||||
add_window.destroy()
|
add_window.destroy()
|
||||||
|
|
||||||
def cancel_add():
|
def cancel_add():
|
||||||
@@ -476,7 +474,7 @@ class TradeTargetUI:
|
|||||||
# 绑定回车键确认
|
# 绑定回车键确认
|
||||||
stock_code_entry.bind('<Return>', lambda event: confirm_add())
|
stock_code_entry.bind('<Return>', lambda event: confirm_add())
|
||||||
|
|
||||||
self.add_log("INFO", "点击添加交易标的按钮")
|
self.add_log(LogLevel.INFO, "点击添加交易标的按钮")
|
||||||
|
|
||||||
def toggle_log_panel(self):
|
def toggle_log_panel(self):
|
||||||
"""切换日志面板的显示/隐藏"""
|
"""切换日志面板的显示/隐藏"""
|
||||||
@@ -515,17 +513,20 @@ class TradeTargetUI:
|
|||||||
if values and values[0] in selected_values:
|
if values and values[0] in selected_values:
|
||||||
self.trade_table.selection_add(item)
|
self.trade_table.selection_add(item)
|
||||||
|
|
||||||
def add_log(self, level, message):
|
def onLog(self, data:LogData):
|
||||||
|
self.add_log(data.level, data.message)
|
||||||
|
|
||||||
|
def add_log(self, level:LogLevel, message):
|
||||||
"""添加日志记录"""
|
"""添加日志记录"""
|
||||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
||||||
self.log_table.insert('', 0, values=(timestamp, level, message))
|
self.log_table.insert('', 0, values=(timestamp, level.value, message))
|
||||||
|
|
||||||
def clear_logs(self):
|
def clear_logs(self):
|
||||||
"""清空日志记录"""
|
"""清空日志记录"""
|
||||||
# 删除所有日志项
|
# 删除所有日志项
|
||||||
for item in self.log_table.get_children():
|
for item in self.log_table.get_children():
|
||||||
self.log_table.delete(item)
|
self.log_table.delete(item)
|
||||||
self.add_log("INFO", "日志已清空")
|
self.add_log(LogLevel.DEBUG, "日志已清空")
|
||||||
|
|
||||||
def system_settings(self):
|
def system_settings(self):
|
||||||
"""系统设置"""
|
"""系统设置"""
|
||||||
@@ -813,12 +814,12 @@ class TradeTargetUI:
|
|||||||
sfgrid_constants.initConfig()
|
sfgrid_constants.initConfig()
|
||||||
|
|
||||||
messagebox.showinfo("成功", f"配置已保存!\n网格价格序列: {grid_price_str}\n部分配置可能需要重启程序后生效。")
|
messagebox.showinfo("成功", f"配置已保存!\n网格价格序列: {grid_price_str}\n部分配置可能需要重启程序后生效。")
|
||||||
self.add_log("INFO", f"系统配置已更新 - 网格数量: {len(grid_prices)}")
|
self.add_log(LogLevel.INFO, f"系统配置已更新 - 网格数量: {len(grid_prices)}")
|
||||||
settings_window.destroy()
|
settings_window.destroy()
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
messagebox.showerror("错误", f"保存配置失败:{str(e)}")
|
messagebox.showerror("错误", f"保存配置失败:{str(e)}")
|
||||||
self.add_log("ERROR", f"保存配置失败: {str(e)}")
|
self.add_log(LogLevel.ERROR, f"保存配置失败: {str(e)}")
|
||||||
|
|
||||||
def cancel_settings():
|
def cancel_settings():
|
||||||
"""取消设置"""
|
"""取消设置"""
|
||||||
|
|||||||
BIN
Binary file not shown.
@@ -16,12 +16,7 @@ def initConfig():
|
|||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
config.read('config.ini')
|
config.read('config.ini')
|
||||||
miniQMTPath = config.get('config','miniQMTPath')
|
miniQMTPath = config.get('config','miniQMTPath')
|
||||||
print(f'QMTPath: {miniQMTPath}')
|
|
||||||
str_list = config.get('config','grid_price').split(',')
|
str_list = config.get('config','grid_price').split(',')
|
||||||
grid_price = [float(item) for item in str_list]
|
grid_price = [float(item) for item in str_list]
|
||||||
print(f'网格设置:{grid_price}')
|
|
||||||
grid_volume = config.getint('config','grid_volume')
|
grid_volume = config.getint('config','grid_volume')
|
||||||
# account_no = config.get('config','account_no')
|
|
||||||
print(f'账号: {account_no}')
|
|
||||||
max_enabled_targets = config.getint('config','max_enabled_targets')
|
max_enabled_targets = config.getint('config','max_enabled_targets')
|
||||||
print(f'最大启用目标数: {max_enabled_targets}')
|
|
||||||
|
|||||||
+2
-3
@@ -1,6 +1,7 @@
|
|||||||
# coding:utf-8
|
# coding:utf-8
|
||||||
from core import strategy_db
|
from core import strategy_db
|
||||||
from core.main_controller import SFGridController
|
from core.main_controller import SFGridController
|
||||||
|
from core.logger import LogLevel, PrintLog
|
||||||
import sfgrid_constants as sdConstants
|
import sfgrid_constants as sdConstants
|
||||||
|
|
||||||
def startTrade(index: int):
|
def startTrade(index: int):
|
||||||
@@ -13,9 +14,7 @@ if __name__ == '__main__':
|
|||||||
sdConstants.initConfig()
|
sdConstants.initConfig()
|
||||||
strategy_db.db.connect()
|
strategy_db.db.connect()
|
||||||
strategy_db.db.create_tables([strategy_db.TradeTarget])
|
strategy_db.db.create_tables([strategy_db.TradeTarget])
|
||||||
print('- [成功]数据库模块初始化')
|
PrintLog(LogLevel.INFO, '- [成功]数据库模块初始化')
|
||||||
|
|
||||||
print(f'{sdConstants.account_no} : {sdConstants.miniQMTPath}')
|
|
||||||
ctrl: SFGridController = SFGridController(sdConstants.account_no, sdConstants.miniQMTPath)
|
ctrl: SFGridController = SFGridController(sdConstants.account_no, sdConstants.miniQMTPath)
|
||||||
|
|
||||||
ctrl.hold()
|
ctrl.hold()
|
||||||
|
|||||||
Reference in New Issue
Block a user