[bug fix]

This commit is contained in:
msincenselee 2021-09-27 15:20:10 +08:00
parent 8c395d72ab
commit f7e94a8a0b
7 changed files with 86 additions and 44 deletions

View File

@ -35,7 +35,7 @@ if __name__ == "__main__":
# 获取某个合约得的分时数据,周期是15分钟返回数据类型是barData # 获取某个合约得的分时数据,周期是15分钟返回数据类型是barData
print('加载数据') print('加载数据')
bars, msg = get_stock_bars(vt_symbol=vt_symbol, freq=bar_freq) bars, msg = get_stock_bars(vt_symbol=vt_symbol, freq=bar_freq,start_date='2021-03-01')
# 创建一个15分钟bar的 kline对象 # 创建一个15分钟bar的 kline对象
setting = {} setting = {}

View File

@ -6,7 +6,7 @@ from vnpy.amqp.consumer import subscriber
if __name__ == '__main__': if __name__ == '__main__':
from time import sleep from time import sleep
c = subscriber(user='admin', password='admin', exchange='x_fanout_md_tick') c = subscriber(host='192.168.1.211',user='admin', password='admin', exchange='x_fanout_idx_tick')
c.subscribe() c.subscribe()

View File

@ -222,7 +222,10 @@ 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_datetime = dt - timedelta(seconds=self.bar_interval_seconds) # 如果数据源是bar时间end标识得需要扣减bar得时间
# bar_datetime = dt - timedelta(seconds=self.bar_interval_seconds)
# 如果数据源是bar时间start标识就不需要扣减bar时间
bar_datetime = dt
bar = BarData( bar = BarData(
gateway_name='backtesting', gateway_name='backtesting',

View File

@ -11,7 +11,7 @@ from abc import ABC
from copy import copy,deepcopy from copy import copy,deepcopy
from typing import Any, Callable, List, Dict from typing import Any, Callable, List, Dict
from logging import INFO, ERROR from logging import INFO, ERROR
from datetime import datetime from datetime import datetime,timedelta
from vnpy.trader.constant import Interval, Direction, Offset, Status, OrderType, Exchange, Color from vnpy.trader.constant import Interval, Direction, Offset, Status, OrderType, Exchange, Color
from vnpy.trader.object import BarData, TickData, OrderData, TradeData, PositionData from vnpy.trader.object import BarData, TickData, OrderData, TradeData, PositionData
from vnpy.trader.utility import virtual, append_data, extract_vt_symbol, get_underlying_symbol, round_to from vnpy.trader.utility import virtual, append_data, extract_vt_symbol, get_underlying_symbol, round_to
@ -741,6 +741,25 @@ class CtaStockTemplate(CtaTemplate):
if dt: if dt:
self.policy.cur_trading_date = dt.strftime('%Y-%m-%d') self.policy.cur_trading_date = dt.strftime('%Y-%m-%d')
def check_adjust(self, vt_symbol):
"""
检查股票的最新除权时间是否在一周内
:param vt_symbol:
:return: True: 一周内没有发生除权 False一周内发生过除权
"""
last_adjust_factor = self.cta_engine.get_adjust_factor(vt_symbol)
if last_adjust_factor is None:
return True
last_adjust_date = last_adjust_factor.get('dividOperateDate', None)
# 最后在除权出息日,发生在一周内
if last_adjust_date and (datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d') <= last_adjust_date:
self.write_log(
'{}[{}]发生除权除息,日期:{}'.format(vt_symbol, last_adjust_factor.get('name'), last_adjust_date))
return False
return True
def after_trading(self): def after_trading(self):
"""收盘后调用一次""" """收盘后调用一次"""
self.write_log(f'{self.strategy_name}收盘后调用') self.write_log(f'{self.strategy_name}收盘后调用')

View File

@ -30,7 +30,7 @@ from vnpy.component.cta_period import CtaPeriod, Period
from vnpy.trader.object import BarData, TickData from vnpy.trader.object import BarData, TickData
from vnpy.trader.constant import Interval, Color, ChanSignals from vnpy.trader.constant import Interval, Color, ChanSignals
from vnpy.trader.utility import round_to, get_trading_date, get_underlying_symbol from vnpy.trader.utility import round_to, get_trading_date, get_underlying_symbol
from vnpy.component.cta_utility import check_chan_xt,check_chan_xt_three_bi, check_qsbc_2nd from vnpy.component.cta_utility import check_chan_xt, check_chan_xt_three_bi, check_qsbc_2nd
try: try:
from vnpy.component.chanlun import ChanGraph, ChanLibrary from vnpy.component.chanlun import ChanGraph, ChanLibrary
@ -231,8 +231,7 @@ class CtaLineBar(object):
self.minute_interval = None # 把各个周期的bar转换为分钟在first_tick中用来修正bar为整点分钟周期 self.minute_interval = None # 把各个周期的bar转换为分钟在first_tick中用来修正bar为整点分钟周期
if setting: if setting:
self.set_params(setting) self.set_params(setting)
if self.is_stock:
self.is_7x24 = True
# 修正self.minute_interval # 修正self.minute_interval
if self.interval == Interval.SECOND: if self.interval == Interval.SECOND:
@ -839,9 +838,9 @@ class CtaLineBar(object):
return return
# 过滤一些 异常的tick价格 # 过滤一些 异常的tick价格
if self.cur_price is not None and self.cur_price !=0 and tick.last_price is not None and tick.last_price != 0: if self.cur_price is not None and self.cur_price != 0 and tick.last_price is not None and tick.last_price != 0:
# 前后价格超过10% # 前后价格超过10%
if abs(tick.last_price - self.cur_price)/self.cur_price >= 0.1: if abs(tick.last_price - self.cur_price) / self.cur_price >= 0.1:
# 是同一天,都不接受这些tick # 是同一天,都不接受这些tick
if self.cur_datetime and self.cur_datetime.date == tick.datetime.date: if self.cur_datetime and self.cur_datetime.date == tick.datetime.date:
return return
@ -852,7 +851,7 @@ class CtaLineBar(object):
return return
self.cur_datetime = tick.datetime self.cur_datetime = tick.datetime
self.cur_tick = tick #copy.copy(tick) self.cur_tick = tick # copy.copy(tick)
# 兼容 标准套利合约它没有last_price # 兼容 标准套利合约它没有last_price
if self.cur_tick.last_price is None or self.cur_tick.last_price == 0: if self.cur_tick.last_price is None or self.cur_tick.last_price == 0:
@ -888,7 +887,7 @@ class CtaLineBar(object):
self.cur_datetime = bar.datetime + timedelta(minutes=bar_freq) self.cur_datetime = bar.datetime + timedelta(minutes=bar_freq)
if self.bar_len == 0: if self.bar_len == 0:
#new_bar = copy.deepcopy(bar) # new_bar = copy.deepcopy(bar)
self.line_bar.append(bar) self.line_bar.append(bar)
self.cur_trading_day = bar.trading_day self.cur_trading_day = bar.trading_day
self.on_bar(bar) self.on_bar(bar)
@ -934,7 +933,7 @@ class CtaLineBar(object):
if is_new_bar: if is_new_bar:
# 添加新的bar # 添加新的bar
#new_bar = copy.deepcopy(bar) # new_bar = copy.deepcopy(bar)
self.line_bar.append(bar) # new_bar self.line_bar.append(bar) # new_bar
# 将上一个Bar推送至OnBar事件 # 将上一个Bar推送至OnBar事件
self.on_bar(lastBar) self.on_bar(lastBar)
@ -6269,15 +6268,15 @@ class CtaLineBar(object):
'signal': signal}) 'signal': signal})
if len(xt_signals) > 200: if len(xt_signals) > 200:
del xt_signals[0] del xt_signals[0]
if cur_signal is not None and self.export_xt_filename : if cur_signal is not None and self.export_xt_filename:
self.append_data( self.append_data(
file_name=self.export_xt_filename.replace('_n_',f'_{n}_'), file_name=self.export_xt_filename.replace('_n_', f'_{n}_'),
dict_data=cur_signal, dict_data=cur_signal,
field_names=["start", "end", "price", "signal"] field_names=["start", "end", "price", "signal"]
) )
# 直接更新 # 直接更新
else: else:
xt_signals[-1].update({'end': self.cur_bi.end, 'price': price,'signal': signal}) xt_signals[-1].update({'end': self.cur_bi.end, 'price': price, 'signal': signal})
# 是否趋势二买 # 是否趋势二买
qsbc_2nd = ChanSignals.Other.value qsbc_2nd = ChanSignals.Other.value
@ -6285,7 +6284,7 @@ class CtaLineBar(object):
if check_qsbc_2nd(big_kline=self, small_kline=None, signal_direction=Direction.LONG): if check_qsbc_2nd(big_kline=self, small_kline=None, signal_direction=Direction.LONG):
qsbc_2nd = ChanSignals.Q2L0.value qsbc_2nd = ChanSignals.Q2L0.value
else: else:
if check_qsbc_2nd(big_kline=self, small_kline=None,signal_direction=Direction.SHORT): if check_qsbc_2nd(big_kline=self, small_kline=None, signal_direction=Direction.SHORT):
qsbc_2nd = ChanSignals.Q2S0.value qsbc_2nd = ChanSignals.Q2S0.value
cur_signal = self.xt_2nd_signals[-1] if len(self.xt_2nd_signals) > 0 else None cur_signal = self.xt_2nd_signals[-1] if len(self.xt_2nd_signals) > 0 else None
# 不同笔开始时间 # 不同笔开始时间
@ -6305,8 +6304,6 @@ class CtaLineBar(object):
else: else:
self.xt_2nd_signals[-1].update({'end': self.cur_bi.end, 'price': price, 'signal': qsbc_2nd}) self.xt_2nd_signals[-1].update({'end': self.cur_bi.end, 'price': price, 'signal': qsbc_2nd})
def write_log(self, content): def write_log(self, content):
"""记录CTA日志""" """记录CTA日志"""
self.strategy.write_log(u'[' + self.name + u']' + content) self.strategy.write_log(u'[' + self.name + u']' + content)
@ -6512,7 +6509,7 @@ class CtaLineBar(object):
'type': 'line' 'type': 'line'
} }
indicators.update({indicator.get('name'): copy.copy(indicator)}) indicators.update({indicator.get('name'): copy.copy(indicator)})
if getattr(self,'para_ema4_len',0) > 0: #isinstance(self.para_ema4_len, int) and self.para_ema4_len > 0: if getattr(self, 'para_ema4_len', 0) > 0: # isinstance(self.para_ema4_len, int) and self.para_ema4_len > 0:
indicator = { indicator = {
'name': 'EMA{}'.format(self.para_ema4_len), 'name': 'EMA{}'.format(self.para_ema4_len),
'attr_name': 'line_ema4', 'attr_name': 'line_ema4',
@ -6520,7 +6517,7 @@ class CtaLineBar(object):
'type': 'line' 'type': 'line'
} }
indicators.update({indicator.get('name'): copy.copy(indicator)}) indicators.update({indicator.get('name'): copy.copy(indicator)})
if getattr(self, 'para_ema5_len',0) > 0: #isinstance(self.para_ema5_len, int) and self.para_ema5_len > 0: if getattr(self, 'para_ema5_len', 0) > 0: # isinstance(self.para_ema5_len, int) and self.para_ema5_len > 0:
indicator = { indicator = {
'name': 'EMA{}'.format(self.para_ema5_len), 'name': 'EMA{}'.format(self.para_ema5_len),
'attr_name': 'line_ema5', 'attr_name': 'line_ema5',
@ -6936,7 +6933,7 @@ class CtaMinuteBar(CtaLineBar):
def add_bar(self, bar, bar_is_completed=False, bar_freq=1): def add_bar(self, bar, bar_is_completed=False, bar_freq=1):
""" """
予以外部初始化程序增加bar CtaMinuteBar予以外部初始化程序增加bar
:param bar: :param bar:
:param bar_is_completed: 插入的bar其周期与K线周期一致就设为True :param bar_is_completed: 插入的bar其周期与K线周期一致就设为True
:param bar_freq, bar对象得frequency :param bar_freq, bar对象得frequency
@ -6975,9 +6972,12 @@ class CtaMinuteBar(CtaLineBar):
if bar_is_completed: if bar_is_completed:
is_new_bar = True is_new_bar = True
minutes_passed = (bar.datetime - datetime.strptime(bar.datetime.strftime('%Y-%m-%d'), if self.cur_trading_day > bar.trading_day:
'%Y-%m-%d')).total_seconds() / 60 is_new_bar = True
if self.underly_symbol in MARKET_ZJ:
minutes_passed = bar.datetime.hour * 60 + bar.datetime.minute
if self.underly_symbol in MARKET_ZJ or self.is_stock:
if int(bar.datetime.strftime('%H%M')) > 1130 and int(bar.datetime.strftime('%H%M')) < 1600: if int(bar.datetime.strftime('%H%M')) > 1130 and int(bar.datetime.strftime('%H%M')) < 1600:
# 扣除11:30到13:00的中场休息的90分钟 # 扣除11:30到13:00的中场休息的90分钟
minutes_passed = minutes_passed - 90 minutes_passed = minutes_passed - 90
@ -6988,10 +6988,11 @@ class CtaMinuteBar(CtaLineBar):
elif int(bar.datetime.strftime('%H%M')) > 1130 and int(bar.datetime.strftime('%H%M')) < 1600: elif int(bar.datetime.strftime('%H%M')) > 1130 and int(bar.datetime.strftime('%H%M')) < 1600:
# 扣除(10:15到10:30的中场休息的15分钟)&(11:30到13:30的中场休息的120分钟) # 扣除(10:15到10:30的中场休息的15分钟)&(11:30到13:30的中场休息的120分钟)
minutes_passed = minutes_passed - 135 minutes_passed = minutes_passed - 135
bars_passed = int(minutes_passed / self.bar_interval) bars_passed = int(minutes_passed / self.bar_interval)
# 不在同一交易日推入新bar # 不在同一交易日推入新bar
if self.cur_trading_day != bar.trading_day: if self.cur_trading_day > bar.trading_day:
is_new_bar = True is_new_bar = True
self.cur_trading_day = bar.trading_day self.cur_trading_day = bar.trading_day
self.bars_count = bars_passed self.bars_count = bars_passed
@ -7005,12 +7006,8 @@ class CtaMinuteBar(CtaLineBar):
# self.write_log("addBar(): {}, bars_count={}".format(bar.datetime.strftime("%Y%m%d %H:%M:%S"), # self.write_log("addBar(): {}, bars_count={}".format(bar.datetime.strftime("%Y%m%d %H:%M:%S"),
# self.bars_count)) # self.bars_count))
# 数字货币如果bar的前后距离超过周期重新开启一个新的bar
if self.is_7x24 and (bar.datetime - lastBar.datetime).total_seconds() >= 60 * self.bar_interval:
is_new_bar = True
if is_new_bar: if is_new_bar:
#new_bar = copy.deepcopy(bar) # new_bar = copy.deepcopy(bar)
# 添加新的bar # 添加新的bar
self.line_bar.append(bar) # new_bar self.line_bar.append(bar) # new_bar
# 将上一个Bar推送至OnBar事件 # 将上一个Bar推送至OnBar事件
@ -7038,17 +7035,18 @@ class CtaMinuteBar(CtaLineBar):
minutes_passed = tick.datetime.hour * 60 + tick.datetime.minute minutes_passed = tick.datetime.hour * 60 + tick.datetime.minute
if self.underly_symbol in MARKET_ZJ: if self.is_stock or self.underly_symbol in MARKET_ZJ:
if int(tick.datetime.strftime('%H%M')) > 1130 and int(tick.datetime.strftime('%H%M')) < 1600: if int(tick.datetime.strftime('%H%M')) > 1130 and int(tick.datetime.strftime('%H%M')) < 1600:
# 扣除11:30到13:00的中场休息的90分钟 # 扣除11:30到13:00的中场休息的90分钟
minutes_passed = minutes_passed - 90 minutes_passed = minutes_passed - 90
else: elif not self.is_7x24:
if int(tick.datetime.strftime('%H%M')) > 1015 and int(tick.datetime.strftime('%H%M')) <= 1130: if int(tick.datetime.strftime('%H%M')) > 1015 and int(tick.datetime.strftime('%H%M')) <= 1130:
# 扣除10:15到10:30的中场休息的15分钟 # 扣除10:15到10:30的中场休息的15分钟
minutes_passed = minutes_passed - 15 minutes_passed = minutes_passed - 15
elif int(tick.datetime.strftime('%H%M')) > 1130 and int(tick.datetime.strftime('%H%M')) < 1600: elif int(tick.datetime.strftime('%H%M')) > 1130 and int(tick.datetime.strftime('%H%M')) < 1600:
# 扣除(10:15到10:30的中场休息的15分钟)&(11:30到13:30的中场休息的120分钟) # 扣除(10:15到10:30的中场休息的15分钟)&(11:30到13:30的中场休息的120分钟)
minutes_passed = minutes_passed - 135 minutes_passed = minutes_passed - 135
bars_passed = int(minutes_passed / self.bar_interval) bars_passed = int(minutes_passed / self.bar_interval)
# 保存第一个K线数据 # 保存第一个K线数据
@ -7451,7 +7449,7 @@ class CtaDayBar(CtaLineBar):
bar_len = len(self.line_bar) bar_len = len(self.line_bar)
if bar_len == 0: if bar_len == 0:
#new_bar = copy.deepcopy(bar) # new_bar = copy.deepcopy(bar)
self.line_bar.append(bar) # new_bar self.line_bar.append(bar) # new_bar
self.cur_trading_day = bar.trading_day if bar.trading_day is not None else get_trading_date(bar.datetime) self.cur_trading_day = bar.trading_day if bar.trading_day is not None else get_trading_date(bar.datetime)
if bar_is_completed: if bar_is_completed:
@ -7478,7 +7476,7 @@ class CtaDayBar(CtaLineBar):
if is_new_bar: if is_new_bar:
# 添加新的bar # 添加新的bar
#new_bar = copy.deepcopy(bar) # new_bar = copy.deepcopy(bar)
self.line_bar.append(bar) # new_bar self.line_bar.append(bar) # new_bar
# 将上一个Bar推送至OnBar事件 # 将上一个Bar推送至OnBar事件
self.on_bar(lastBar) self.on_bar(lastBar)

View File

@ -253,7 +253,7 @@ class ChanSignals(Enum):
X3SE0 = "X3SE0~向上盘背" X3SE0 = "X3SE0~向上盘背"
X3SF0 = "X3SF0~向上无背" X3SF0 = "X3SF0~向上无背"
# 趋势类买卖点 # 趋势类买卖点(9~13笔分析结果
Q1L0 = "Q1L0~趋势类一买" Q1L0 = "Q1L0~趋势类一买"
Q2L0 = "Q2L0~趋势类二买" Q2L0 = "Q2L0~趋势类二买"
Q3L0 = "Q2L0~趋势类三买" Q3L0 = "Q2L0~趋势类三买"

View File

@ -1482,6 +1482,8 @@ class KLineWidget(KeyWraper):
:param sub_indicators: 副图的indicator list :param sub_indicators: 副图的indicator list
:return: :return:
""" """
print(f'start plot kline data')
t1 = datetime.now()
# 设置中心点时间 # 设置中心点时间
self.index = 0 self.index = 0
# 绑定数据更新横坐标映射更新Y轴自适应函数更新十字光标映射 # 绑定数据更新横坐标映射更新Y轴自适应函数更新十字光标映射
@ -1515,7 +1517,9 @@ class KLineWidget(KeyWraper):
# 调用画图函数 # 调用画图函数
self.plot_all(redraw=True, xMin=0, xMax=len(self.datas)) self.plot_all(redraw=True, xMin=0, xMax=len(self.datas))
self.crosshair.signal.emit((None, None)) self.crosshair.signal.emit((None, None))
print('finished load Data') t2 = datetime.now()
s = (t2-t1).microseconds
print(f'finished plot kline data in {s} ms')
class GridKline(QtWidgets.QWidget): class GridKline(QtWidgets.QWidget):
@ -1662,8 +1666,14 @@ class GridKline(QtWidgets.QWidget):
data_file = kline_setting.get('data_file', None) data_file = kline_setting.get('data_file', None)
if not data_file: if not data_file:
continue continue
print(f'loading {data_file}')
t1 = datetime.now()
df = pd.read_csv(data_file) df = pd.read_csv(data_file)
df = df.set_index(pd.DatetimeIndex(df['datetime'])) df = df.set_index(pd.DatetimeIndex(df['datetime']))
t2 = datetime.now()
s = (t2 - t1).microseconds
print(f'finished load in {s} ms')
canvas.loadData(df, canvas.loadData(df,
main_indicators=kline_setting.get('main_indicators', []), main_indicators=kline_setting.get('main_indicators', []),
sub_indicators=kline_setting.get('sub_indicators', []) sub_indicators=kline_setting.get('sub_indicators', [])
@ -1673,19 +1683,31 @@ class GridKline(QtWidgets.QWidget):
trade_list_file = kline_setting.get('trade_list_file', None) trade_list_file = kline_setting.get('trade_list_file', None)
if trade_list_file and os.path.exists(trade_list_file): if trade_list_file and os.path.exists(trade_list_file):
print(f'loading {trade_list_file}') print(f'loading {trade_list_file}')
t1 = datetime.now()
df_trade_list = pd.read_csv(trade_list_file) df_trade_list = pd.read_csv(trade_list_file)
self.kline_dict[kline_name].add_signals(df_trade_list) self.kline_dict[kline_name].add_signals(df_trade_list)
t2 = datetime.now()
s = (t2-t1).microseconds
print(f'finished load in {s} ms')
# 记载交易信号(实盘产生的) # 记载交易信号(实盘产生的)
trade_file = kline_setting.get('trade_file', None) trade_file = kline_setting.get('trade_file', None)
if trade_file and os.path.exists(trade_file): if trade_file and os.path.exists(trade_file):
print(f'loading {trade_file}') print(f'loading {trade_file}')
t1 = datetime.now()
df_trade = pd.read_csv(trade_file) df_trade = pd.read_csv(trade_file)
t2 = datetime.now()
s = (t2 - t1).microseconds
print(f'finished load in {s} ms')
t1 = datetime.now()
self.kline_dict[kline_name].add_trades( self.kline_dict[kline_name].add_trades(
df_trades=df_trade, df_trades=df_trade,
include_symbols=kline_setting.get('trade_include_symbols', []), include_symbols=kline_setting.get('trade_include_symbols', []),
exclude_symbols=kline_setting.get('trade_excclude_symbols', [])) exclude_symbols=kline_setting.get('trade_excclude_symbols', []))
t2 = datetime.now()
s = (t2 - t1).microseconds
print(f'finished plot trade in {s} ms')
# 加载tns( 回测、实盘产生的) # 加载tns( 回测、实盘产生的)
tns_file = kline_setting.get('tns_file', None) tns_file = kline_setting.get('tns_file', None)