[update] 一般更新

This commit is contained in:
msincenselee 2022-01-25 16:09:20 +08:00
parent e260c16795
commit 7104a2fe0b
7 changed files with 53 additions and 18 deletions

View File

@ -63,6 +63,7 @@ class AlgoEngine(BaseEngine):
from .algos.dma_algo import DmaAlgo
from .algos.arbitrage_algo import ArbitrageAlgo
from .algos.spread_algo_v2 import SpreadAlgoV2
from .algos.autostopwin_algo import AutoStopWinAlgo
self.add_algo_template(TwapAlgo)
self.add_algo_template(IcebergAlgo)
@ -73,6 +74,7 @@ class AlgoEngine(BaseEngine):
self.add_algo_template(DmaAlgo)
self.add_algo_template(ArbitrageAlgo)
self.add_algo_template(SpreadAlgoV2)
self.add_algo_template(AutoStopWinAlgo)
def add_algo_template(self, template: AlgoTemplate):
""""""
@ -180,7 +182,8 @@ class AlgoEngine(BaseEngine):
def stop_all(self):
""""""
for algo_name in list(self.algos.keys()):
self.stop_algo(algo_name)
if self.stop_algo(algo_name):
self.main_engine.write_log(f'{algo_name}已停止')
def subscribe(self, algo: AlgoTemplate, vt_symbol: str):
""""""
@ -215,7 +218,7 @@ class AlgoEngine(BaseEngine):
contract = self.main_engine.get_contract(vt_symbol)
if not contract:
self.write_log(f'委托下单失败,找不到合约:{vt_symbol}', algo_name=algo.algo_name)
return
return []
volume = round_to(volume, contract.min_volume)
if not volume:

View File

@ -104,12 +104,10 @@ STOP_STATUS_MAP = {
# 假期后续可以从cta_option_config.json文件中获取更新
holiday_dict = {
# 放假第一天:放假最后一天
"2000124": "20200130",
"20200501": "20200505",
"20201001": "20201008",
"20210211": "20210217",
"20210501": "20210505",
"20211001": "20211007",
"20220131": "20220206",
"20220430": "20220504",
"20221001": "20221007",
# updated by 黄健威 2022.01.07
}

View File

@ -142,9 +142,9 @@ class BackTestingEngine(object):
self.holdings = {} # 多空持仓
# 当前最新数据,用于模拟成交用
self.gateway_name = u'BackTest'
# 当前最新数据,用于模拟成交用
self.last_bar = {} # 最新的bar
self.last_tick = {} # 最新tick
self.last_dt = None # 最新时间
@ -158,7 +158,7 @@ class BackTestingEngine(object):
# 回测计算相关
self.use_margin = True # 使用保证金模式(期货使用,计算保证金时,按照开仓价计算。股票是按照当前价计算)
self.force_cross = False # 强制撮合成功,不使用价格比对,一般用于模拟市价成交
self.init_capital = 1000000 # 期初资金
self.cur_capital = self.init_capital # 当前资金净值
self.net_capital = self.init_capital # 实时资金净值每日根据capital和持仓浮盈计算
@ -604,6 +604,11 @@ class BackTestingEngine(object):
# 缺省使用保证金方式。(期货使用保证金/股票不使用保证金)
self.use_margin = test_setting.get('use_margin', True)
if 'force_cross' in test_setting:
self.force_cross = test_setting.get('force_cross', False)
if self.force_cross:
self.write_log(f'使用强制撮合模式!')
# 设置最大资金使用比例
if 'percent_limit' in test_setting:
self.write_log(u'设置最大资金使用比例:{}%'.format(test_setting.get('percent_limit')))
@ -645,6 +650,7 @@ class BackTestingEngine(object):
# 创建资金K线
self.create_fund_kline(self.test_name, use_renko=test_setting.get('use_renko', False))
# 自动输出日线净值曲线图png文件
self.is_plot_daily = test_setting.get('is_plot_daily', False)
# 加载所有本地策略class
@ -1293,8 +1299,8 @@ class BackTestingEngine(object):
sell_best_cross_price = tick.last_price
# 判断是否会成交
buy_cross = order.direction == Direction.LONG and order.price >= buy_cross_price
sell_cross = order.direction == Direction.SHORT and order.price <= sell_cross_price
buy_cross = order.direction == Direction.LONG and (order.price >= buy_cross_price or self.force_cross)
sell_cross = order.direction == Direction.SHORT and (order.price <= sell_cross_price or self.force_cross)
# 如果发生了成交
if buy_cross or sell_cross:
@ -1321,9 +1327,9 @@ class BackTestingEngine(object):
# 2. 假设在上一根K线结束(也是当前K线开始)的时刻策略发出的委托为限价105
# 3. 则在实际中的成交价会是100而不是105因为委托发出时市场的最优价格是100
if buy_cross:
trade_price = min(order.price, buy_best_cross_price)
trade_price = min(order.price, buy_best_cross_price) if not self.force_cross else order.price
else:
trade_price = max(order.price, sell_best_cross_price)
trade_price = max(order.price, sell_best_cross_price) if not self.force_cross else order.price
# renko bar较为特殊使用委托价进行成交
if trade.vt_symbol.startswith('future_renko'):

View File

@ -160,6 +160,12 @@ class PortfolioTestingEngine(BackTestingEngine):
self.use_pkb2 = test_setting.get('use_pkb2', True)
if self.use_tq:
self.use_pkb2 = False
self.output(f'使用天勤数据')
if self.use_pkb2:
self.output(f'使用pkb2压缩格式')
else:
self.output(f'使用csv文件格式')
def prepare_data(self, data_dict):
"""
@ -282,6 +288,7 @@ class PortfolioTestingEngine(BackTestingEngine):
bar.low_time = bar_data.get('low_time', None) # 最后一次进入低位区域的时间
bar.high_time = bar_data.get('high_time', None) # 最后一次进入高位区域的时间
else:
# 读取的bar是以bar结束时间作为datetimevnpy是以bar开始时间作为bar datetime
bar_datetime = dt - timedelta(seconds=self.bar_interval_seconds)
bar = BarData(
@ -400,7 +407,7 @@ class PortfolioTestingEngine(BackTestingEngine):
return None
df = pd.read_csv(file_path, encoding='gbk', parse_dates=False)
df.columns = ['date', 'time', 'last_price', 'volume', 'last_volume', 'open_interest',
df.columns = ['date', 'time', 'last_price', 'last_volume', 'volume', 'open_interest',
'bid_price_1', 'bid_volume_1', 'bid_price_2', 'bid_volume_2', 'bid_price_3', 'bid_volume_3',
'ask_price_1', 'ask_volume_1', 'ask_price_2', 'ask_volume_2', 'ask_price_3', 'ask_volume_3', 'BS']

View File

@ -323,7 +323,7 @@ class SpreadTestingEngine(BackTestingEngine):
symbol, exchange = extract_vt_symbol(vt_symbol)
underly_symbol = get_underlying_symbol(symbol)
exchange_folder = VN_EXCHANGE_TICKFOLDER_MAP.get(exchange.value)
exchange_folder = VN_EXCHANGE_TICKFOLDER_MAP.get(exchange.value,'LOCAL')
if exchange == Exchange.INE:
file_path = os.path.abspath(

View File

@ -627,6 +627,16 @@ def check_chan_xt_nine_bi(kline, bi_list: List[ChanObject]):
if bi_9.high > gg > zg > bi_9.low > zd:
return ChanSignals.Q2L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二买', v2='九笔')
if min_low == bi_7.low and max_high == bi_1.high and bi_6.high < bi_2.low: # 前7笔构成向下类趋势
zd = max([x.low for x in [bi_5, bi_6]])
zg = min([x.high for x in [bi_4, bi_6]])
gg = max([x.high for x in [bi_4, bi_6]])
if zg > zd and bi_8.high > gg == bi_4.high : # 456构成中枢7离开中枢8反包且8的高点大于gg,4高 >6高点
atan = (bi_4.high - bi_6.high) / (bi_5.bars + bi_6.bars - 1)
p = bi_6.high - atan * (bi_7.bars + bi_8.bars + bi_9.bars - 2)
if zd > bi_9.low > p:
return ChanSignals.Q2L0.value
elif direction == 1:
# 倒9笔是最高点倒一笔是最低点
@ -688,8 +698,8 @@ def check_chan_xt_nine_bi(kline, bi_list: List[ChanObject]):
# 参考双重顶或者圆弧顶, 在 bi_5.low => bi_7.low => p点 形成一条斜线如果bi_9.high 在斜线之下,就是三卖
if dd == bi_5.low and zd == bi_7.low:
atan = (zd - dd) / (bi_5.bars + bi_6.bars)
p = bi_7.low + atan * (bi_7.bars + bi_8.bars + bi_9.bars)
atan = (zd - dd) / (bi_5.bars + bi_6.bars - 1)
p = bi_7.low + atan * (bi_7.bars + bi_8.bars + bi_9.bars - 2)
if bi_9.high < p:
return ChanSignals.Q3S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类三卖', v2='九笔ZD三卖')
@ -697,6 +707,16 @@ def check_chan_xt_nine_bi(kline, bi_list: List[ChanObject]):
if dd < zd <= bi_9.high < zg:
return ChanSignals.Q2S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二卖', v2='九笔')
if min_low == bi_1.low and max_high == bi_7.high and bi_2.high < bi_6.low: # 前7笔形成上涨趋势
zd = max([x.low for x in [bi_4, bi_6]])
zg = min([x.high for x in [bi_4, bi_6]])
dd = min([x.low for x in [bi_4, bi_6]])
if zg > zd and bi_8.low < dd == bi_4.low: # 456构成中枢7离开中枢8反包且8的低点小于dd,4低点< 6低点
atan = (bi_6.low - bi_4.low) / (bi_5.bars + bi_6.bars -1)
p = bi_6.low + atan * (bi_7.bars + bi_8.bars + bi_9.bars - 2)
if zg < bi_9.high < p:
return ChanSignals.Q2S0.value
return v

View File

@ -337,6 +337,7 @@ class ContractData(BaseData):
option_underlying: str = "" # vt_symbol of underlying contract
option_type: OptionType = None
option_expiry: datetime = None
option_portfolio: str = ""
option_index: str = "" # vt_symbol mapping cur option
def __post_init__(self):