[update] 一般更新
This commit is contained in:
parent
e260c16795
commit
7104a2fe0b
@ -63,6 +63,7 @@ class AlgoEngine(BaseEngine):
|
|||||||
from .algos.dma_algo import DmaAlgo
|
from .algos.dma_algo import DmaAlgo
|
||||||
from .algos.arbitrage_algo import ArbitrageAlgo
|
from .algos.arbitrage_algo import ArbitrageAlgo
|
||||||
from .algos.spread_algo_v2 import SpreadAlgoV2
|
from .algos.spread_algo_v2 import SpreadAlgoV2
|
||||||
|
from .algos.autostopwin_algo import AutoStopWinAlgo
|
||||||
|
|
||||||
self.add_algo_template(TwapAlgo)
|
self.add_algo_template(TwapAlgo)
|
||||||
self.add_algo_template(IcebergAlgo)
|
self.add_algo_template(IcebergAlgo)
|
||||||
@ -73,6 +74,7 @@ class AlgoEngine(BaseEngine):
|
|||||||
self.add_algo_template(DmaAlgo)
|
self.add_algo_template(DmaAlgo)
|
||||||
self.add_algo_template(ArbitrageAlgo)
|
self.add_algo_template(ArbitrageAlgo)
|
||||||
self.add_algo_template(SpreadAlgoV2)
|
self.add_algo_template(SpreadAlgoV2)
|
||||||
|
self.add_algo_template(AutoStopWinAlgo)
|
||||||
|
|
||||||
def add_algo_template(self, template: AlgoTemplate):
|
def add_algo_template(self, template: AlgoTemplate):
|
||||||
""""""
|
""""""
|
||||||
@ -180,7 +182,8 @@ class AlgoEngine(BaseEngine):
|
|||||||
def stop_all(self):
|
def stop_all(self):
|
||||||
""""""
|
""""""
|
||||||
for algo_name in list(self.algos.keys()):
|
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):
|
def subscribe(self, algo: AlgoTemplate, vt_symbol: str):
|
||||||
""""""
|
""""""
|
||||||
@ -215,7 +218,7 @@ class AlgoEngine(BaseEngine):
|
|||||||
contract = self.main_engine.get_contract(vt_symbol)
|
contract = self.main_engine.get_contract(vt_symbol)
|
||||||
if not contract:
|
if not contract:
|
||||||
self.write_log(f'委托下单失败,找不到合约:{vt_symbol}', algo_name=algo.algo_name)
|
self.write_log(f'委托下单失败,找不到合约:{vt_symbol}', algo_name=algo.algo_name)
|
||||||
return
|
return []
|
||||||
|
|
||||||
volume = round_to(volume, contract.min_volume)
|
volume = round_to(volume, contract.min_volume)
|
||||||
if not volume:
|
if not volume:
|
||||||
|
@ -104,12 +104,10 @@ STOP_STATUS_MAP = {
|
|||||||
# 假期,后续可以从cta_option_config.json文件中获取更新
|
# 假期,后续可以从cta_option_config.json文件中获取更新
|
||||||
holiday_dict = {
|
holiday_dict = {
|
||||||
# 放假第一天:放假最后一天
|
# 放假第一天:放假最后一天
|
||||||
"2000124": "20200130",
|
"20220131": "20220206",
|
||||||
"20200501": "20200505",
|
"20220430": "20220504",
|
||||||
"20201001": "20201008",
|
"20221001": "20221007",
|
||||||
"20210211": "20210217",
|
# updated by 黄健威 2022.01.07
|
||||||
"20210501": "20210505",
|
|
||||||
"20211001": "20211007",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -142,9 +142,9 @@ class BackTestingEngine(object):
|
|||||||
|
|
||||||
self.holdings = {} # 多空持仓
|
self.holdings = {} # 多空持仓
|
||||||
|
|
||||||
# 当前最新数据,用于模拟成交用
|
|
||||||
self.gateway_name = u'BackTest'
|
self.gateway_name = u'BackTest'
|
||||||
|
|
||||||
|
# 当前最新数据,用于模拟成交用
|
||||||
self.last_bar = {} # 最新的bar
|
self.last_bar = {} # 最新的bar
|
||||||
self.last_tick = {} # 最新tick
|
self.last_tick = {} # 最新tick
|
||||||
self.last_dt = None # 最新时间
|
self.last_dt = None # 最新时间
|
||||||
@ -158,7 +158,7 @@ class BackTestingEngine(object):
|
|||||||
|
|
||||||
# 回测计算相关
|
# 回测计算相关
|
||||||
self.use_margin = True # 使用保证金模式(期货使用,计算保证金时,按照开仓价计算。股票是按照当前价计算)
|
self.use_margin = True # 使用保证金模式(期货使用,计算保证金时,按照开仓价计算。股票是按照当前价计算)
|
||||||
|
self.force_cross = False # 强制撮合成功,不使用价格比对,一般用于模拟市价成交
|
||||||
self.init_capital = 1000000 # 期初资金
|
self.init_capital = 1000000 # 期初资金
|
||||||
self.cur_capital = self.init_capital # 当前资金净值
|
self.cur_capital = self.init_capital # 当前资金净值
|
||||||
self.net_capital = self.init_capital # 实时资金净值(每日根据capital和持仓浮盈计算)
|
self.net_capital = self.init_capital # 实时资金净值(每日根据capital和持仓浮盈计算)
|
||||||
@ -604,6 +604,11 @@ class BackTestingEngine(object):
|
|||||||
# 缺省使用保证金方式。(期货使用保证金/股票不使用保证金)
|
# 缺省使用保证金方式。(期货使用保证金/股票不使用保证金)
|
||||||
self.use_margin = test_setting.get('use_margin', True)
|
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:
|
if 'percent_limit' in test_setting:
|
||||||
self.write_log(u'设置最大资金使用比例:{}%'.format(test_setting.get('percent_limit')))
|
self.write_log(u'设置最大资金使用比例:{}%'.format(test_setting.get('percent_limit')))
|
||||||
@ -645,6 +650,7 @@ class BackTestingEngine(object):
|
|||||||
# 创建资金K线
|
# 创建资金K线
|
||||||
self.create_fund_kline(self.test_name, use_renko=test_setting.get('use_renko', False))
|
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)
|
self.is_plot_daily = test_setting.get('is_plot_daily', False)
|
||||||
|
|
||||||
# 加载所有本地策略class
|
# 加载所有本地策略class
|
||||||
@ -1293,8 +1299,8 @@ class BackTestingEngine(object):
|
|||||||
sell_best_cross_price = tick.last_price
|
sell_best_cross_price = tick.last_price
|
||||||
|
|
||||||
# 判断是否会成交
|
# 判断是否会成交
|
||||||
buy_cross = order.direction == Direction.LONG and order.price >= buy_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
|
sell_cross = order.direction == Direction.SHORT and (order.price <= sell_cross_price or self.force_cross)
|
||||||
|
|
||||||
# 如果发生了成交
|
# 如果发生了成交
|
||||||
if buy_cross or sell_cross:
|
if buy_cross or sell_cross:
|
||||||
@ -1321,9 +1327,9 @@ class BackTestingEngine(object):
|
|||||||
# 2. 假设在上一根K线结束(也是当前K线开始)的时刻,策略发出的委托为限价105
|
# 2. 假设在上一根K线结束(也是当前K线开始)的时刻,策略发出的委托为限价105
|
||||||
# 3. 则在实际中的成交价会是100而不是105,因为委托发出时市场的最优价格是100
|
# 3. 则在实际中的成交价会是100而不是105,因为委托发出时市场的最优价格是100
|
||||||
if buy_cross:
|
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:
|
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较为特殊,使用委托价进行成交
|
# renko bar较为特殊,使用委托价进行成交
|
||||||
if trade.vt_symbol.startswith('future_renko'):
|
if trade.vt_symbol.startswith('future_renko'):
|
||||||
|
@ -160,6 +160,12 @@ class PortfolioTestingEngine(BackTestingEngine):
|
|||||||
self.use_pkb2 = test_setting.get('use_pkb2', True)
|
self.use_pkb2 = test_setting.get('use_pkb2', True)
|
||||||
if self.use_tq:
|
if self.use_tq:
|
||||||
self.use_pkb2 = False
|
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):
|
def prepare_data(self, data_dict):
|
||||||
"""
|
"""
|
||||||
@ -282,6 +288,7 @@ class PortfolioTestingEngine(BackTestingEngine):
|
|||||||
bar.low_time = bar_data.get('low_time', None) # 最后一次进入低位区域的时间
|
bar.low_time = bar_data.get('low_time', None) # 最后一次进入低位区域的时间
|
||||||
bar.high_time = bar_data.get('high_time', None) # 最后一次进入高位区域的时间
|
bar.high_time = bar_data.get('high_time', None) # 最后一次进入高位区域的时间
|
||||||
else:
|
else:
|
||||||
|
# 读取的bar是以bar结束时间作为datetime,vnpy是以bar开始时间作为bar datetime
|
||||||
bar_datetime = dt - timedelta(seconds=self.bar_interval_seconds)
|
bar_datetime = dt - timedelta(seconds=self.bar_interval_seconds)
|
||||||
|
|
||||||
bar = BarData(
|
bar = BarData(
|
||||||
@ -400,7 +407,7 @@ class PortfolioTestingEngine(BackTestingEngine):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
df = pd.read_csv(file_path, encoding='gbk', parse_dates=False)
|
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',
|
'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']
|
'ask_price_1', 'ask_volume_1', 'ask_price_2', 'ask_volume_2', 'ask_price_3', 'ask_volume_3', 'BS']
|
||||||
|
|
||||||
|
@ -323,7 +323,7 @@ class SpreadTestingEngine(BackTestingEngine):
|
|||||||
|
|
||||||
symbol, exchange = extract_vt_symbol(vt_symbol)
|
symbol, exchange = extract_vt_symbol(vt_symbol)
|
||||||
underly_symbol = get_underlying_symbol(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:
|
if exchange == Exchange.INE:
|
||||||
file_path = os.path.abspath(
|
file_path = os.path.abspath(
|
||||||
|
@ -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:
|
if bi_9.high > gg > zg > bi_9.low > zd:
|
||||||
return ChanSignals.Q2L0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二买', v2='九笔')
|
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:
|
elif direction == 1:
|
||||||
|
|
||||||
# 倒9笔是最高点,倒一笔是最低点
|
# 倒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 在斜线之下,就是三卖
|
# 参考双重顶或者圆弧顶, 在 bi_5.low => bi_7.low => p点 形成一条斜线,如果bi_9.high 在斜线之下,就是三卖
|
||||||
if dd == bi_5.low and zd == bi_7.low:
|
if dd == bi_5.low and zd == bi_7.low:
|
||||||
atan = (zd - dd) / (bi_5.bars + bi_6.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)
|
p = bi_7.low + atan * (bi_7.bars + bi_8.bars + bi_9.bars - 2)
|
||||||
if bi_9.high < p:
|
if bi_9.high < p:
|
||||||
return ChanSignals.Q3S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类三卖', v2='九笔ZD三卖')
|
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:
|
if dd < zd <= bi_9.high < zg:
|
||||||
return ChanSignals.Q2S0.value # Signal(k1=freq.value, k2=di_name, k3='类买卖点', v1='类二卖', v2='九笔')
|
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
|
return v
|
||||||
|
|
||||||
|
|
||||||
|
@ -337,6 +337,7 @@ class ContractData(BaseData):
|
|||||||
option_underlying: str = "" # vt_symbol of underlying contract
|
option_underlying: str = "" # vt_symbol of underlying contract
|
||||||
option_type: OptionType = None
|
option_type: OptionType = None
|
||||||
option_expiry: datetime = None
|
option_expiry: datetime = None
|
||||||
|
option_portfolio: str = ""
|
||||||
option_index: str = "" # vt_symbol mapping cur option
|
option_index: str = "" # vt_symbol mapping cur option
|
||||||
|
|
||||||
def __post_init__(self):
|
def __post_init__(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user