[增强功能] 一般更新
This commit is contained in:
parent
08175de6d0
commit
3a086af423
@ -519,6 +519,8 @@ class AccountRecorder(BaseEngine):
|
|||||||
data = event.data
|
data = event.data
|
||||||
dt = data.get('datetime')
|
dt = data.get('datetime')
|
||||||
|
|
||||||
|
# db.today_strategy_pos.createIndex({'account_id':1,'strategy_group':1,'strategy_name':1,'date':1},{'name':'accountid_strategy_group_strategy_name_date'})
|
||||||
|
|
||||||
account_id = data.get('accountid')
|
account_id = data.get('accountid')
|
||||||
fld = {
|
fld = {
|
||||||
'account_id': account_id,
|
'account_id': account_id,
|
||||||
|
@ -859,7 +859,8 @@ class CtaEngine(BaseEngine):
|
|||||||
vt_symbol: str,
|
vt_symbol: str,
|
||||||
days: int,
|
days: int,
|
||||||
interval: Interval,
|
interval: Interval,
|
||||||
callback: Callable[[BarData], None]
|
callback: Callable[[BarData], None],
|
||||||
|
interval_num: int = 1
|
||||||
):
|
):
|
||||||
""""""
|
""""""
|
||||||
symbol, exchange = extract_vt_symbol(vt_symbol)
|
symbol, exchange = extract_vt_symbol(vt_symbol)
|
||||||
@ -875,6 +876,7 @@ class CtaEngine(BaseEngine):
|
|||||||
symbol=symbol,
|
symbol=symbol,
|
||||||
exchange=exchange,
|
exchange=exchange,
|
||||||
interval=interval,
|
interval=interval,
|
||||||
|
interval_num=interval_num,
|
||||||
start=start,
|
start=start,
|
||||||
end=end
|
end=end
|
||||||
)
|
)
|
||||||
|
@ -109,8 +109,15 @@ class CtaEngine(BaseEngine):
|
|||||||
"""
|
"""
|
||||||
super().__init__(main_engine, event_engine, APP_NAME)
|
super().__init__(main_engine, event_engine, APP_NAME)
|
||||||
|
|
||||||
|
# 股票引擎得配置,包括
|
||||||
|
# "accountid" : "xxxx", 资金账号,一般用于推送消息时附带
|
||||||
|
# "strategy_group": "cta_strategy_pro", # 当前实例名。多个实例时,区分开
|
||||||
|
# "trade_2_wx": true # 是否交易记录转发至微信通知
|
||||||
|
# "event_log: false # 是否转发日志到event bus,显示在图形界面
|
||||||
|
# "snapshot2file": false # 是否保存切片到文件
|
||||||
self.engine_config = {}
|
self.engine_config = {}
|
||||||
|
# 是否激活 write_log写入event bus(比较耗资源)
|
||||||
|
self.event_log = False
|
||||||
self.strategy_setting = {} # strategy_name: dict
|
self.strategy_setting = {} # strategy_name: dict
|
||||||
self.strategy_data = {} # strategy_name: dict
|
self.strategy_data = {} # strategy_name: dict
|
||||||
|
|
||||||
@ -222,8 +229,8 @@ class CtaEngine(BaseEngine):
|
|||||||
# 每5分钟检查一次
|
# 每5分钟检查一次
|
||||||
if dt.minute % 10 == 0:
|
if dt.minute % 10 == 0:
|
||||||
# 比对仓位,使用上述获取得持仓信息,不用重复获取
|
# 比对仓位,使用上述获取得持仓信息,不用重复获取
|
||||||
#self.compare_pos(strategy_pos_list=copy(all_strategy_pos))
|
self.compare_pos(strategy_pos_list=copy(all_strategy_pos))
|
||||||
pass
|
|
||||||
|
|
||||||
# 推送到事件
|
# 推送到事件
|
||||||
self.put_all_strategy_pos_event(all_strategy_pos)
|
self.put_all_strategy_pos_event(all_strategy_pos)
|
||||||
@ -1301,12 +1308,13 @@ class CtaEngine(BaseEngine):
|
|||||||
self.write_log(f'{strategy_name}返回得K线切片数据为空')
|
self.write_log(f'{strategy_name}返回得K线切片数据为空')
|
||||||
return
|
return
|
||||||
|
|
||||||
# 剩下工作:保存本地文件/数据库
|
if self.engine_config.get('snapshot2file', False):
|
||||||
snapshot_folder = get_folder_path(f'data/snapshots/{strategy_name}')
|
# 剩下工作:保存本地文件/数据库
|
||||||
snapshot_file = snapshot_folder.joinpath('{}.pkb2'.format(datetime.now().strftime('%Y%m%d_%H%M%S')))
|
snapshot_folder = get_folder_path(f'data/snapshots/{strategy_name}')
|
||||||
with bz2.BZ2File(str(snapshot_file), 'wb') as f:
|
snapshot_file = snapshot_folder.joinpath('{}.pkb2'.format(datetime.now().strftime('%Y%m%d_%H%M%S')))
|
||||||
pickle.dump(snapshot, f)
|
with bz2.BZ2File(str(snapshot_file), 'wb') as f:
|
||||||
self.write_log(u'切片保存成功:{}'.format(str(snapshot_file)))
|
pickle.dump(snapshot, f)
|
||||||
|
self.write_log(u'切片保存成功:{}'.format(str(snapshot_file)))
|
||||||
|
|
||||||
# 通过事件方式,传导到account_recorder
|
# 通过事件方式,传导到account_recorder
|
||||||
snapshot.update({
|
snapshot.update({
|
||||||
@ -1681,8 +1689,13 @@ class CtaEngine(BaseEngine):
|
|||||||
Load setting file.
|
Load setting file.
|
||||||
"""
|
"""
|
||||||
# 读取引擎得配置
|
# 读取引擎得配置
|
||||||
|
# "accountid" : "xxxx", 资金账号,一般用于推送消息时附带
|
||||||
|
# "strategy_group": "cta_strategy_pro", # 当前实例名。多个实例时,区分开
|
||||||
|
# "trade_2_wx": true # 是否交易记录转发至微信通知
|
||||||
|
# "event_log: false # 是否转发日志到event bus,显示在图形界面
|
||||||
self.engine_config = load_json(self.engine_filename)
|
self.engine_config = load_json(self.engine_filename)
|
||||||
|
# 是否产生event log 日志(一般GUI界面才产生,而且比好消耗资源)
|
||||||
|
self.event_log = self.engine_config.get('event_log', False)
|
||||||
# 读取策略得配置
|
# 读取策略得配置
|
||||||
self.strategy_setting = load_json(self.setting_filename)
|
self.strategy_setting = load_json(self.setting_filename)
|
||||||
|
|
||||||
@ -1754,12 +1767,13 @@ class CtaEngine(BaseEngine):
|
|||||||
"""
|
"""
|
||||||
Create cta engine log event.
|
Create cta engine log event.
|
||||||
"""
|
"""
|
||||||
# 推送至全局CTA_LOG Event
|
if self.event_log:
|
||||||
log = LogData(msg=f"{strategy_name}: {msg}" if strategy_name else msg,
|
# 推送至全局CTA_LOG Event
|
||||||
gateway_name="CtaStrategy",
|
log = LogData(msg=f"{strategy_name}: {msg}" if strategy_name else msg,
|
||||||
level=level)
|
gateway_name="CtaStrategy",
|
||||||
event = Event(type=EVENT_CTA_LOG, data=log)
|
level=level)
|
||||||
self.event_engine.put(event)
|
event = Event(type=EVENT_CTA_LOG, data=log)
|
||||||
|
self.event_engine.put(event)
|
||||||
|
|
||||||
# 保存单独的策略日志
|
# 保存单独的策略日志
|
||||||
if strategy_name:
|
if strategy_name:
|
||||||
|
@ -565,7 +565,7 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
"""初始化Policy"""
|
"""初始化Policy"""
|
||||||
self.write_log(u'init_policy(),初始化执行逻辑')
|
self.write_log(u'init_policy(),初始化执行逻辑')
|
||||||
self.policy.load()
|
self.policy.load()
|
||||||
self.write_log('{}'.format(json.dumps(self.policy.to_json(),indent=2, ensure_ascii=True)))
|
self.write_log('{}'.format(json.dumps(self.policy.to_json(),indent=2, ensure_ascii=False)))
|
||||||
|
|
||||||
def init_position(self):
|
def init_position(self):
|
||||||
"""
|
"""
|
||||||
@ -637,7 +637,7 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
|
|
||||||
return pos
|
return pos
|
||||||
|
|
||||||
def compare_pos(self):
|
def compare_pos(self,auto_balance=False):
|
||||||
"""比较仓位"""
|
"""比较仓位"""
|
||||||
for vt_symbol, position in self.positions.items():
|
for vt_symbol, position in self.positions.items():
|
||||||
name = self.cta_engine.get_name(vt_symbol)
|
name = self.cta_engine.get_name(vt_symbol)
|
||||||
@ -752,13 +752,13 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
if len(grid.order_ids) > 0:
|
if len(grid.order_ids) > 0:
|
||||||
self.write_log(f'剩余委托单号:{grid.order_ids}')
|
self.write_log(f'剩余委托单号:{grid.order_ids}')
|
||||||
|
|
||||||
|
"""
|
||||||
# 网格的所有委托单已经执行完毕
|
# 网格的所有委托单已经执行完毕
|
||||||
if grid.volume <= grid.traded_volume:
|
if grid.volume <= grid.traded_volume:
|
||||||
grid.order_status = False
|
grid.order_status = False
|
||||||
if grid.volume < grid.traded_volume:
|
if grid.volume < grid.traded_volume:
|
||||||
self.write_error(f'{order.vt_symbol} 已成交总量:{grid.traded_volume}超出{grid.volume}, 更新=>{grid.traded_volume}')
|
self.write_error(f'{order.vt_symbol} 已成交总量:{grid.traded_volume}超出{grid.volume}, 更新=>{grid.traded_volume}')
|
||||||
grid.volume = grid.traded_volume
|
grid.volume = grid.traded_volume
|
||||||
grid.traded_volume = 0
|
|
||||||
|
|
||||||
# 卖出完毕(sell)
|
# 卖出完毕(sell)
|
||||||
if order.direction != Direction.LONG:
|
if order.direction != Direction.LONG:
|
||||||
@ -774,10 +774,11 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
# 开仓完毕( buy)
|
# 开仓完毕( buy)
|
||||||
else:
|
else:
|
||||||
grid.open_status = True
|
grid.open_status = True
|
||||||
|
grid.traded_volume = 0
|
||||||
grid.open_time = self.cur_datetime
|
grid.open_time = self.cur_datetime
|
||||||
self.write_log(f'买入{order.vt_symbol}完毕,总量:{grid.volume},最后一笔委托价:{order.price}'
|
self.write_log(f'买入{order.vt_symbol}完毕,总量:{grid.volume},最后一笔委托价:{order.price}'
|
||||||
+ f',成交:{order.volume}')
|
+ f',成交:{order.volume}')
|
||||||
|
"""
|
||||||
self.gt.save()
|
self.gt.save()
|
||||||
|
|
||||||
# 在策略得活动订单中,移除
|
# 在策略得活动订单中,移除
|
||||||
@ -872,6 +873,7 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
return
|
return
|
||||||
|
|
||||||
remove_gids = []
|
remove_gids = []
|
||||||
|
changed = False
|
||||||
# 多单网格逐一止损/止盈检查:
|
# 多单网格逐一止损/止盈检查:
|
||||||
long_grids = self.gt.get_opened_grids(direction=Direction.LONG)
|
long_grids = self.gt.get_opened_grids(direction=Direction.LONG)
|
||||||
for lg in long_grids:
|
for lg in long_grids:
|
||||||
@ -896,7 +898,7 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
lg.close_price,
|
lg.close_price,
|
||||||
lg.open_price,
|
lg.open_price,
|
||||||
lg.volume))
|
lg.volume))
|
||||||
|
changed = True
|
||||||
if lg.traded_volume > 0:
|
if lg.traded_volume > 0:
|
||||||
lg.volume -= lg.traded_volume
|
lg.volume -= lg.traded_volume
|
||||||
lg.traded_volume = 0
|
lg.traded_volume = 0
|
||||||
@ -910,6 +912,7 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
lg.order_status = True
|
lg.order_status = True
|
||||||
lg.close_status = True
|
lg.close_status = True
|
||||||
self.write_log(f'{lg.vt_symbol}[{cn_name}] 数量:{lg.volume},准备卖出')
|
self.write_log(f'{lg.vt_symbol}[{cn_name}] 数量:{lg.volume},准备卖出')
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# 止损
|
# 止损
|
||||||
@ -925,7 +928,7 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
lg.stop_price,
|
lg.stop_price,
|
||||||
lg.open_price,
|
lg.open_price,
|
||||||
lg.volume))
|
lg.volume))
|
||||||
|
changed = True
|
||||||
if lg.traded_volume > 0:
|
if lg.traded_volume > 0:
|
||||||
lg.volume -= lg.traded_volume
|
lg.volume -= lg.traded_volume
|
||||||
lg.traded_volume = 0
|
lg.traded_volume = 0
|
||||||
@ -940,8 +943,9 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
lg.close_status = True
|
lg.close_status = True
|
||||||
self.write_log(f'{lg.vt_symbol}[{cn_name}] 数量:{lg.volume},准备卖出')
|
self.write_log(f'{lg.vt_symbol}[{cn_name}] 数量:{lg.volume},准备卖出')
|
||||||
|
|
||||||
if len(remove_gids) > 0:
|
if changed:
|
||||||
self.gt.remove_grids_by_ids(direction=Direction.LONG, ids=remove_gids)
|
if len(remove_gids) > 0:
|
||||||
|
self.gt.remove_grids_by_ids(direction=Direction.LONG, ids=remove_gids)
|
||||||
self.gt.save()
|
self.gt.save()
|
||||||
|
|
||||||
def tns_excute_sell_grids(self, vt_symbol=None):
|
def tns_excute_sell_grids(self, vt_symbol=None):
|
||||||
@ -993,7 +997,7 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
vt_symbol=ordering_grid.vt_symbol,
|
vt_symbol=ordering_grid.vt_symbol,
|
||||||
direction=Direction.NET)
|
direction=Direction.NET)
|
||||||
if acc_symbol_pos is None:
|
if acc_symbol_pos is None:
|
||||||
self.write_error(u'当前{}持仓查询不到'.format(ordering_grid.vt_symbol))
|
self.write_error(f'{self.strategy_name}当前{ordering_grid.vt_symbol}持仓查询不到, 无法执行卖出')
|
||||||
return
|
return
|
||||||
|
|
||||||
vt_symbol = ordering_grid.vt_symbol
|
vt_symbol = ordering_grid.vt_symbol
|
||||||
@ -1038,10 +1042,10 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
order_time=self.cur_datetime,
|
order_time=self.cur_datetime,
|
||||||
grid=ordering_grid)
|
grid=ordering_grid)
|
||||||
if vt_orderids is None or len(vt_orderids) == 0:
|
if vt_orderids is None or len(vt_orderids) == 0:
|
||||||
self.write_error(f'委托卖出失败,{vt_symbol} 委托价:{sell_price} 数量:{sell_volume}')
|
self.write_error(f'{vt_symbol} 委托卖出失败,委托价:{sell_price} 数量:{sell_volume}')
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.write_log(f'已委托卖出,{sell_volume},委托价:{sell_price}, 数量:{sell_volume}')
|
self.write_log(f'{vt_symbol} 已委托卖出,{sell_volume},委托价:{sell_price}, 数量:{sell_volume}')
|
||||||
|
|
||||||
|
|
||||||
def tns_finish_sell_grid(self, grid):
|
def tns_finish_sell_grid(self, grid):
|
||||||
@ -1177,7 +1181,7 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
self.write_error(f'委托买入失败,{vt_symbol} 委托价:{buy_price} 数量:{buy_volume}')
|
self.write_error(f'委托买入失败,{vt_symbol} 委托价:{buy_price} 数量:{buy_volume}')
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.write_error(f'{vt_orderids},已委托买入,{vt_symbol} 委托价:{buy_price} 数量:{buy_volume}')
|
self.write_log(f'{self.strategy_name}, {vt_orderids},已委托买入,{vt_symbol} 委托价:{buy_price} 数量:{buy_volume}')
|
||||||
|
|
||||||
def tns_finish_buy_grid(self, grid):
|
def tns_finish_buy_grid(self, grid):
|
||||||
"""
|
"""
|
||||||
@ -1185,7 +1189,7 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
self.write_log(u'事务完成买入网格:{},计划数量:{},计划价格:{},实际数量:{}'
|
self.write_log(u'事务完成买入网格:{},计划数量:{},计划价格:{},实际数量:{}'
|
||||||
.format(grid.type, grid.volume, grid.openPrice, grid.traded_volume))
|
.format(grid.type, grid.volume, grid.open_price, grid.traded_volume))
|
||||||
if grid.volume != grid.traded_volume:
|
if grid.volume != grid.traded_volume:
|
||||||
grid.volume = grid.traded_volume
|
grid.volume = grid.traded_volume
|
||||||
grid.traded_volume = 0
|
grid.traded_volume = 0
|
||||||
@ -1276,15 +1280,15 @@ class CtaStockTemplate(CtaTemplate):
|
|||||||
name = self.cta_engine.get_name(grid.vt_symbol)
|
name = self.cta_engine.get_name(grid.vt_symbol)
|
||||||
|
|
||||||
if not grid.open_status and grid.order_status:
|
if not grid.open_status and grid.order_status:
|
||||||
opening_info += f'网格{grid.type},买入状态:{name}[{grid.vt_symbol}], [已买入:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}\n'
|
opening_info += f'网格{grid.type},买入状态:{name}[{grid.vt_symbol}], 买入价:{grid.open_price} [已买入:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}\n'
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if grid.open_status and not grid.close_status:
|
if grid.open_status and not grid.close_status:
|
||||||
holding_info += f'网格{grid.type},持有状态:{name}[{grid.vt_symbol}],[数量:{grid.volume}, 开仓时间:{grid.open_time}]\n'
|
holding_info += f'网格{grid.type},持有状态:{name}[{grid.vt_symbol}],买入价:{grid.open_price} [数量:{grid.volume}, 开仓时间:{grid.open_time}]\n'
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if grid.open_status and grid.close_status:
|
if grid.open_status and grid.close_status:
|
||||||
closing_info += f'网格{grid.type},卖出状态:{name}[{grid.vt_symbol}], [已卖出:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}\n'
|
closing_info += f'网格{grid.type},卖出状态:{name}[{grid.vt_symbol}],卖出价:{grid.close_price} [已卖出:{grid.traded_volume} => 目标:{grid.volume}, 委托时间:{grid.order_time}\n'
|
||||||
|
|
||||||
if len(opening_info) > 0:
|
if len(opening_info) > 0:
|
||||||
self.write_log(opening_info)
|
self.write_log(opening_info)
|
||||||
|
@ -114,8 +114,15 @@ class CtaEngine(BaseEngine):
|
|||||||
:param event_engine: 事件引擎
|
:param event_engine: 事件引擎
|
||||||
"""
|
"""
|
||||||
super().__init__(main_engine, event_engine, APP_NAME)
|
super().__init__(main_engine, event_engine, APP_NAME)
|
||||||
|
# 增强策略引擎得特殊参数配置
|
||||||
|
# "accountid" : "xxxx", 资金账号,一般用于推送消息时附带
|
||||||
|
# "strategy_group": "cta_strategy_pro", # 当前实例名。多个实例时,区分开
|
||||||
|
# "trade_2_wx": true # 是否交易记录转发至微信通知
|
||||||
|
# "event_log: false # 是否转发日志到event bus,显示在图形界面
|
||||||
|
# "snapshot2file": false # 是否保存切片到文件
|
||||||
self.engine_config = {}
|
self.engine_config = {}
|
||||||
|
# 是否激活 write_log写入event bus(比较耗资源)
|
||||||
|
self.event_log = False
|
||||||
|
|
||||||
self.strategy_setting = {} # strategy_name: dict
|
self.strategy_setting = {} # strategy_name: dict
|
||||||
self.strategy_data = {} # strategy_name: dict
|
self.strategy_data = {} # strategy_name: dict
|
||||||
@ -812,8 +819,8 @@ class CtaEngine(BaseEngine):
|
|||||||
"""查询价格最小跳动"""
|
"""查询价格最小跳动"""
|
||||||
contract = self.main_engine.get_contract(vt_symbol)
|
contract = self.main_engine.get_contract(vt_symbol)
|
||||||
if contract is None:
|
if contract is None:
|
||||||
self.write_error(f'查询不到{vt_symbol}合约信息,缺省使用0.1作为价格跳动')
|
self.write_error(f'查询不到{vt_symbol}合约信息,缺省使用1作为价格跳动')
|
||||||
return 0.1
|
return 1
|
||||||
|
|
||||||
return contract.pricetick
|
return contract.pricetick
|
||||||
|
|
||||||
@ -1313,12 +1320,13 @@ class CtaEngine(BaseEngine):
|
|||||||
self.write_log(f'{strategy_name}返回得K线切片数据为空')
|
self.write_log(f'{strategy_name}返回得K线切片数据为空')
|
||||||
return
|
return
|
||||||
|
|
||||||
# 剩下工作:保存本地文件/数据库
|
if self.engine_config.get('snapshot2file', False):
|
||||||
snapshot_folder = get_folder_path(f'data/snapshots/{strategy_name}')
|
# 剩下工作:保存本地文件/数据库
|
||||||
snapshot_file = snapshot_folder.joinpath('{}.pkb2'.format(datetime.now().strftime('%Y%m%d_%H%M%S')))
|
snapshot_folder = get_folder_path(f'data/snapshots/{strategy_name}')
|
||||||
with bz2.BZ2File(str(snapshot_file), 'wb') as f:
|
snapshot_file = snapshot_folder.joinpath('{}.pkb2'.format(datetime.now().strftime('%Y%m%d_%H%M%S')))
|
||||||
pickle.dump(snapshot, f)
|
with bz2.BZ2File(str(snapshot_file), 'wb') as f:
|
||||||
self.write_log(u'切片保存成功:{}'.format(str(snapshot_file)))
|
pickle.dump(snapshot, f)
|
||||||
|
self.write_log(u'切片保存成功:{}'.format(str(snapshot_file)))
|
||||||
|
|
||||||
# 通过事件方式,传导到account_recorder
|
# 通过事件方式,传导到account_recorder
|
||||||
snapshot.update({
|
snapshot.update({
|
||||||
@ -1498,7 +1506,7 @@ class CtaEngine(BaseEngine):
|
|||||||
spd_vt_symbol = pos.get('vt_symbol', None)
|
spd_vt_symbol = pos.get('vt_symbol', None)
|
||||||
if spd_vt_symbol is not None and spd_vt_symbol.endswith('SPD'):
|
if spd_vt_symbol is not None and spd_vt_symbol.endswith('SPD'):
|
||||||
spd_symbol, spd_exchange = extract_vt_symbol(spd_vt_symbol)
|
spd_symbol, spd_exchange = extract_vt_symbol(spd_vt_symbol)
|
||||||
spd_setting = self.main_engine.get_all_custom_contracts().get(spd_symbol, None)
|
spd_setting = self.main_engine.get_all_custom_contracts(rtn_setting=True).get(spd_symbol, None)
|
||||||
|
|
||||||
if spd_setting is None:
|
if spd_setting is None:
|
||||||
self.write_error(u'获取不到:{}得设置信息,检查自定义合约配置文件'.format(spd_symbol))
|
self.write_error(u'获取不到:{}得设置信息,检查自定义合约配置文件'.format(spd_symbol))
|
||||||
@ -1511,13 +1519,13 @@ class CtaEngine(BaseEngine):
|
|||||||
|
|
||||||
leg1_pos = {}
|
leg1_pos = {}
|
||||||
leg1_pos.update({'symbol': spd_setting.get('leg1_symbol')})
|
leg1_pos.update({'symbol': spd_setting.get('leg1_symbol')})
|
||||||
leg1_pos.update({'vt_symbol': spd_setting.get('leg1_symbol')})
|
leg1_pos.update({'vt_symbol': '{}.{}'.format(spd_setting.get('leg1_symbol'), spd_setting.get('leg1_exchange'))})
|
||||||
leg1_pos.update({'direction': leg1_direction})
|
leg1_pos.update({'direction': leg1_direction})
|
||||||
leg1_pos.update({'volume': spd_setting.get('leg1_ratio', 1) * spd_volume})
|
leg1_pos.update({'volume': spd_setting.get('leg1_ratio', 1) * spd_volume})
|
||||||
|
|
||||||
leg2_pos = {}
|
leg2_pos = {}
|
||||||
leg2_pos.update({'symbol': spd_setting.get('leg2_symbol')})
|
leg2_pos.update({'symbol': spd_setting.get('leg2_symbol')})
|
||||||
leg2_pos.update({'vt_symbol': spd_setting.get('leg2_symbol')})
|
leg2_pos.update({'vt_symbol': '{}.{}'.format(spd_setting.get('leg2_symbol'), spd_setting.get('leg2_exchange'))})
|
||||||
leg2_pos.update({'direction': leg2_direction})
|
leg2_pos.update({'direction': leg2_direction})
|
||||||
leg2_pos.update({'volume': spd_setting.get('leg2_ratio', 1) * spd_volume})
|
leg2_pos.update({'volume': spd_setting.get('leg2_ratio', 1) * spd_volume})
|
||||||
|
|
||||||
@ -1649,7 +1657,7 @@ class CtaEngine(BaseEngine):
|
|||||||
continue
|
continue
|
||||||
if holding.exchange == Exchange.SPD:
|
if holding.exchange == Exchange.SPD:
|
||||||
continue
|
continue
|
||||||
if '&' in holding.vt_symbol and (holding.vt_symbol.startswith('SP') or holding.vt_symbol.startswith('STG')):
|
if '&' in holding.vt_symbol and (holding.vt_symbol.startswith('SP') or holding.vt_symbol.startswith('STG') or holding.vt_symbol.startswith('PRT')):
|
||||||
continue
|
continue
|
||||||
|
|
||||||
compare_pos[vt_symbol] = OrderedDict(
|
compare_pos[vt_symbol] = OrderedDict(
|
||||||
@ -1672,7 +1680,7 @@ class CtaEngine(BaseEngine):
|
|||||||
vt_symbols.add(vt_symbol)
|
vt_symbols.add(vt_symbol)
|
||||||
symbol_pos = compare_pos.get(vt_symbol, None)
|
symbol_pos = compare_pos.get(vt_symbol, None)
|
||||||
if symbol_pos is None:
|
if symbol_pos is None:
|
||||||
self.write_log(u'账号持仓信息获取不到{},创建一个'.format(vt_symbol))
|
# self.write_log(u'账号持仓信息获取不到{},创建一个'.format(vt_symbol))
|
||||||
symbol_pos = OrderedDict(
|
symbol_pos = OrderedDict(
|
||||||
{
|
{
|
||||||
"账号空单": 0,
|
"账号空单": 0,
|
||||||
@ -1700,9 +1708,8 @@ class CtaEngine(BaseEngine):
|
|||||||
compare_info = ''
|
compare_info = ''
|
||||||
for vt_symbol in sorted(vt_symbols):
|
for vt_symbol in sorted(vt_symbols):
|
||||||
# 发送不一致得结果
|
# 发送不一致得结果
|
||||||
symbol_pos = compare_pos.pop(vt_symbol, None)
|
symbol_pos = compare_pos.pop(vt_symbol, {})
|
||||||
if symbol_pos is None:
|
|
||||||
continue
|
|
||||||
d_long = {
|
d_long = {
|
||||||
'account_id': self.engine_config.get('accountid', '-'),
|
'account_id': self.engine_config.get('accountid', '-'),
|
||||||
'vt_symbol': vt_symbol,
|
'vt_symbol': vt_symbol,
|
||||||
@ -1716,21 +1723,21 @@ class CtaEngine(BaseEngine):
|
|||||||
'strategy_list': symbol_pos.get('空单策略', [])}
|
'strategy_list': symbol_pos.get('空单策略', [])}
|
||||||
|
|
||||||
# 多空都一致
|
# 多空都一致
|
||||||
if round(symbol_pos['账号空单'], 7) == round(symbol_pos['策略空单'], 7) and \
|
if round(symbol_pos.get('账号空单',0), 7) == round(symbol_pos.get('策略空单',0), 7) and \
|
||||||
round(symbol_pos['账号多单'], 7) == round(symbol_pos['策略多单'], 7):
|
round(symbol_pos.get('账号多单',0), 7) == round(symbol_pos.get('策略多单',0), 7):
|
||||||
msg = u'{}多空都一致.{}\n'.format(vt_symbol, json.dumps(symbol_pos, indent=2, ensure_ascii=False))
|
msg = u'{}多空都一致.{}\n'.format(vt_symbol, json.dumps(symbol_pos, indent=2, ensure_ascii=False))
|
||||||
self.write_log(msg)
|
self.write_log(msg)
|
||||||
compare_info += msg
|
compare_info += msg
|
||||||
else:
|
else:
|
||||||
pos_compare_result += '\n{}: '.format(vt_symbol)
|
pos_compare_result += '\n{}: '.format(vt_symbol)
|
||||||
# 判断是多单不一致?
|
# 判断是多单不一致?
|
||||||
diff_long_volume = round(symbol_pos['账号多单'], 7) - round(symbol_pos['策略多单'], 7)
|
diff_long_volume = round(symbol_pos.get('账号多单',0), 7) - round(symbol_pos.get('策略多单',0), 7)
|
||||||
if diff_long_volume != 0:
|
if diff_long_volume != 0:
|
||||||
msg = '{}多单[账号({}), 策略{},共({})], ' \
|
msg = '{}多单[账号({}), 策略{},共({})], ' \
|
||||||
.format(vt_symbol,
|
.format(vt_symbol,
|
||||||
symbol_pos['账号多单'],
|
symbol_pos.get('账号多单'),
|
||||||
symbol_pos['多单策略'],
|
symbol_pos.get('多单策略'),
|
||||||
symbol_pos['策略多单'])
|
symbol_pos.get('策略多单'))
|
||||||
|
|
||||||
pos_compare_result += msg
|
pos_compare_result += msg
|
||||||
self.write_error(u'{}不一致:{}'.format(vt_symbol, msg))
|
self.write_error(u'{}不一致:{}'.format(vt_symbol, msg))
|
||||||
@ -1739,14 +1746,14 @@ class CtaEngine(BaseEngine):
|
|||||||
self.balance_pos(vt_symbol, Direction.LONG, diff_long_volume)
|
self.balance_pos(vt_symbol, Direction.LONG, diff_long_volume)
|
||||||
|
|
||||||
# 判断是空单不一致:
|
# 判断是空单不一致:
|
||||||
diff_short_volume = round(symbol_pos['账号空单'], 7) - round(symbol_pos['策略空单'], 7)
|
diff_short_volume = round(symbol_pos.get('账号空单',0), 7) - round(symbol_pos.get('策略空单',0), 7)
|
||||||
|
|
||||||
if diff_short_volume != 0:
|
if diff_short_volume != 0:
|
||||||
msg = '{}空单[账号({}), 策略{},共({})], ' \
|
msg = '{}空单[账号({}), 策略{},共({})], ' \
|
||||||
.format(vt_symbol,
|
.format(vt_symbol,
|
||||||
symbol_pos['账号空单'],
|
symbol_pos.get('账号空单'),
|
||||||
symbol_pos['空单策略'],
|
symbol_pos.get('空单策略'),
|
||||||
symbol_pos['策略空单'])
|
symbol_pos.get('策略空单'))
|
||||||
pos_compare_result += msg
|
pos_compare_result += msg
|
||||||
self.write_error(u'{}不一致:{}'.format(vt_symbol, msg))
|
self.write_error(u'{}不一致:{}'.format(vt_symbol, msg))
|
||||||
compare_info += u'{}不一致:{}\n'.format(vt_symbol, msg)
|
compare_info += u'{}不一致:{}\n'.format(vt_symbol, msg)
|
||||||
@ -1841,6 +1848,8 @@ class CtaEngine(BaseEngine):
|
|||||||
"""
|
"""
|
||||||
# 读取引擎得配置
|
# 读取引擎得配置
|
||||||
self.engine_config = load_json(self.engine_filename)
|
self.engine_config = load_json(self.engine_filename)
|
||||||
|
# 是否产生event log 日志(一般GUI界面才产生,而且比好消耗资源)
|
||||||
|
self.event_log = self.engine_config.get('event_log', False)
|
||||||
|
|
||||||
# 读取策略得配置
|
# 读取策略得配置
|
||||||
self.strategy_setting = load_json(self.setting_filename)
|
self.strategy_setting = load_json(self.setting_filename)
|
||||||
@ -1913,12 +1922,13 @@ class CtaEngine(BaseEngine):
|
|||||||
"""
|
"""
|
||||||
Create cta engine log event.
|
Create cta engine log event.
|
||||||
"""
|
"""
|
||||||
# 推送至全局CTA_LOG Event
|
if self.event_log:
|
||||||
log = LogData(msg=f"{strategy_name}: {msg}" if strategy_name else msg,
|
# 推送至全局CTA_LOG Event
|
||||||
gateway_name="CtaStrategy",
|
log = LogData(msg=f"{strategy_name}: {msg}" if strategy_name else msg,
|
||||||
level=level)
|
gateway_name="CtaStrategy",
|
||||||
event = Event(type=EVENT_CTA_LOG, data=log)
|
level=level)
|
||||||
self.event_engine.put(event)
|
event = Event(type=EVENT_CTA_LOG, data=log)
|
||||||
|
self.event_engine.put(event)
|
||||||
|
|
||||||
# 保存单独的策略日志
|
# 保存单独的策略日志
|
||||||
if strategy_name:
|
if strategy_name:
|
||||||
|
@ -384,6 +384,7 @@ class CtaTemplate(ABC):
|
|||||||
days: int,
|
days: int,
|
||||||
interval: Interval = Interval.MINUTE,
|
interval: Interval = Interval.MINUTE,
|
||||||
callback: Callable = None,
|
callback: Callable = None,
|
||||||
|
interval_num: int = 1
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
Load historical bar data for initializing strategy.
|
Load historical bar data for initializing strategy.
|
||||||
@ -391,7 +392,7 @@ class CtaTemplate(ABC):
|
|||||||
if not callback:
|
if not callback:
|
||||||
callback = self.on_bar
|
callback = self.on_bar
|
||||||
|
|
||||||
self.cta_engine.load_bar(self.vt_symbol, days, interval, callback)
|
self.cta_engine.load_bar(self.vt_symbol, days, interval, callback, interval_num)
|
||||||
|
|
||||||
def load_tick(self, days: int):
|
def load_tick(self, days: int):
|
||||||
"""
|
"""
|
||||||
@ -1059,7 +1060,7 @@ class CtaProTemplate(CtaTemplate):
|
|||||||
def save_tns(self, tns_data):
|
def save_tns(self, tns_data):
|
||||||
"""
|
"""
|
||||||
保存多空事务记录=》csv文件,便于后续分析
|
保存多空事务记录=》csv文件,便于后续分析
|
||||||
:param tns_data:
|
:param tns_data: {"datetime":xxx, "direction":"long"或者"short", "price":xxx}
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
if self.backtesting:
|
if self.backtesting:
|
||||||
@ -1770,6 +1771,7 @@ class CtaProFutureTemplate(CtaProTemplate):
|
|||||||
if self.activate_today_lock:
|
if self.activate_today_lock:
|
||||||
self.write_log(u'昨仓多单:{},没有今仓,满足条件,直接平昨仓'.format(grid_pos.long_yd))
|
self.write_log(u'昨仓多单:{},没有今仓,满足条件,直接平昨仓'.format(grid_pos.long_yd))
|
||||||
|
|
||||||
|
|
||||||
sell_price = self.cta_engine.get_price(sell_symbol)
|
sell_price = self.cta_engine.get_price(sell_symbol)
|
||||||
if sell_price is None:
|
if sell_price is None:
|
||||||
self.write_error(f'暂时不能获取{sell_symbol}价格,不能平仓')
|
self.write_error(f'暂时不能获取{sell_symbol}价格,不能平仓')
|
||||||
@ -1780,12 +1782,16 @@ class CtaProFutureTemplate(CtaProTemplate):
|
|||||||
grid.volume -= grid.traded_volume
|
grid.volume -= grid.traded_volume
|
||||||
grid.traded_volume = 0
|
grid.traded_volume = 0
|
||||||
|
|
||||||
|
if grid_pos.long_pos <grid.volume:
|
||||||
|
self.write_error(f'账号{sell_symbol}多单持仓:{grid_pos.long_pos}不满足平仓:{grid.volume}要求:')
|
||||||
|
return False
|
||||||
|
|
||||||
vt_orderids = self.sell(price=sell_price,
|
vt_orderids = self.sell(price=sell_price,
|
||||||
volume=grid.volume,
|
volume=grid.volume,
|
||||||
vt_symbol=sell_symbol,
|
vt_symbol=sell_symbol,
|
||||||
order_type=self.order_type,
|
order_type=self.order_type,
|
||||||
order_time=self.cur_datetime,
|
order_time=self.cur_datetime,
|
||||||
grid=grid)
|
grid=grid)
|
||||||
if len(vt_orderids) == 0:
|
if len(vt_orderids) == 0:
|
||||||
self.write_error(u'多单平仓委托失败')
|
self.write_error(u'多单平仓委托失败')
|
||||||
return False
|
return False
|
||||||
@ -1870,6 +1876,10 @@ class CtaProFutureTemplate(CtaProTemplate):
|
|||||||
grid.volume -= grid.traded_volume
|
grid.volume -= grid.traded_volume
|
||||||
grid.traded_volume = 0
|
grid.traded_volume = 0
|
||||||
|
|
||||||
|
if grid_pos.short_pos < grid.volume:
|
||||||
|
self.write_error(f'账号{cover_symbol}多单持仓:{grid_pos.short_pos}不满足平仓:{grid.volume}要求:')
|
||||||
|
return False
|
||||||
|
|
||||||
vt_orderids = self.cover(price=cover_price,
|
vt_orderids = self.cover(price=cover_price,
|
||||||
volume=grid.volume,
|
volume=grid.volume,
|
||||||
vt_symbol=cover_symbol,
|
vt_symbol=cover_symbol,
|
||||||
@ -1997,7 +2007,7 @@ class CtaProFutureTemplate(CtaProTemplate):
|
|||||||
target_long_grid = None
|
target_long_grid = None
|
||||||
remove_long_grid_ids = []
|
remove_long_grid_ids = []
|
||||||
for g in sorted(locked_long_grids, key=lambda grid: grid.volume):
|
for g in sorted(locked_long_grids, key=lambda grid: grid.volume):
|
||||||
if g.orderStatus or len(g.orderRef) > 0:
|
if g.order_status or len(g.orderRef) > 0:
|
||||||
continue
|
continue
|
||||||
if target_long_grid is None:
|
if target_long_grid is None:
|
||||||
target_long_grid = g
|
target_long_grid = g
|
||||||
@ -2133,7 +2143,7 @@ class CtaProFutureTemplate(CtaProTemplate):
|
|||||||
vt_symbol = g.snapshot.get('mi_symbol', self.vt_symbol)
|
vt_symbol = g.snapshot.get('mi_symbol', self.vt_symbol)
|
||||||
volume = g.volume - g.traded_volume
|
volume = g.volume - g.traded_volume
|
||||||
locked_long_dict.update({vt_symbol: locked_long_dict.get(vt_symbol, 0) + volume})
|
locked_long_dict.update({vt_symbol: locked_long_dict.get(vt_symbol, 0) + volume})
|
||||||
if g.orderStatus or g.order_ids:
|
if g.order_status or g.order_ids:
|
||||||
self.write_log(u'当前对锁格:{}存在委托,不进行解锁'.format(g.to_json()))
|
self.write_log(u'当前对锁格:{}存在委托,不进行解锁'.format(g.to_json()))
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -2150,7 +2160,7 @@ class CtaProFutureTemplate(CtaProTemplate):
|
|||||||
vt_symbol = g.snapshot.get('mi_symbol', self.vt_symbol)
|
vt_symbol = g.snapshot.get('mi_symbol', self.vt_symbol)
|
||||||
volume = g.volume - g.traded_volume
|
volume = g.volume - g.traded_volume
|
||||||
locked_short_dict.update({vt_symbol: locked_short_dict.get(vt_symbol, 0) + volume})
|
locked_short_dict.update({vt_symbol: locked_short_dict.get(vt_symbol, 0) + volume})
|
||||||
if g.orderStatus or g.order_ids:
|
if g.order_status or g.order_ids:
|
||||||
self.write_log(u'当前对锁格:{}存在委托,不进行解锁'.format(g.to_json()))
|
self.write_log(u'当前对锁格:{}存在委托,不进行解锁'.format(g.to_json()))
|
||||||
return
|
return
|
||||||
|
|
||||||
@ -2238,7 +2248,7 @@ class CtaProFutureTemplate(CtaProTemplate):
|
|||||||
for g in long_grids:
|
for g in long_grids:
|
||||||
# 满足离场条件,或者碰到止损价格
|
# 满足离场条件,或者碰到止损价格
|
||||||
if g.stop_price > 0 and g.stop_price > self.cur_99_price \
|
if g.stop_price > 0 and g.stop_price > self.cur_99_price \
|
||||||
and g.openStatus and not g.orderStatus:
|
and g.open_status and not g.order_status:
|
||||||
dist_record = dict()
|
dist_record = dict()
|
||||||
dist_record['datetime'] = self.cur_datetime
|
dist_record['datetime'] = self.cur_datetime
|
||||||
dist_record['symbol'] = self.idx_symbol
|
dist_record['symbol'] = self.idx_symbol
|
||||||
@ -2262,7 +2272,7 @@ class CtaProFutureTemplate(CtaProTemplate):
|
|||||||
short_grids = self.gt.get_opened_grids_without_types(direction=Direction.SHORT, types=[LOCK_GRID])
|
short_grids = self.gt.get_opened_grids_without_types(direction=Direction.SHORT, types=[LOCK_GRID])
|
||||||
for g in short_grids:
|
for g in short_grids:
|
||||||
if g.stop_price > 0 and g.stop_price < self.cur_99_price \
|
if g.stop_price > 0 and g.stop_price < self.cur_99_price \
|
||||||
and g.openStatus and not g.orderStatus:
|
and g.open_status and not g.order_status:
|
||||||
dist_record = dict()
|
dist_record = dict()
|
||||||
dist_record['datetime'] = self.cur_datetime
|
dist_record['datetime'] = self.cur_datetime
|
||||||
dist_record['symbol'] = self.idx_symbol
|
dist_record['symbol'] = self.idx_symbol
|
||||||
|
Loading…
Reference in New Issue
Block a user