update for restructure

This commit is contained in:
2025-11-11 12:15:40 +08:00
parent 7cfb433aaf
commit c42648d1b4
15 changed files with 880 additions and 306 deletions
+402
View File
@@ -0,0 +1,402 @@
# coding:utf-8
from core.sfgrid.model import TradeTarget
from core.eventbus import ActionDisableMarketData, ActionEnableMarketData, ActionEventAddTradeTarget, ActionEventDeleteTradeTarget, ActionEventDisableTrade, ActionEventEnableTrade, EventTradeTargetUpdate, MarketDataUpdate, MarketDataEnabled, MarketDataDisabled, ResultEventTradeDisabled, ResultEventTradeEnabled, ResultEventTradeTargetDeleted, ActionEventGridFix, event_bus
from xtquant.xttrader import XtQuantTrader
import time
from peewee import ModelSelect
import core.sfgrid.model as model
import sfgrid_config
from core.sfgrid.sfgrid_strategy import SFGridStrategy
from core.util import getInstrumentName, getStockPosition, queryPendingOrder
from xtquant.xttrader import XtQuantTrader
from xtquant.xttype import StockAccount, XtAsset, XtOrder, XtPosition, XtTrade
from xtquant import xtdata
from xtquant.xttrader import XtQuantTraderCallback
import datetime
import core.sfgrid.ui as ui
from core.logger import PrintLog, LogLevel
from core.sfgrid.objects import GridFixData
# 量化核心控制对象
class SFGridController(XtQuantTraderCallback):
def __init__(self, account_no: str, miniQmtPath: str):
super().__init__()
self.registerEventHandler()
self.appUi = ui.TradeTargetUI()
xtdata.enable_hello = False
session_id = int(time.time())
self.xt_trader: XtQuantTrader = XtQuantTrader(miniQmtPath, session_id)
self.xt_trader.register_callback(self)
self.xt_trader.start()
self.xt_trader.connect()
PrintLog(LogLevel.INFO, f'- [{'成功' if self.xt_trader.connected else '失败'}]市场交易连接: {miniQmtPath}')
if self.xt_trader.connected == False:
self.inited: bool = False
return
else:
self.inited = True
self.account= StockAccount(account_no, 'STOCK')
PrintLog(LogLevel.INFO, f'- [成功]交易账号对象初始化完成, 账号: {self.account.account_id}') # pyright: ignore[reportAttributeAccessIssue]
subscribe_result = self.xt_trader.subscribe(self.account)
PrintLog(LogLevel.INFO, f'- [{'成功' if subscribe_result == 0 else '失败'}:{subscribe_result}]交易状态订阅')
if subscribe_result == 0:
self.inited = True
else:
self.inited = False
return
self.listening_stock = []
self.stock_trade_ctrl = {}
self.init_instrument_pool(self.xt_trader, self.account) # type: ignore
self.seq = None
PrintLog(LogLevel.INFO, '- [成功]三疯交易系统初始化完成')
self.startMarketData()
def registerEventHandler(self):
event_bus.subscribe(ActionEventEnableTrade, self.onEnableTrade)
event_bus.subscribe(ActionEventDisableTrade, self.onDisableTrade)
event_bus.subscribe(ActionEnableMarketData, self.onMarketDataEnabled)
event_bus.subscribe(ActionDisableMarketData, self.onMarketDataDisabled)
event_bus.subscribe(ActionEventAddTradeTarget, self.onAddTradeTarget)
event_bus.subscribe(ActionEventDeleteTradeTarget, self.onDeleteTradeTarget)
event_bus.subscribe(ActionEventGridFix, self.onGridFix)
def onDeleteTradeTarget(self, id: int):
"""处理删除交易标的事件"""
self.del_trade_target(id)
# 发布删除完成事件
event_bus.publish(ResultEventTradeTargetDeleted, id)
def onAddTradeTarget(self, stock_code: str):
"""处理添加交易标的事件"""
self.add_trade_target(stock_code)
def onMarketDataEnabled(self, data):
"""处理市场数据监听启用事件"""
self.startMarketData()
def onMarketDataDisabled(self, data):
"""处理市场数据监听禁用事件"""
self.stopMarketData()
def onEnableTrade(self, id: int):
self.start_stock_trade(id)
def onDisableTrade(self, id: int):
self.pause_stock_trade(id)
def onGridFix(self, data: GridFixData):
"""处理网格修正事件"""
self.update_trade_target_grid(data)
def update_trade_target_grid(self, data: GridFixData):
"""更新交易标的网格信息"""
try:
target = data.tradeTarget
grid_index = data.grid_index
# 更新数据库中的网格索引
target.grid_index = grid_index
target.save()
# 更新内存中的交易标的
if target.get_id() in self.instrument_pool:
self.instrument_pool[target.get_id()] = target
# 更新交易控制器中的网格信息
if target.stock_code in self.stock_trade_ctrl:
trade_controller: SFGridStrategy = self.stock_trade_ctrl[target.stock_code]
trade_controller.updateGridIndex(grid_index) # type: ignore
PrintLog(LogLevel.INFO, f"网格修正已应用: {target.stock_code} - {target.stock_name}, 网格索引: {grid_index}")
except Exception as e:
PrintLog(LogLevel.ERROR, f"网格修正更新失败: {str(e)}")
def hold(self):
self.appUi.run()
def startMarketData(self):
PrintLog(LogLevel.INFO, '- 启动市场数据订阅')
self.seq = xtdata.subscribe_whole_quote(['SH', 'SZ'], callback=self.onDataUpdate)
if self.seq == -1:
PrintLog(LogLevel.ERROR, '- 市场数据订阅失败')
else:
event_bus.publish(MarketDataEnabled, True)
PrintLog(LogLevel.INFO, f'- 市场数据订阅成功, 订阅号={self.seq}')
def stopMarketData(self):
PrintLog(LogLevel.INFO, '- 停止市场数据订阅')
if self.seq is not None and self.seq > 0:
xtdata.unsubscribe_quote(self.seq)
event_bus.publish(MarketDataDisabled, False)
def add_trade_target(self, stock_code: str):
try:
stock_name = getInstrumentName(stock_code)
if not stock_name:
PrintLog(LogLevel.ERROR, f'无法获取股票代码 {stock_code} 的名称,请检查代码是否正确')
return
# 检查是否已存在该标的
existing_target = model.TradeTarget.get_or_none(model.TradeTarget.stock_code == stock_code)
if existing_target:
PrintLog(LogLevel.INFO, f'交易标的 {stock_code} {stock_name} 已存在')
return
new_target = model.TradeTarget.create(
stock_name=stock_name,
stock_code=stock_code,
market_price=0.0,
current_position=0,
grid_index=0,
last_trade_price=0.0,
plan_buy_price=0.0,
plan_sell_price=0.0,
current_order_price=0.0,
current_order_no='',
current_order_type=''
)
new_target.save()
PrintLog(LogLevel.INFO, f'新增交易标的 {stock_code} {stock_name}, {new_target.id}')
# 刷新标的持仓
pos = getStockPosition(stock_code, self.xt_trader, self.account) # type: ignore
model.TradeTarget.update(current_position=pos).where(model.TradeTarget.stock_code == stock_code).execute()
# 更新标的池
self.refresh_targets()
# 添加交易控制器
stockTradeController = SFGridStrategy(new_target, self.xt_trader, self.account) # type: ignore
self.stock_trade_ctrl[stock_code] = stockTradeController
except Exception as e:
PrintLog(LogLevel.ERROR, f'新增交易标的失败 {stock_code} {e}')
def del_trade_target(self, id:int):
try:
# 检查标的是否存在
if id not in self.instrument_pool:
PrintLog(LogLevel.ERROR, f"交易标的 ID {id} 不存在")
return
target: model.TradeTarget = self.instrument_pool[id]
# 如果存在交易控制器,先停止交易
if target.stock_code in self.stock_trade_ctrl:
# 停止交易控制器
del self.stock_trade_ctrl[target.stock_code]
# 从数据库中删除
target.delete_instance()
# 从内存中删除
del self.instrument_pool[id]
# 刷新标的池
self.refresh_targets()
PrintLog(LogLevel.INFO, f"已删除交易标的: {target.stock_code} - {target.stock_name}")
except Exception as e:
PrintLog(LogLevel.ERROR, f"删除交易标的失败 ID {id}: {str(e)}")
def init_instrument_pool(self, xtTrader:XtQuantTrader, account:StockAccount):
self.refresh_targets()
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_config.grid_price[target.grid_index]} 状态: {status} 启用交易线程: {'自动交易中' if target.enabled else '交易已停止'}') # type: ignore
tradeTarget:model.TradeTarget = self.instrument_pool[id]
tradeTarget.current_position = getStockPosition(tradeTarget.stock_code, xtTrader, account) # type: ignore
result = tradeTarget.save()
PrintLog(LogLevel.INFO, f' |- 同步[{target.stock_code}-{target.stock_name}]持仓信息[{'成功' if result == 1 else '失败'}]')
stockTradeController = SFGridStrategy(tradeTarget, self.xt_trader, self.account) # type: ignore
self.stock_trade_ctrl[tradeTarget.stock_code] = stockTradeController
event_bus.publish(EventTradeTargetUpdate, tradeTarget)
PrintLog(LogLevel.INFO, f'- [成功]交易标的信息初始化, 共 {len(self.instrument_pool)} 个标的')
def refresh_targets(self):
# 更新标的池
results:ModelSelect = model.TradeTarget.select()
self.instrument_pool: dict[int, model.TradeTarget] = {}
for temp in results:
result :model.TradeTarget = temp
self.instrument_pool[result.get_id()] = result
def print_position_info(self):
positions:list[XtPosition] = self.xt_trader.query_stock_positions(self.account)
if positions:
PrintLog(LogLevel.INFO, "\n- 持仓信息")
for temp in positions:
pos : XtPosition = temp
if pos.volume <=0:
continue
PrintLog(LogLevel.INFO, f"股票代码: {pos.stock_code}-{getInstrumentName(pos.stock_code)}")
PrintLog(LogLevel.INFO, f"总持仓: {pos.volume}")
PrintLog(LogLevel.INFO, f"可用持仓: {pos.can_use_volume}")
PrintLog(LogLevel.INFO, f"持仓成本: {pos.avg_price}")
PrintLog(LogLevel.INFO, "---")
else:
PrintLog(LogLevel.INFO, "\n当前无持仓")
def print_account_info(self):
temp = self.xt_trader.query_stock_asset(self.account)
asset: XtAsset = temp # type: ignore
PrintLog(LogLevel.INFO, f"=== 账户信息 {self.account.account_id} ===") # type: ignore
PrintLog(LogLevel.INFO, f"可用资金: {asset.cash}")
PrintLog(LogLevel.INFO, f"总资产: {asset.total_asset}")
PrintLog(LogLevel.INFO, f"证券市值: {asset.market_value}")
def print_stock_orders(self):
orders = self.xt_trader.query_stock_orders(self.account, cancelable_only=True)
if orders:
PrintLog(LogLevel.INFO, "\n=== 委托信息 ===")
for order in orders:
PrintLog(LogLevel.INFO, f"委托编号: {order.order_id}")
PrintLog(LogLevel.INFO, f"股票代码: {order.stock_code} {getInstrumentName(order.stock_code)}")
PrintLog(LogLevel.INFO, f"委托方向: {order.offset_flag} ")
PrintLog(LogLevel.INFO, f"委托价格: {order.price}")
PrintLog(LogLevel.INFO, f"委托数量: {order.order_volume}")
PrintLog(LogLevel.INFO, f"已成交数量: {order.traded_volume}")
PrintLog(LogLevel.INFO, f"委托状态: {order.order_status} ")
PrintLog(LogLevel.INFO, "---")
else:
PrintLog(LogLevel.INFO, "\n当前无委托记录")
# 初始化指定标的交易控制器
def start_stock_trade(self, id: int):
tradeTarget: TradeTarget = self.instrument_pool[id]
# check existing thread
if tradeTarget.stock_code in self.stock_trade_ctrl:
tradeController: SFGridStrategy = self.stock_trade_ctrl[tradeTarget.stock_code]
tradeTarget = tradeController.enabledTrading(True)
self.instrument_pool[id] = tradeTarget
event_bus.publish(ResultEventTradeEnabled, tradeTarget)
else:
PrintLog(LogLevel.INFO, f"\t创建标的交易控制器 {tradeTarget.stock_code} {getInstrumentName(tradeTarget.stock_code)}")
def pause_stock_trade(self, id: int):
localTarget: model.TradeTarget = self.instrument_pool[id]
print(f'暂停标的交易 {localTarget.stock_code} - enabled {localTarget.enabled}')
if localTarget.stock_code in self.stock_trade_ctrl:
tradeController: SFGridStrategy = self.stock_trade_ctrl[localTarget.stock_code]
tradeTarget = tradeController.enabledTrading(False)
orders = queryPendingOrder(localTarget.stock_code, tradeController.getName(), self.xt_trader, self.account) # type: ignore
for order in orders:
self.xt_trader.cancel_order_stock_async(self.account, order.order_id)
print(f'取消未成交订单 {len(orders)}')
self.instrument_pool[id] = tradeTarget
event_bus.publish(ResultEventTradeDisabled, tradeTarget)
else:
print(f"标的交易控制器不存在 {localTarget.stock_code} {localTarget.stock_name}\n")
# ====== 市场回调方法 -- 以下方法由XtQuantData调用 ======
def onDataUpdate(self, data):
# 收集所有市场数据用于市场监控
for stock_code, tickData in data.items():
if stock_code in self.stock_trade_ctrl:
stock_controller: SFGridStrategy = self.stock_trade_ctrl[stock_code]
stock_controller.onDataUpdate(data)
else:
# 非目标交易,发布市场数据更新事件用于市场监控
lastPrice = tickData['lastPrice']
if lastPrice == 10 or stock_code in self.listening_stock:
# 发布市场数据更新事件用于市场监控
market_target = TradeTarget()
market_target.stock_code = stock_code
market_target.stock_name = getInstrumentName(stock_code) # type: ignore
market_target.market_price = lastPrice # type: ignore
event_bus.publish(MarketDataUpdate, market_target)
if stock_code not in self.listening_stock:
self.listening_stock.append(stock_code)
# ====== 市场回调方法 -- 以下方法由XtQuantTrader调用 ======
def on_connected(self):
"""
连接成功推送
"""
print(datetime.datetime.now(), '连接成功回调')
def on_disconnected(self):
"""
连接断开
:return:
"""
print(datetime.datetime.now(), '连接断开回调')
def on_stock_order(self, order:XtOrder):
"""
委托回报推送
:param order: XtOrder对象
:return:
"""
print(f'orderd {order.strategy_name}-{order.stock_code} {order.order_id} {order.order_volume}-{order.order_status}')
stockCode = order.stock_code
ctrl:SFGridStrategy = self.stock_trade_ctrl[stockCode]
# 如果存在对应的StockTradeController,则调用其onDataUpdate方法
if ctrl is not None and order.strategy_name == ctrl.getName():
print(f'controller info {ctrl.getName()}')
ctrl.onAsyncOrderResponse(order) # type: ignore
else:
print(f"委托下单回调 投资备注 orderId: {order.order_sysid} [{order.stock_code}-{order.instrument_name}] volume: {order.order_volume} 订单策略: '{order.strategy_name}'<-->'{ctrl.getName()}'")
def on_stock_trade(self, trade:XtTrade):
"""
成交变动推送
:param trade: XtTrade对象
:return:
"""
stockCode = trade.stock_code
ctrl:SFGridStrategy = self.stock_trade_ctrl[stockCode]
# 如果存在对应的StockTradeController,则调用其onDataUpdate方法
if ctrl is not None and trade.strategy_name == ctrl.getName():
ctrl.onOrderTrade(trade)
else:
print(f"委托回调 投资备注 {trade.strategy_name} 不匹配 {ctrl.getName()}")
# def on_order_stock_async_response(self, response:XtOrderResponse):
# stockCode = response.order_remark
# ctrl:SFGridStrategy = self.stock_trade_ctrl[stockCode]
# # 如果存在对应的StockTradeController,则调用其onDataUpdate方法
# if ctrl is not None and response.strategy_name == ctrl.getName():
# ctrl.onAsyncOrderResponse(response)
# else:
# print(f"委托回调 投资备注 {response.strategy_name} 不匹配 {ctrl.getName()}")
def on_order_error(self, order_error):
"""
委托失败推送
:param order_error:XtOrderError 对象
:return:
"""
# print("on order_error callback")
# print(order_error.order_id, order_error.error_id, order_error.error_msg)
print(f"\n委托报错回调 {order_error.order_remark} {order_error.error_msg}")
def on_account_status(self, status):
"""
:param response: XtAccountStatus 对象
:return:
"""
print(datetime.datetime.now(), status)
+26
View File
@@ -0,0 +1,26 @@
from peewee import CharField, IntegerField, FloatField, BooleanField
from core.database import BaseModel, db
# 定义Target类,对应targets表
class TradeTarget(BaseModel):
stock_code = CharField(unique=True)
stock_name = CharField()
market_price = FloatField()
current_position = IntegerField()
grid_index = IntegerField()
last_trade_price = FloatField()
plan_buy_price = FloatField()
plan_sell_price = FloatField()
current_order_price = FloatField()
current_order_no = CharField(default='')
current_order_type = CharField(default='')
status = IntegerField(default=0) # 0表示新标的,1表示已建初始仓,正常交易中
enabled = BooleanField(default=False) # 是否启动交易线程
def targetName(self):
return f'{self.stock_name}[{self.stock_code}]'
db.create_tables([TradeTarget])
+7
View File
@@ -0,0 +1,7 @@
from core.sfgrid.model import TradeTarget
class GridFixData:
def __init__(self, grid_index, tradeTarget:TradeTarget):
self.grid_index = grid_index
self.tradeTarget = tradeTarget
+223
View File
@@ -0,0 +1,223 @@
import core.sfgrid.model as model
from core import constants
from core.eventbus import EventTradeTargetUpdate, event_bus
from core.constants import OrderTypeBuy, OrderTypeInit, OrderTypeSell
from core.util import queryPendingOrder, is_trading_time
from xtquant import xttrader, xtconstant
from xtquant.xttype import StockAccount, XtOrder, XtTrade
import sfgrid_config
import threading
class SFGridStrategy:
def __init__(self, tradeTarget: model.TradeTarget, xt_trader: xttrader.XtQuantTrader, account: StockAccount):
self.tradeTarget:model.TradeTarget = tradeTarget
self.xt_trader: xttrader.XtQuantTrader = xt_trader
self.account:StockAccount = account
self.enabledTrading(bool(tradeTarget.enabled)) # 修复类型兼容性问题
event_bus.publish(EventTradeTargetUpdate, self.tradeTarget)
self.dataUpdateLock = threading.Lock()
def updateGridIndex(self, grid_index: int):
"""更新网格索引"""
self.tradeTarget.grid_index = grid_index # type: ignore
self.refreshPlanPrice()
self.saveProxy()
def enabledTrading(self, enabled: bool) -> model.TradeTarget:
self.tradeTarget.enabled = enabled # type: ignore
self.saveProxy()
if enabled:
self.refreshPlanPrice()
print(f" |- 标的{self.tradeTarget.targetName()}交易启动, 持仓量:{self.tradeTarget.current_position}")
if self.tradeTarget.status == 0: # 未建仓
print(f" |- 标的{self.tradeTarget.targetName()}初始状态, 设置网格序号 1")
self.tradeTarget.grid_index = 1 # pyright: ignore[reportAttributeAccessIssue]
else: # 已建仓
# 交易阶段,检查仓位,检查现有订单
print(f" |- 标的{self.tradeTarget.targetName()}已有仓位或非初始状态 无需建初始仓 当前仓位: {self.tradeTarget.current_position} 状态: {self.tradeTarget.status}")
minRequirePosition:int = sfgrid_config.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:
print(f' |- 仓位检查: 持仓需求不足, (gridVolume*gridIndex)={minRequirePosition}, 当前持仓:{self.tradeTarget.current_position}, 交易启动失败')
self.tradeTarget.enabled = False # type: ignore
self.saveProxy()
else:
print(f" |- 标的{self.tradeTarget.targetName()}交易监控暂停")
return self.tradeTarget
def isEnabled(self) -> bool:
print(f'|- 检查交易状态[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - {self.tradeTarget.enabled}')
return bool(self.tradeTarget.enabled) # 修复返回类型问题
def onDataUpdate(self, data):
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - START')
lastPrice = float("{:.3f}".format(data[self.tradeTarget.stock_code]['lastPrice']))
self.tradeTarget.market_price = lastPrice # type: ignore
self.saveProxy()
if not is_trading_time():
print(f"|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 非交易时间,不进行自动交易")
return
if not self.tradeTarget.enabled: # 未建仓,自动交易暂停
print(f"|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - 未建仓或交易监控暂停,不进行自动交易")
return
self.dataUpdateLock.acquire()
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - LOCKED')
try:
orderPrice:float = -1
orderType = -1
index: int = self.tradeTarget.grid_index # pyright: ignore[reportAssignmentType]
orderRemark= ""
gridBasePrice = -1 if index>=len(sfgrid_config.grid_price) or index < 0 else sfgrid_config.grid_price[int(index)] # pyright: ignore[reportArgumentType]
if self.tradeTarget.enabled and self.tradeTarget.status == 0 and lastPrice <= sfgrid_config.grid_price[1]: # 已启用,未建仓,建仓
orderPrice = sfgrid_config.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_config.grid_price) else sfgrid_config.grid_price[int(index) + 1] # pyright: ignore[reportArgumentType]
highPrice = sfgrid_config.grid_price[index - 1]
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)
if len([order for order in orders if order.order_type == orderType and order.price == orderPrice]) > 0:
# 已存在未交易的多单
print(f' |- [{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}]已存在未交易的{"多单" if orderType == xtconstant.STOCK_BUY else "空单"},不重复下单')
else:
print(f' |- 下网格{"多单" if orderType == xtconstant.STOCK_BUY else "空单"}')
self.tradeTarget.current_order_no = self.xt_trader.order_stock_async(
self.account,
str(self.tradeTarget.stock_code),
orderType,
sfgrid_config.grid_volume,
xtconstant.FIX_PRICE,
orderPrice,
self.getName(), # strategy_name
orderRemark # remark # type: ignore
)
orderTypeName = ""
if orderRemark == OrderTypeBuy:
orderTypeName = "多单"
elif orderRemark == OrderTypeSell:
orderTypeName = "空单"
elif orderRemark == OrderTypeInit:
orderTypeName = "建仓单"
print(f' |- {orderTypeName}委托, 单号 {self.tradeTarget.current_order_no}, 网格基准价 {gridBasePrice}, 下单价 {orderPrice}, 下单量 {sfgrid_config.grid_volume}')
finally:
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - release lock')
self.saveProxy()
self.dataUpdateLock.release()
print(f'|- 市价更新[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}] - END')
def onAsyncOrderResponse(self, order:XtOrder):
print(f' |- 委托回调[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{order.order_id}]:START')
self.dataUpdateLock.acquire()
print(f' |- 委托回调[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{order.order_id}]:LOCKED')
try:
if order.strategy_name == self.getName():
self.tradeTarget.current_order_no = order.order_id
self.tradeTarget.current_order_type = order.order_remark
self.saveProxy()
else:
print(f' |- 委托回调[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{order.order_id}]: 不在策略监控范围内{order.strategy_name}')
finally:
print(f' |- 委托回调[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{order.order_id}]:release lock')
self.dataUpdateLock.release()
print(f' |- 委托回调[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{order.order_id}]:END')
def onOrderTrade(self, trade:XtTrade):
print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:START, {trade.order_id}')
self.dataUpdateLock.acquire()
print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:LOCKED')
try:
if not trade.strategy_name == self.getName():
print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]: 不在策略监控范围内{trade.strategy_name}')
return
if self.tradeTarget.status == 0 and trade.order_id == self.tradeTarget.current_order_no and trade.order_remark == constants.OrderTypeInit:
# 此时为建仓成交
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.grid_index = 1 # type: ignore
self.tradeTarget.plan_buy_price = float(sfgrid_config.grid_price[2]) # type: ignore
self.tradeTarget.plan_sell_price = float(sfgrid_config.grid_price[0]) # type: ignore
self.tradeTarget.status = 1 # type: ignore
self.saveProxy()
print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 建初始仓订单ID: {self.tradeTarget.current_order_no}已成交 ")
print(f' 成交价: {trade.traded_price} 成交量: {trade.traded_volume}')
print(f' 当前持仓: {self.tradeTarget.current_position}')
print(f' 网格坐标: {self.tradeTarget.grid_index}')
elif trade.order_id == self.tradeTarget.current_order_no and self.tradeTarget.status == 1 and trade.order_type == xtconstant.STOCK_SELL: # 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.grid_index = int(self.tradeTarget.grid_index) - 1 # type: ignore
print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 上涨 卖单已成交 订单ID: {self.tradeTarget.current_order_no} Price: {sfgrid_config.grid_price[int(self.tradeTarget.grid_index)]} Volume: {sfgrid_config.grid_volume} 手续费: {trade.commission}\n") # type: ignore
print(f' 成交价: {trade.traded_price} 成交量: {trade.traded_volume}')
print(f' 当前持仓: {self.tradeTarget.current_position}')
print(f' 网格坐标: {self.tradeTarget.grid_index}')
elif trade.order_id == self.tradeTarget.current_order_no and self.tradeTarget.status == 1 and trade.order_type == xtconstant.STOCK_BUY: # 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.grid_index = int(self.tradeTarget.grid_index) + 1 # type: ignore
print(f"|- 标的{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name} 下跌 买单已成交 订单ID: {self.tradeTarget.current_order_no} Price: {trade.traded_price} Volume: {sfgrid_config.grid_volume} 手续费: {trade.commission}")
print(f' 成交价: {trade.traded_price} 成交量: {trade.traded_volume}')
print(f' 当前持仓: {self.tradeTarget.current_position}')
print(f' 网格坐标: {self.tradeTarget.grid_index}')
else:
# 打印订单信息和订单状态
print(f'|- 非策略内部订单,或订单状态不满足监控条件 {trade.order_id} {trade.stock_code}-{trade.instrument_name} {trade.commission}')
finally:
self.refreshPlanPrice()
print(f' |- 委托成交通知[{self.tradeTarget.stock_code}-{self.tradeTarget.stock_name}-{trade.order_id}]:release lock')
self.dataUpdateLock.release()
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_config.grid_price[sellIdx]) # pyright: ignore[reportAttributeAccessIssue]
else:
self.tradeTarget.plan_sell_price = -1.0 # type: ignore
if self.tradeTarget.grid_index < len(sfgrid_config.grid_price) - 1:
self.tradeTarget.plan_buy_price = float(sfgrid_config.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):
return "SFGRID"
def saveProxy(self):
rc = self.tradeTarget.save()
event_bus.publish(EventTradeTargetUpdate, self.tradeTarget)
return rc
+1064
View File
File diff suppressed because it is too large Load Diff