[bug fix]
This commit is contained in:
parent
8c395d72ab
commit
f7e94a8a0b
@ -35,7 +35,7 @@ if __name__ == "__main__":
|
||||
|
||||
# 获取某个合约得的分时数据,周期是15分钟,返回数据类型是barData
|
||||
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对象
|
||||
setting = {}
|
||||
|
@ -6,7 +6,7 @@ from vnpy.amqp.consumer import subscriber
|
||||
if __name__ == '__main__':
|
||||
|
||||
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()
|
||||
|
||||
|
@ -222,7 +222,10 @@ class PortfolioTestingEngine(BackTestingEngine):
|
||||
bar.low_time = bar_data.get('low_time', None) # 最后一次进入低位区域的时间
|
||||
bar.high_time = bar_data.get('high_time', None) # 最后一次进入高位区域的时间
|
||||
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(
|
||||
gateway_name='backtesting',
|
||||
|
@ -11,7 +11,7 @@ from abc import ABC
|
||||
from copy import copy,deepcopy
|
||||
from typing import Any, Callable, List, Dict
|
||||
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.object import BarData, TickData, OrderData, TradeData, PositionData
|
||||
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:
|
||||
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):
|
||||
"""收盘后调用一次"""
|
||||
self.write_log(f'{self.strategy_name}收盘后调用')
|
||||
|
@ -30,7 +30,7 @@ from vnpy.component.cta_period import CtaPeriod, Period
|
||||
from vnpy.trader.object import BarData, TickData
|
||||
from vnpy.trader.constant import Interval, Color, ChanSignals
|
||||
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:
|
||||
from vnpy.component.chanlun import ChanGraph, ChanLibrary
|
||||
@ -231,8 +231,7 @@ class CtaLineBar(object):
|
||||
self.minute_interval = None # 把各个周期的bar转换为分钟,在first_tick中,用来修正bar为整点分钟周期
|
||||
if setting:
|
||||
self.set_params(setting)
|
||||
if self.is_stock:
|
||||
self.is_7x24 = True
|
||||
|
||||
|
||||
# 修正self.minute_interval
|
||||
if self.interval == Interval.SECOND:
|
||||
@ -839,9 +838,9 @@ class CtaLineBar(object):
|
||||
return
|
||||
|
||||
# 过滤一些 异常的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%
|
||||
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
|
||||
if self.cur_datetime and self.cur_datetime.date == tick.datetime.date:
|
||||
return
|
||||
@ -852,7 +851,7 @@ class CtaLineBar(object):
|
||||
return
|
||||
|
||||
self.cur_datetime = tick.datetime
|
||||
self.cur_tick = tick #copy.copy(tick)
|
||||
self.cur_tick = tick # copy.copy(tick)
|
||||
|
||||
# 兼容 标准套利合约,它没有last_price
|
||||
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)
|
||||
|
||||
if self.bar_len == 0:
|
||||
#new_bar = copy.deepcopy(bar)
|
||||
# new_bar = copy.deepcopy(bar)
|
||||
self.line_bar.append(bar)
|
||||
self.cur_trading_day = bar.trading_day
|
||||
self.on_bar(bar)
|
||||
@ -934,7 +933,7 @@ class CtaLineBar(object):
|
||||
|
||||
if is_new_bar:
|
||||
# 添加新的bar
|
||||
#new_bar = copy.deepcopy(bar)
|
||||
# new_bar = copy.deepcopy(bar)
|
||||
self.line_bar.append(bar) # new_bar
|
||||
# 将上一个Bar推送至OnBar事件
|
||||
self.on_bar(lastBar)
|
||||
@ -6269,15 +6268,15 @@ class CtaLineBar(object):
|
||||
'signal': signal})
|
||||
if len(xt_signals) > 200:
|
||||
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(
|
||||
file_name=self.export_xt_filename.replace('_n_',f'_{n}_'),
|
||||
file_name=self.export_xt_filename.replace('_n_', f'_{n}_'),
|
||||
dict_data=cur_signal,
|
||||
field_names=["start", "end", "price", "signal"]
|
||||
)
|
||||
# 直接更新
|
||||
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
|
||||
@ -6285,7 +6284,7 @@ class CtaLineBar(object):
|
||||
if check_qsbc_2nd(big_kline=self, small_kline=None, signal_direction=Direction.LONG):
|
||||
qsbc_2nd = ChanSignals.Q2L0.value
|
||||
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
|
||||
cur_signal = self.xt_2nd_signals[-1] if len(self.xt_2nd_signals) > 0 else None
|
||||
# 不同笔开始时间
|
||||
@ -6305,8 +6304,6 @@ class CtaLineBar(object):
|
||||
else:
|
||||
self.xt_2nd_signals[-1].update({'end': self.cur_bi.end, 'price': price, 'signal': qsbc_2nd})
|
||||
|
||||
|
||||
|
||||
def write_log(self, content):
|
||||
"""记录CTA日志"""
|
||||
self.strategy.write_log(u'[' + self.name + u']' + content)
|
||||
@ -6512,7 +6509,7 @@ class CtaLineBar(object):
|
||||
'type': 'line'
|
||||
}
|
||||
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 = {
|
||||
'name': 'EMA{}'.format(self.para_ema4_len),
|
||||
'attr_name': 'line_ema4',
|
||||
@ -6520,7 +6517,7 @@ class CtaLineBar(object):
|
||||
'type': 'line'
|
||||
}
|
||||
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 = {
|
||||
'name': 'EMA{}'.format(self.para_ema5_len),
|
||||
'attr_name': 'line_ema5',
|
||||
@ -6936,7 +6933,7 @@ class CtaMinuteBar(CtaLineBar):
|
||||
|
||||
def add_bar(self, bar, bar_is_completed=False, bar_freq=1):
|
||||
"""
|
||||
予以外部初始化程序增加bar
|
||||
CtaMinuteBar予以外部初始化程序增加bar
|
||||
:param bar:
|
||||
:param bar_is_completed: 插入的bar,其周期与K线周期一致,就设为True
|
||||
:param bar_freq, bar对象得frequency
|
||||
@ -6975,9 +6972,12 @@ class CtaMinuteBar(CtaLineBar):
|
||||
if bar_is_completed:
|
||||
is_new_bar = True
|
||||
|
||||
minutes_passed = (bar.datetime - datetime.strptime(bar.datetime.strftime('%Y-%m-%d'),
|
||||
'%Y-%m-%d')).total_seconds() / 60
|
||||
if self.underly_symbol in MARKET_ZJ:
|
||||
if self.cur_trading_day > bar.trading_day:
|
||||
is_new_bar = True
|
||||
|
||||
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:
|
||||
# 扣除11:30到13:00的中场休息的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:
|
||||
# 扣除(10:15到10:30的中场休息的15分钟)&(11:30到13:30的中场休息的120分钟)
|
||||
minutes_passed = minutes_passed - 135
|
||||
|
||||
bars_passed = int(minutes_passed / self.bar_interval)
|
||||
|
||||
# 不在同一交易日,推入新bar
|
||||
if self.cur_trading_day != bar.trading_day:
|
||||
if self.cur_trading_day > bar.trading_day:
|
||||
is_new_bar = True
|
||||
self.cur_trading_day = bar.trading_day
|
||||
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.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:
|
||||
#new_bar = copy.deepcopy(bar)
|
||||
# new_bar = copy.deepcopy(bar)
|
||||
# 添加新的bar
|
||||
self.line_bar.append(bar) # new_bar
|
||||
# 将上一个Bar推送至OnBar事件
|
||||
@ -7038,17 +7035,18 @@ class CtaMinuteBar(CtaLineBar):
|
||||
|
||||
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:
|
||||
# 扣除11:30到13:00的中场休息的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:
|
||||
# 扣除10:15到10:30的中场休息的15分钟
|
||||
minutes_passed = minutes_passed - 15
|
||||
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分钟)
|
||||
minutes_passed = minutes_passed - 135
|
||||
|
||||
bars_passed = int(minutes_passed / self.bar_interval)
|
||||
|
||||
# 保存第一个K线数据
|
||||
@ -7451,7 +7449,7 @@ class CtaDayBar(CtaLineBar):
|
||||
bar_len = len(self.line_bar)
|
||||
|
||||
if bar_len == 0:
|
||||
#new_bar = copy.deepcopy(bar)
|
||||
# new_bar = copy.deepcopy(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)
|
||||
if bar_is_completed:
|
||||
@ -7478,7 +7476,7 @@ class CtaDayBar(CtaLineBar):
|
||||
|
||||
if is_new_bar:
|
||||
# 添加新的bar
|
||||
#new_bar = copy.deepcopy(bar)
|
||||
# new_bar = copy.deepcopy(bar)
|
||||
self.line_bar.append(bar) # new_bar
|
||||
# 将上一个Bar推送至OnBar事件
|
||||
self.on_bar(lastBar)
|
||||
|
@ -253,7 +253,7 @@ class ChanSignals(Enum):
|
||||
X3SE0 = "X3SE0~向上盘背"
|
||||
X3SF0 = "X3SF0~向上无背"
|
||||
|
||||
# 趋势类买卖点
|
||||
# 趋势类买卖点(9~13笔分析结果)
|
||||
Q1L0 = "Q1L0~趋势类一买"
|
||||
Q2L0 = "Q2L0~趋势类二买"
|
||||
Q3L0 = "Q2L0~趋势类三买"
|
||||
|
@ -1482,6 +1482,8 @@ class KLineWidget(KeyWraper):
|
||||
:param sub_indicators: 副图的indicator list
|
||||
:return:
|
||||
"""
|
||||
print(f'start plot kline data')
|
||||
t1 = datetime.now()
|
||||
# 设置中心点时间
|
||||
self.index = 0
|
||||
# 绑定数据,更新横坐标映射,更新Y轴自适应函数,更新十字光标映射
|
||||
@ -1515,7 +1517,9 @@ class KLineWidget(KeyWraper):
|
||||
# 调用画图函数
|
||||
self.plot_all(redraw=True, xMin=0, xMax=len(self.datas))
|
||||
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):
|
||||
@ -1662,8 +1666,14 @@ class GridKline(QtWidgets.QWidget):
|
||||
data_file = kline_setting.get('data_file', None)
|
||||
if not data_file:
|
||||
continue
|
||||
print(f'loading {data_file}')
|
||||
t1 = datetime.now()
|
||||
df = pd.read_csv(data_file)
|
||||
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,
|
||||
main_indicators=kline_setting.get('main_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)
|
||||
if trade_list_file and os.path.exists(trade_list_file):
|
||||
print(f'loading {trade_list_file}')
|
||||
t1 = datetime.now()
|
||||
df_trade_list = pd.read_csv(trade_list_file)
|
||||
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)
|
||||
if trade_file and os.path.exists(trade_file):
|
||||
print(f'loading {trade_file}')
|
||||
t1 = datetime.now()
|
||||
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(
|
||||
df_trades=df_trade,
|
||||
include_symbols=kline_setting.get('trade_include_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_file = kline_setting.get('tns_file', None)
|
||||
|
Loading…
Reference in New Issue
Block a user