diff --git a/vnpy/app/cta_crypto/back_testing.py b/vnpy/app/cta_crypto/back_testing.py index cbe5986a..55a6f639 100644 --- a/vnpy/app/cta_crypto/back_testing.py +++ b/vnpy/app/cta_crypto/back_testing.py @@ -378,6 +378,8 @@ class BackTestingEngine(object): def get_position_holding(self, vt_symbol: str, gateway_name: str = ''): """ 查询合约在账号的持仓(包含多空)""" + if not gateway_name: + gateway_name = self.gateway_name k = f'{gateway_name}.{vt_symbol}' holding = self.holdings.get(k, None) if not holding: @@ -1063,8 +1065,12 @@ class BackTestingEngine(object): strategy.on_stop_order(stop_order) strategy.on_order(order) self.append_trade(trade) - holding = self.get_position_holding(vt_symbol=trade.vt_symbol) + + # 更新持仓缓存数据 + k = '.'.join([self.gateway_name, trade.vt_symbol]) + holding = self.get_position_holding(trade.vt_symbol, self.gateway_name) holding.update_trade(trade) + strategy.on_trade(trade) def cross_limit_order(self, bar: BarData = None, tick: TickData = None): @@ -1139,21 +1145,19 @@ class BackTestingEngine(object): # 记录该合约来自哪个策略实例 trade.strategy_name = strategy.strategy_name + # 更新持仓缓存数据 + k = '.'.join([self.gateway_name, trade.vt_symbol]) + holding = self.get_position_holding(trade.vt_symbol, self.gateway_name) + holding.update_trade(trade) strategy.on_trade(trade) self.trade_dict[trade.vt_tradeid] = trade self.trades[trade.vt_tradeid] = copy.copy(trade) self.write_log(u'vt_trade_id:{0}'.format(trade.vt_tradeid)) - # 更新持仓缓存数据 - pos_buffer = self.pos_holding_dict.get(trade.vt_symbol, None) - if not pos_buffer: - pos_buffer = PositionHolding(self.get_contract(vt_symbol)) - self.pos_holding_dict[trade.vt_symbol] = pos_buffer - pos_buffer.update_trade(trade) self.write_log(u'{} : crossLimitOrder: TradeId:{}, posBuffer = {}'.format(trade.strategy_name, trade.tradeid, - pos_buffer.to_str())) + holding.to_str())) # 写入交易记录 self.append_trade(trade) diff --git a/vnpy/app/cta_crypto/engine.py b/vnpy/app/cta_crypto/engine.py index 84d7584c..f627fdc6 100644 --- a/vnpy/app/cta_crypto/engine.py +++ b/vnpy/app/cta_crypto/engine.py @@ -140,9 +140,12 @@ class CtaEngine(BaseEngine): def init_engine(self): """ """ + self.register_event() + self.register_funcs() + self.load_strategy_class() self.load_strategy_setting() - self.register_event() + self.write_log("CTA策略数字货币引擎初始化成功") def close(self): @@ -175,18 +178,17 @@ class CtaEngine(BaseEngine): self.main_engine.save_strategy_snapshot = self.save_strategy_snapshot # 注册到远程服务调用 - rpc_service = self.main_engine.apps.get('RpcService') - if rpc_service: - rpc_service.register(self.main_engine.get_strategy_status) - rpc_service.register(self.main_engine.get_strategy_pos) - rpc_service.register(self.main_engine.add_strategy) - rpc_service.register(self.main_engine.init_strategy) - rpc_service.register(self.main_engine.start_strategy) - rpc_service.register(self.main_engine.stop_strategy) - rpc_service.register(self.main_engine.remove_strategy) - rpc_service.register(self.main_engine.reload_strategy) - rpc_service.register(self.main_engine.save_strategy_data) - rpc_service.register(self.main_engine.save_strategy_snapshot) + if self.main_engine.rpc_service: + self.main_engine.rpc_service.register(self.main_engine.get_strategy_status) + self.main_engine.rpc_service.register(self.main_engine.get_strategy_pos) + self.main_engine.rpc_service.register(self.main_engine.add_strategy) + self.main_engine.rpc_service.register(self.main_engine.init_strategy) + self.main_engine.rpc_service.register(self.main_engine.start_strategy) + self.main_engine.rpc_service.register(self.main_engine.stop_strategy) + self.main_engine.rpc_service.register(self.main_engine.remove_strategy) + self.main_engine.rpc_service.register(self.main_engine.reload_strategy) + self.main_engine.rpc_service.register(self.main_engine.save_strategy_data) + self.main_engine.rpc_service.register(self.main_engine.save_strategy_snapshot) def process_timer_event(self, event: Event): """ 处理定时器事件""" @@ -1317,7 +1319,7 @@ class CtaEngine(BaseEngine): """ return list(self.classes.keys()) - def get_strategy_status(self, strategy_name): + def get_strategy_status(self): """ return strategy inited/trading status :param strategy_name: diff --git a/vnpy/app/cta_crypto/template.py b/vnpy/app/cta_crypto/template.py index dd95d308..1152f141 100644 --- a/vnpy/app/cta_crypto/template.py +++ b/vnpy/app/cta_crypto/template.py @@ -714,7 +714,6 @@ class CtaFutureTemplate(CtaTemplate): # 未执行的订单中,存在是异常,删除 self.write_log(u'{}报单更新,{}'.format(self.cur_datetime, order.__dict__)) - if order.vt_orderid in self.active_orders: if order.volume == order.traded and order.status in [Status.ALLTRADED]: @@ -787,6 +786,7 @@ class CtaFutureTemplate(CtaTemplate): else: old_traded_volume = grid.traded_volume grid.traded_volume += order.volume + grid.traded_volume = round(grid.traded_volume, 7) self.write_log(f'{grid.direction.value}单部分{order.offset}仓,' + f'网格volume:{grid.volume}, traded_volume:{old_traded_volume}=>{grid.traded_volume}') @@ -820,7 +820,7 @@ class CtaFutureTemplate(CtaTemplate): self.write_log(u'{} 委托信息:{}'.format(order.vt_orderid, old_order)) old_order['traded'] = order.traded order_vt_symbol = copy(old_order['vt_symbol']) - order_volume = old_order['volume'] - old_order['traded'] + order_volume = round(old_order['volume'] - old_order['traded'], 7) if order_volume <= 0: msg = u'{} {}{}需重新开仓数量为{},不再开仓' \ .format(self.strategy_name, @@ -1044,6 +1044,8 @@ class CtaFutureTemplate(CtaTemplate): """ self.write_log(u'执行事务平多仓位:{}'.format(grid.to_json())) + self.account_pos = self.cta_engine.get_position_holding(self.vt_symbol) + if self.account_pos is None: self.write_error(u'无法获取{}得持仓信息'.format(self.vt_symbol)) return False @@ -1057,14 +1059,17 @@ class CtaFutureTemplate(CtaTemplate): # 发出平多委托 if grid.traded_volume > 0: grid.volume -= grid.traded_volume + grid.volume = round(grid.volume, 7) grid.traded_volume = 0 - if self.account_pos.long_pos < grid.volume: - self.write_error(u'当前{}的多单持仓:{},不满足平仓目标:{}' + if 0 < self.account_pos.long_pos < grid.volume: + self.write_error(u'当前{}的多单持仓:{},不满足平仓目标:{},强制降低' .format(self.vt_symbol, self.account_pos.long_pos, grid.volume)) + grid.volume = self.account_pos.long_pos + vt_orderids = self.sell( vt_symbol=self.vt_symbol, price=sell_price, @@ -1091,6 +1096,7 @@ class CtaFutureTemplate(CtaTemplate): """ self.write_log(u'执行事务平空仓位:{}'.format(grid.to_json())) + self.account_pos = self.cta_engine.get_position_holding(self.vt_symbol) if self.account_pos is None: self.write_error(u'无法获取{}得持仓信息'.format(self.vt_symbol)) return False @@ -1104,8 +1110,17 @@ class CtaFutureTemplate(CtaTemplate): # 发出cover委托 if grid.traded_volume > 0: grid.volume -= grid.traded_volume + grid.volume = round(grid.volume, 7) grid.traded_volume = 0 + if 0 < abs(self.account_pos.short_pos) < grid.volume: + self.write_error(u'当前{}的空单持仓:{},不满足平仓目标:{}, 强制降低' + .format(self.vt_symbol, + self.account_pos.short_pos, + grid.volume)) + + grid.volume = abs(self.account_pos.short_pos) + vt_orderids = self.cover( price=cover_price, vt_symbol=self.vt_symbol, diff --git a/vnpy/component/cta_position.py b/vnpy/component/cta_position.py index 3c1c428b..6342c725 100644 --- a/vnpy/component/cta_position.py +++ b/vnpy/component/cta_position.py @@ -55,12 +55,14 @@ class CtaPosition(CtaComponent): if self.short_pos + volume > 0: self.write_error(u'平仓异常,超出仓位。净:{0},空:{1},平仓:{2}'.format(self.pos, self.short_pos, volume)) - self.write_log(f'空仓:{self.short_pos}->{self.short_pos + volume}') - self.write_log(f'净:{self.pos}->{self.pos + volume}') + pre_short_pos = self.short_pos + pre_pos = self.pos self.short_pos += volume self.pos += volume self.short_pos = round(self.short_pos, 7) self.pos = round(self.pos, 7) + self.write_log(f'空仓:{pre_short_pos}->{self.short_pos}') + self.write_log(f'净:{pre_pos}->{self.pos}') # 更新上层策略的pos。该方法不推荐使用 self.strategy.pos = self.pos @@ -68,15 +70,18 @@ class CtaPosition(CtaComponent): if direction == Direction.SHORT: # 平多仓 if self.long_pos - volume < 0: self.write_error(u'平仓异常,超出仓位。净:{0},多:{1},平仓:{2}'.format(self.pos, self.long_pos, volume)) - - self.write_log(f'多仓:{self.long_pos}->{self.long_pos - volume}') - self.write_log(f'净:{self.pos}->{self.pos - volume}') + pre_long_pos = self.long_pos + pre_pos = self.pos self.long_pos -= volume self.pos -= volume self.long_pos = round(self.long_pos, 7) self.pos = round(self.pos, 7) + self.write_log(f'多仓:{pre_long_pos}->{self.long_pos}') + self.write_log(f'净:{pre_pos}->{self.pos}') + + return True def clear(self):