[增强功能] 实时查看策略内K线切片功能
This commit is contained in:
parent
1c2c21812f
commit
eb14b154d5
@ -1221,6 +1221,25 @@ class CtaEngine(BaseEngine):
|
||||
self.write_error(u'保存策略{}数据异常:'.format(strategy_name, str(ex)))
|
||||
self.write_error(traceback.format_exc())
|
||||
|
||||
def get_strategy_snapshot(self, strategy_name):
|
||||
"""实时获取策略的K线切片(比较耗性能)"""
|
||||
strategy = self.strategies.get(strategy_name, None)
|
||||
if strategy is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
# 5.保存策略切片
|
||||
snapshot = strategy.get_klines_snapshot()
|
||||
if not snapshot:
|
||||
self.write_log(f'{strategy_name}返回得K线切片数据为空')
|
||||
return None
|
||||
return snapshot
|
||||
|
||||
except Exception as ex:
|
||||
self.write_error(u'获取策略{}切片数据异常:'.format(strategy_name, str(ex)))
|
||||
self.write_error(traceback.format_exc())
|
||||
return None
|
||||
|
||||
def save_strategy_snapshot(self, select_name: str = 'ALL'):
|
||||
"""
|
||||
保存策略K线切片数据
|
||||
|
@ -414,8 +414,9 @@ class CtaStockTemplate(CtaTemplate):
|
||||
cancel_seconds = 120 # 撤单时间(秒)
|
||||
|
||||
# 资金相关
|
||||
max_invest_rate = 0.1 # 最大仓位(0~1)
|
||||
max_invest_margin = 0 # 资金上限 0,不限制
|
||||
max_invest_rate = 0.1 # 策略使用账号的最大仓位(0~1)
|
||||
max_invest_margin = 0 # 策略资金上限, 0,不限制
|
||||
max_single_margin = 0 # 策略内,各只股票使用的资金上限
|
||||
|
||||
# 是否回测状态
|
||||
backtesting = False
|
||||
|
@ -8,12 +8,14 @@ from vnpy.trader.ui.widget import (
|
||||
TimeCell,
|
||||
BaseMonitor
|
||||
)
|
||||
from vnpy.trader.ui.kline.ui_snapshot import UiSnapshot
|
||||
from ..base import (
|
||||
APP_NAME,
|
||||
EVENT_CTA_LOG,
|
||||
EVENT_CTA_STOPORDER,
|
||||
EVENT_CTA_STRATEGY
|
||||
)
|
||||
|
||||
from ..engine import CtaEngine
|
||||
|
||||
|
||||
@ -205,6 +207,9 @@ class StrategyManager(QtWidgets.QFrame):
|
||||
save_button = QtWidgets.QPushButton("保存")
|
||||
save_button.clicked.connect(self.save_strategy)
|
||||
|
||||
view_button = QtWidgets.QPushButton("K线")
|
||||
view_button.clicked.connect(self.view_strategy_snapshot)
|
||||
|
||||
strategy_name = self._data["strategy_name"]
|
||||
#vt_symbol = self._data["vt_symbol"]
|
||||
class_name = self._data["class_name"]
|
||||
@ -227,6 +232,7 @@ class StrategyManager(QtWidgets.QFrame):
|
||||
hbox.addWidget(remove_button)
|
||||
hbox.addWidget(reload_button)
|
||||
hbox.addWidget(save_button)
|
||||
hbox.addWidget(view_button)
|
||||
|
||||
vbox = QtWidgets.QVBoxLayout()
|
||||
vbox.addWidget(label)
|
||||
@ -279,8 +285,16 @@ class StrategyManager(QtWidgets.QFrame):
|
||||
self.cta_engine.reload_strategy(self.strategy_name)
|
||||
|
||||
def save_strategy(self):
|
||||
"""保存策略缓存数据"""
|
||||
self.cta_engine.save_strategy_data(self.strategy_name)
|
||||
|
||||
def view_strategy_snapshot(self):
|
||||
"""实时查看策略切片"""
|
||||
snapshot = self.cta_engine.get_strategy_snapshot(self.strategy_name)
|
||||
if snapshot is None:
|
||||
return
|
||||
ui_snapshot = UiSnapshot()
|
||||
ui_snapshot.show(snapshot_file="", d=snapshot)
|
||||
|
||||
class DataMonitor(QtWidgets.QTableWidget):
|
||||
"""
|
||||
|
@ -1190,6 +1190,25 @@ class CtaEngine(BaseEngine):
|
||||
self.write_error(u'保存策略{}数据异常:'.format(strategy_name, str(ex)))
|
||||
self.write_error(traceback.format_exc())
|
||||
|
||||
def get_strategy_snapshot(self, strategy_name):
|
||||
"""实时获取策略的K线切片(比较耗性能)"""
|
||||
strategy = self.strategies.get(strategy_name, None)
|
||||
if strategy is None:
|
||||
return None
|
||||
|
||||
try:
|
||||
# 5.保存策略切片
|
||||
snapshot = strategy.get_klines_snapshot()
|
||||
if not snapshot:
|
||||
self.write_log(f'{strategy_name}返回得K线切片数据为空')
|
||||
return None
|
||||
return snapshot
|
||||
|
||||
except Exception as ex:
|
||||
self.write_error(u'获取策略{}切片数据异常:'.format(strategy_name, str(ex)))
|
||||
self.write_error(traceback.format_exc())
|
||||
return None
|
||||
|
||||
def save_strategy_snapshot(self, select_name: str = 'ALL'):
|
||||
"""
|
||||
保存策略K线切片数据
|
||||
@ -1567,6 +1586,10 @@ class CtaEngine(BaseEngine):
|
||||
holding = self.offset_converter.holdings.get(holding_key, None)
|
||||
if holding is None:
|
||||
continue
|
||||
if holding.exchange == Exchange.SPD:
|
||||
continue
|
||||
if '&' in holding.vt_symbol and (holding.vt_symbol.startswith('SP') or holding.vt_symbol.startswith('STG')):
|
||||
continue
|
||||
|
||||
compare_pos[vt_symbol] = OrderedDict(
|
||||
{
|
||||
|
@ -8,12 +8,14 @@ from vnpy.trader.ui.widget import (
|
||||
TimeCell,
|
||||
BaseMonitor
|
||||
)
|
||||
from vnpy.trader.ui.kline.ui_snapshot import UiSnapshot
|
||||
from ..base import (
|
||||
APP_NAME,
|
||||
EVENT_CTA_LOG,
|
||||
EVENT_CTA_STOPORDER,
|
||||
EVENT_CTA_STRATEGY
|
||||
)
|
||||
|
||||
from ..engine import CtaEngine
|
||||
|
||||
|
||||
@ -205,6 +207,9 @@ class StrategyManager(QtWidgets.QFrame):
|
||||
save_button = QtWidgets.QPushButton("保存")
|
||||
save_button.clicked.connect(self.save_strategy)
|
||||
|
||||
view_button = QtWidgets.QPushButton("K线")
|
||||
view_button.clicked.connect(self.view_strategy_snapshot)
|
||||
|
||||
strategy_name = self._data["strategy_name"]
|
||||
vt_symbol = self._data["vt_symbol"]
|
||||
class_name = self._data["class_name"]
|
||||
@ -227,6 +232,7 @@ class StrategyManager(QtWidgets.QFrame):
|
||||
hbox.addWidget(remove_button)
|
||||
hbox.addWidget(reload_button)
|
||||
hbox.addWidget(save_button)
|
||||
hbox.addWidget(view_button)
|
||||
|
||||
vbox = QtWidgets.QVBoxLayout()
|
||||
vbox.addWidget(label)
|
||||
@ -279,8 +285,17 @@ class StrategyManager(QtWidgets.QFrame):
|
||||
self.cta_engine.reload_strategy(self.strategy_name)
|
||||
|
||||
def save_strategy(self):
|
||||
"""保存策略缓存数据"""
|
||||
self.cta_engine.save_strategy_data(self.strategy_name)
|
||||
self.cta_engine.save_strategy_snapshot(self.strategy_name)
|
||||
|
||||
def view_strategy_snapshot(self):
|
||||
"""实时查看策略切片"""
|
||||
snapshot = self.cta_engine.get_strategy_snapshot(self.strategy_name)
|
||||
if snapshot is None:
|
||||
return
|
||||
ui_snapshot = UiSnapshot()
|
||||
ui_snapshot.show(snapshot_file="", d=snapshot)
|
||||
|
||||
class DataMonitor(QtWidgets.QTableWidget):
|
||||
"""
|
||||
|
@ -143,11 +143,9 @@ class CtaLineBar(object):
|
||||
# 参数列表,保存了参数的名称
|
||||
paramList = ['vt_symbol']
|
||||
|
||||
# 参数列表
|
||||
|
||||
def __init__(self, strategy, cb_on_bar, setting=None):
|
||||
|
||||
# OnBar事件回调函数
|
||||
# on_bar事件回调函数,X周期bar合成完毕时,回调到策略的cb_on_bar接口
|
||||
self.cb_on_bar = cb_on_bar
|
||||
|
||||
# 周期变更事件回调函数
|
||||
@ -156,27 +154,28 @@ class CtaLineBar(object):
|
||||
# K 线服务的策略
|
||||
self.strategy = strategy
|
||||
|
||||
# 当前商品合约 属性
|
||||
self.underly_symbol = '' # 商品的短代码
|
||||
self.price_tick = 1 # 商品的最小价格单位
|
||||
self.round_n = 4 # round() 小数点的截断数量
|
||||
self.is_7x24 = False # 是否7x24小时运行( 一般为数字货币)
|
||||
|
||||
self.is_7x24 = False
|
||||
|
||||
# 当前的Tick
|
||||
self.cur_tick = None
|
||||
self.last_tick = None
|
||||
self.cur_datetime = None
|
||||
self.cur_trading_day = ''
|
||||
self.cur_price = 0
|
||||
# 当前的Tick的信息
|
||||
self.cur_tick = None # 当前 onTick()函数接收的 最新的tick
|
||||
self.last_tick = None # 当前正在合成的 X周期bar 的最后(新)一根tick
|
||||
self.cur_datetime = None # 当前add_bar()传进来的bar/on_tick()传进来tick 对应的最新时间
|
||||
self.cur_trading_day = '' # 当前传入tick/bar对应的交易日
|
||||
self.cur_price = 0 # 当前curTick.last_price/add_bar中的bar.close_price传进来的 最新市场价格
|
||||
|
||||
# K线保存数据
|
||||
self.cur_bar = None # K线数据对象,代表最后一根/未走完的bar
|
||||
self.line_bar = [] # K线缓存数据队列
|
||||
self.bar_len = 0 # 当前K线得真实数量
|
||||
self.line_bar = [] # K线缓存数据队列(缓存合成完 以及正在合成的bar)
|
||||
self.bar_len = 0 # 当前K线得真实数量(包含已经合成以及正在合成的bar)
|
||||
self.max_hold_bars = 2000
|
||||
self.is_first_tick = False # K线的第一条Tick数据
|
||||
|
||||
# (实时运行时,或者addbar小于bar得周期时,不包含最后一根Bar)
|
||||
# (实时运行时,或者addbar小于bar得周期时,不包含最后一根正在合成的Bar)
|
||||
# 目标bar合成成功后,才会更新以下序列
|
||||
self.open_array = np.zeros(self.max_hold_bars) # 与lineBar一致得开仓价清单
|
||||
self.open_array[:] = np.nan
|
||||
self.high_array = np.zeros(self.max_hold_bars) # 与lineBar一致得最高价清单
|
||||
@ -192,14 +191,14 @@ class CtaLineBar(object):
|
||||
self.mid4_array[:] = np.nan
|
||||
self.mid5_array = np.zeros(self.max_hold_bars) # 收盘价*2/开仓价/最高/最低价 的平均价
|
||||
self.mid5_array[:] = np.nan
|
||||
# 导出到CSV文件 的目录名 和 要导出的 字段
|
||||
self.export_filename = None # 数据要导出的目标文件夹
|
||||
self.export_fields = [] # 定义要导出的数据字段
|
||||
|
||||
self.export_filename = None
|
||||
self.export_fields = []
|
||||
|
||||
# 创建内部变量
|
||||
# 创建本类型bar的内部变量,以及添加所有指标输入参数,到self.paramList列表
|
||||
self.init_properties()
|
||||
|
||||
# 创建初始化指标
|
||||
# 初始化定义所有的指标输入参数,以及指标生成的数据
|
||||
self.init_indicators()
|
||||
|
||||
# 启动实时得函数
|
||||
@ -209,6 +208,7 @@ class CtaLineBar(object):
|
||||
# 注册回调函数
|
||||
self.cb_dict = {}
|
||||
|
||||
self.minute_interval = None # 把各个周期的bar转换为分钟,在first_tick中,用来修正bar为整点分钟周期
|
||||
if setting:
|
||||
self.set_params(setting)
|
||||
|
||||
@ -221,11 +221,13 @@ class CtaLineBar(object):
|
||||
self.minute_interval = 60
|
||||
elif self.interval == Interval.DAILY:
|
||||
self.minute_interval = 60 * 24
|
||||
|
||||
# 修正精度
|
||||
if self.price_tick < 1:
|
||||
exponent = decimal.Decimal(str(self.price_tick))
|
||||
self.round_n = max(abs(exponent.as_tuple().exponent) + 2, 4)
|
||||
self.write_log(f'round_n: {self.round_n}')
|
||||
|
||||
# 导入卡尔曼过滤器
|
||||
if self.para_active_kf:
|
||||
try:
|
||||
@ -246,37 +248,45 @@ class CtaLineBar(object):
|
||||
self.cb_on_period = cb_func
|
||||
|
||||
def init_param_list(self):
|
||||
self.paramList.append('bar_interval')
|
||||
self.paramList.append('interval')
|
||||
self.paramList.append('mode')
|
||||
"""初始化添加,本类型bar的内部变量,以及添加所有指标输入参数,到self.paramList列表"""
|
||||
# ------- 本类型bar的内部变量 ---------
|
||||
self.paramList.append('name') # K线的名称
|
||||
self.paramList.append('bar_interval') # bar的周期数量
|
||||
self.paramList.append('interval') # bar的类型
|
||||
self.paramList.append('mode') # tick/bar模式
|
||||
self.paramList.append('is_7x24') #是否为7X24小时运行的bar(一般为数字货币)
|
||||
self.paramList.append('price_tick') # 最小跳动,用于处理指数等不一致的价格
|
||||
self.paramList.append('underly_symbol') # 短合约,
|
||||
|
||||
self.paramList.append('para_pre_len')
|
||||
self.paramList.append('para_ma1_len')
|
||||
# ---------- 下方为指标输入参数 ---------------
|
||||
self.paramList.append('para_pre_len') # 唐其安通道的长度(前高/前低)
|
||||
|
||||
self.paramList.append('para_ma1_len') # 三条均线
|
||||
self.paramList.append('para_ma2_len')
|
||||
self.paramList.append('para_ma3_len')
|
||||
|
||||
self.paramList.append('para_ema1_len')
|
||||
self.paramList.append('para_ema1_len') # 三条EMA均线
|
||||
self.paramList.append('para_ema2_len')
|
||||
self.paramList.append('para_ema3_len')
|
||||
|
||||
self.paramList.append('para_dmi_len')
|
||||
self.paramList.append('para_dmi_max')
|
||||
|
||||
self.paramList.append('para_atr1_len')
|
||||
self.paramList.append('para_atr1_len') # 三个波动率
|
||||
self.paramList.append('para_atr2_len')
|
||||
self.paramList.append('para_atr3_len')
|
||||
|
||||
self.paramList.append('para_vol_len')
|
||||
self.paramList.append('para_vol_len') # 成交量平均
|
||||
|
||||
self.paramList.append('para_rsi1_len')
|
||||
self.paramList.append('para_rsi1_len') # 2组 RSI摆动指标
|
||||
self.paramList.append('para_rsi2_len')
|
||||
|
||||
self.paramList.append('para_cmi_len')
|
||||
self.paramList.append('para_cmi_len') #
|
||||
|
||||
self.paramList.append('para_boll_len')
|
||||
self.paramList.append('para_boll_tb_len')
|
||||
self.paramList.append('para_boll_std_rate')
|
||||
self.paramList.append('para_boll2_len')
|
||||
self.paramList.append('para_boll_len') # 布林通道长度(文华计算方式)
|
||||
self.paramList.append('para_boll_tb_len') # 布林通道长度(tb计算方式)
|
||||
self.paramList.append('para_boll_std_rate') # 标准差倍率,一般为2
|
||||
self.paramList.append('para_boll2_len') # 第二条布林通道
|
||||
self.paramList.append('para_boll2_tb_len')
|
||||
self.paramList.append('para_boll2_std_rate')
|
||||
|
||||
@ -291,22 +301,22 @@ class CtaLineBar(object):
|
||||
self.paramList.append('para_macd_slow_len')
|
||||
self.paramList.append('para_macd_signal_len')
|
||||
|
||||
self.paramList.append('para_active_kf')
|
||||
self.paramList.append('para_active_kf') # 卡尔曼均线
|
||||
|
||||
self.paramList.append('para_sar_step')
|
||||
self.paramList.append('para_sar_limit')
|
||||
|
||||
self.paramList.append('para_active_skd')
|
||||
self.paramList.append('para_active_skd') # 摆动指标
|
||||
self.paramList.append('para_skd_fast_len')
|
||||
self.paramList.append('para_skd_slow_len')
|
||||
self.paramList.append('para_skd_low')
|
||||
self.paramList.append('para_skd_high')
|
||||
|
||||
self.paramList.append('para_active_yb')
|
||||
self.paramList.append('para_active_yb') # 重心线
|
||||
self.paramList.append('para_yb_len')
|
||||
self.paramList.append('para_yb_ref')
|
||||
|
||||
self.paramList.append('para_golden_n')
|
||||
self.paramList.append('para_golden_n') # 黄金分割
|
||||
|
||||
self.paramList.append('para_active_area')
|
||||
|
||||
@ -319,12 +329,7 @@ class CtaLineBar(object):
|
||||
|
||||
self.paramList.append('para_bd_len')
|
||||
|
||||
self.paramList.append('is_7x24')
|
||||
|
||||
self.paramList.append('price_tick')
|
||||
self.paramList.append('underly_symbol')
|
||||
|
||||
self.paramList.append('name')
|
||||
|
||||
def init_properties(self):
|
||||
"""
|
||||
@ -361,9 +366,9 @@ class CtaLineBar(object):
|
||||
self.__dict__[key] = state.__dict__[key]
|
||||
|
||||
def init_indicators(self):
|
||||
""" 定义所有的指标数据"""
|
||||
""" 初始化定义所有的指标输入参数,以及指标生成的数据 """
|
||||
|
||||
# 指标参数
|
||||
# ------------- 指标输入参数 ------------------
|
||||
self.para_pre_len = 0 # 20 # 前高前低的周期长度
|
||||
|
||||
self.para_ma1_len = 0 # 10 # 第一根MA均线的周期长度
|
||||
@ -403,7 +408,7 @@ class CtaLineBar(object):
|
||||
|
||||
self.para_cci_len = 0 # 计算CCI的K线周期
|
||||
|
||||
self.para_macd_fast_len = 0 # 计算MACD的K线周期
|
||||
self.para_macd_fast_len = 0 # 计算MACD的K线周期(26,12,9)
|
||||
self.para_macd_slow_len = 0 # 慢线周期
|
||||
self.para_macd_signal_len = 0 # 平滑周期
|
||||
|
||||
@ -412,7 +417,7 @@ class CtaLineBar(object):
|
||||
self.para_sar_step = 0 # 抛物线的参数
|
||||
self.para_sar_limit = 0 # 抛物线参数
|
||||
|
||||
self.para_active_skd = False # 是否激活摆动指标
|
||||
self.para_active_skd = False # 是否激活摆动指标 优化的多空动量线
|
||||
self.para_skd_fast_len = 13 # 摆动指标快线周期1
|
||||
self.para_skd_slow_len = 8 # 摆动指标慢线周期2
|
||||
self.para_skd_low = 30 # 摆动指标下限区域
|
||||
@ -435,7 +440,7 @@ class CtaLineBar(object):
|
||||
|
||||
self.para_bd_len = 0 # 波段买卖观测长度
|
||||
|
||||
# K 线的相关计算结果数据
|
||||
# --------------- K 线的指标相关计算结果数据 ----------------
|
||||
self.line_pre_high = [] # K线的前para_pre_len的的最高
|
||||
self.line_pre_low = [] # K线的前para_pre_len的的最低
|
||||
|
||||
@ -452,13 +457,13 @@ class CtaLineBar(object):
|
||||
self._rt_ma2_atan = None
|
||||
self._rt_ma3_atan = None
|
||||
|
||||
self.ma12_count = 0 # ma1 与 ma2 ,金叉/死叉后第几根bar
|
||||
self.ma13_count = 0 # ma1 与 ma3 ,金叉/死叉后第几根bar
|
||||
self.ma23_count = 0 # ma2 与 ma3 ,金叉/死叉后第几根bar
|
||||
self.ma12_count = 0 # ma1 与 ma2 ,金叉/死叉后第几根bar,金叉正数,死叉负数
|
||||
self.ma13_count = 0 # ma1 与 ma3 ,金叉/死叉后第几根bar,金叉正数,死叉负数
|
||||
self.ma23_count = 0 # ma2 与 ma3 ,金叉/死叉后第几根bar,金叉正数,死叉负数
|
||||
|
||||
self.line_ema1 = [] # K线的EMA1均线,周期是InputEmaLen1,不包含当前bar
|
||||
self.line_ema2 = [] # K线的EMA2均线,周期是InputEmaLen2,不包含当前bar
|
||||
self.line_ema3 = [] # K线的EMA3均线,周期是InputEmaLen3,不包含当前bar
|
||||
self.line_ema1 = [] # K线的EMA1均线,周期是para_ema1_len1,不包含当前bar
|
||||
self.line_ema2 = [] # K线的EMA2均线,周期是para_ema1_len2,不包含当前bar
|
||||
self.line_ema3 = [] # K线的EMA3均线,周期是para_ema1_len3,不包含当前bar
|
||||
|
||||
self._rt_ema1 = None # K线的实时EMA(para_ema1_len)
|
||||
self._rt_ema2 = None # K线的实时EMA(para_ema2_len)
|
||||
@ -485,9 +490,9 @@ class CtaLineBar(object):
|
||||
self.signal_adx_short = False # 空过滤器条件,做空趋势的判断,ADXR高于前一天,下降动向> inputMM
|
||||
|
||||
# K线的ATR技术数据
|
||||
self.line_atr1 = [] # K线的ATR1,周期为inputAtr1Len
|
||||
self.line_atr2 = [] # K线的ATR2,周期为inputAtr2Len
|
||||
self.line_atr3 = [] # K线的ATR3,周期为inputAtr3Len
|
||||
self.line_atr1 = [] # K线的ATR1,周期为para_atr1_len
|
||||
self.line_atr2 = [] # K线的ATR2,周期为para_atr2_len
|
||||
self.line_atr3 = [] # K线的ATR3,周期为para_atr3_len
|
||||
|
||||
self.cur_atr1 = 0
|
||||
self.cur_atr2 = 0
|
||||
@ -497,22 +502,25 @@ class CtaLineBar(object):
|
||||
self.line_vol_ma = [] # K 线的交易量平均
|
||||
|
||||
# K线的RSI计算数据
|
||||
self.line_rsi1 = [] # 记录K线对应的RSI数值,只保留inputRsi1Len*8
|
||||
self.line_rsi2 = [] # 记录K线对应的RSI数值,只保留inputRsi2Len*8
|
||||
self.line_rsi1 = [] # 记录K线对应的RSI数值,只保留para_rsi1_len*8
|
||||
self.line_rsi2 = [] # 记录K线对应的RSI数值,只保留para_rsi2_len*8
|
||||
|
||||
self.para_rsi_low = 30 # RSI的最低线
|
||||
self.para_rsi_high = 70 # RSI的最高线
|
||||
|
||||
self.rsi_top_list = [] # 记录RSI的最高峰,只保留 inputRsiLen个
|
||||
self.rsi_buttom_list = [] # 记录RSI的最低谷,只保留 inputRsiLen个
|
||||
self.cur_rsi_top_buttom = {} # 最近的一个波峰/波谷
|
||||
|
||||
# K线的CMI计算数据
|
||||
self.line_cmi = [] # 记录K线对应的Cmi数值,只保留inputCmiLen*8
|
||||
self.line_cmi = [] # 记录K线对应的Cmi数值,只保留para_cmi_len*8
|
||||
|
||||
# K线的布林特计算数据
|
||||
self.line_boll_upper = [] # 上轨
|
||||
self.line_boll_middle = [] # 中线
|
||||
self.line_boll_lower = [] # 下轨
|
||||
self.line_boll_std = [] # 标准差
|
||||
|
||||
self.line_upper_atan = []
|
||||
self.line_middle_atan = []
|
||||
self.line_lower_atan = []
|
||||
@ -523,17 +531,19 @@ class CtaLineBar(object):
|
||||
self._rt_middle_atan = None
|
||||
self._rt_lower_atan = None
|
||||
|
||||
self.cur_upper = 0 # 最后一根K的Boll上轨数值(与MinDiff取整)
|
||||
self.cur_middle = 0 # 最后一根K的Boll中轨数值(与MinDiff取整)
|
||||
self.cur_lower = 0 # 最后一根K的Boll下轨数值(与MinDiff取整+1)
|
||||
self.cur_upper = 0 # 最后一根K的Boll上轨数值(与price_tick取整)
|
||||
self.cur_middle = 0 # 最后一根K的Boll中轨数值(与price_tick取整)
|
||||
self.cur_lower = 0 # 最后一根K的Boll下轨数值(与price_tick取整+1)
|
||||
|
||||
self.line_boll2_upper = [] # 上轨
|
||||
self.line_boll2_middle = [] # 中线
|
||||
self.line_boll2_lower = [] # 下轨
|
||||
self.line_boll2_std = [] # 标准差
|
||||
|
||||
self.line_upper2_atan = []
|
||||
self.line_middle2_atan = []
|
||||
self.line_lower2_atan = []
|
||||
|
||||
self._rt_upper2 = None
|
||||
self._rt_middle2 = None
|
||||
self._rt_lower2 = None
|
||||
@ -541,16 +551,16 @@ class CtaLineBar(object):
|
||||
self._rt_middle2_atan = None
|
||||
self._rt_lower2_atan = None
|
||||
|
||||
self.cur_upper2 = 0 # 最后一根K的Boll2上轨数值(与MinDiff取整)
|
||||
self.cur_middle2 = 0 # 最后一根K的Boll2中轨数值(与MinDiff取整)
|
||||
self.cur_lower2 = 0 # 最后一根K的Boll2下轨数值(与MinDiff取整+1)
|
||||
self.cur_upper2 = 0 # 最后一根K的Boll2上轨数值(与price_tick取整)
|
||||
self.cur_middle2 = 0 # 最后一根K的Boll2中轨数值(与price_tick取整)
|
||||
self.cur_lower2 = 0 # 最后一根K的Boll2下轨数值(与price_tick取整+1)
|
||||
|
||||
# K线的KDJ指标计算数据
|
||||
self.line_k = [] # K为快速指标
|
||||
self.line_d = [] # D为慢速指标
|
||||
self.line_j = [] #
|
||||
self.kdj_top_list = [] # 记录KDJ最高峰,只保留 inputKdjLen个
|
||||
self.kdj_buttom_list = [] # 记录KDJ的最低谷,只保留 inputKdjLen个
|
||||
self.kdj_top_list = [] # 记录KDJ最高峰,只保留 para_kdj_len个
|
||||
self.kdj_buttom_list = [] # 记录KDJ的最低谷,只保留 para_kdj_len个
|
||||
self.line_rsv = [] # RSV
|
||||
self.cur_kdj_top_buttom = {} # 最近的一个波峰/波谷
|
||||
self.cur_k = 0 # bar内计算时,最后一个未关闭的bar的实时K值
|
||||
@ -620,6 +630,7 @@ class CtaLineBar(object):
|
||||
self.line_skd_sto = [] # 根据RSI演算的STO
|
||||
self.line_sk = [] # 快线
|
||||
self.line_sd = [] # 慢线
|
||||
|
||||
self.cur_skd_count = 0 # 当前金叉/死叉后累加
|
||||
self._rt_sk = None # 实时SK值
|
||||
self._rt_sd = None # 实时SD值
|
||||
@ -664,6 +675,7 @@ class CtaLineBar(object):
|
||||
self.line_bd_fast = [] # 波段快线
|
||||
self.line_bd_slow = [] # 波段慢线
|
||||
self.cur_bd_count = 0 # 当前波段快线慢线金叉死叉, +金叉计算, - 死叉技术
|
||||
|
||||
self._bd_fast = 0
|
||||
self._bd_slow = 0
|
||||
|
||||
@ -795,6 +807,7 @@ class CtaLineBar(object):
|
||||
|
||||
def on_bar(self, bar: BarData):
|
||||
"""OnBar事件"""
|
||||
# 将上一根bar合成完结了,触发本on_bar事件(缓存开高收低等序列,计算各个指标)
|
||||
if not bar.interval:
|
||||
bar.interval = self.interval
|
||||
bar.interval_num = self.bar_interval
|
||||
@ -804,7 +817,7 @@ class CtaLineBar(object):
|
||||
bar_mid4 = round((2 * bar.close_price + bar.high_price + bar.low_price) / 4, self.round_n)
|
||||
bar_mid5 = round((2 * bar.close_price + bar.open_price + bar.high_price + bar.low_price) / 5, self.round_n)
|
||||
|
||||
# 扩展open,close,high,low numpy array列表
|
||||
# 扩展open,close,high,low numpy array列表 平移更新序列最新值
|
||||
self.open_array[:-1] = self.open_array[1:]
|
||||
self.open_array[-1] = bar.open_price
|
||||
|
||||
@ -826,7 +839,11 @@ class CtaLineBar(object):
|
||||
self.mid5_array[:-1] = self.mid5_array[1:]
|
||||
self.mid5_array[-1] = bar_mid5
|
||||
|
||||
self.bar_len = len(self.line_bar)
|
||||
# 计算当前self.line_bar长度,并维持self.line_bar序列在max_hold_bars长度
|
||||
self.bar_len = len(self.line_bar) # 当前K线得真实数量(包含已经合成以及正在合成的bar)
|
||||
if self.bar_len > self.max_hold_bars:
|
||||
del self.line_bar[0]
|
||||
self.bar_len = self.bar_len - 1 # 删除了最前面的bar,bar长度少一位
|
||||
|
||||
self.__count_pre_high_low()
|
||||
self.__count_ma()
|
||||
@ -853,9 +870,9 @@ class CtaLineBar(object):
|
||||
self.__count_skdj()
|
||||
self.export_to_csv(bar)
|
||||
|
||||
self.rt_executed = False
|
||||
self.rt_executed = False # 是否 启动实时计算得函数
|
||||
|
||||
# 回调上层调用者
|
||||
# 回调上层调用者,将合成的 x分钟bar,回调给策略 def on_bar_x(self, bar: BarData):函数
|
||||
if self.cb_on_bar:
|
||||
self.cb_on_bar(bar=bar)
|
||||
|
||||
@ -890,6 +907,7 @@ class CtaLineBar(object):
|
||||
|
||||
def export_to_csv(self, bar: BarData):
|
||||
""" 输出到csv文件"""
|
||||
# 将我们配置在self.export_fields的要输出的 bar信息以及指标信息 ==》输出到csv文件
|
||||
if self.export_filename is None or len(self.export_fields) == 0:
|
||||
return
|
||||
field_names = []
|
||||
@ -911,6 +929,8 @@ class CtaLineBar(object):
|
||||
save_dict[field_name] = 0
|
||||
else:
|
||||
save_dict[field_name] = list_obj[-1]
|
||||
elif type_ == 'string':
|
||||
save_dict[field_name] = getattr(self, str(attr_name), '')
|
||||
else:
|
||||
save_dict[field_name] = getattr(self, str(attr_name), 0)
|
||||
|
||||
@ -940,21 +960,21 @@ class CtaLineBar(object):
|
||||
if self.para_ma2_len > 0 and len(self.line_ma2) > 0:
|
||||
msg = msg + u',MA({0}):{1}'.format(self.para_ma2_len, self.line_ma2[-1])
|
||||
if self.ma12_count == 1:
|
||||
msg = msg + u'MA{}金叉MA{}'.format(self.para_ma1_len, self.para_ma2_len)
|
||||
msg = msg + u',MA{}金叉MA{}'.format(self.para_ma1_len, self.para_ma2_len)
|
||||
elif self.ma12_count == -1:
|
||||
msg = msg + u'MA{}死叉MA{}'.format(self.para_ma1_len, self.para_ma2_len)
|
||||
msg = msg + u',MA{}死叉MA{}'.format(self.para_ma1_len, self.para_ma2_len)
|
||||
|
||||
if self.para_ma3_len > 0 and len(self.line_ma3) > 0:
|
||||
msg = msg + u',MA({0}):{1}'.format(self.para_ma3_len, self.line_ma3[-1])
|
||||
if self.ma13_count == 1:
|
||||
msg = msg + u'MA{}金叉MA{}'.format(self.para_ma1_len, self.para_ma3_len)
|
||||
msg = msg + u',MA{}金叉MA{}'.format(self.para_ma1_len, self.para_ma3_len)
|
||||
elif self.ma13_count == -1:
|
||||
msg = msg + u'MA{}死叉MA{}'.format(self.para_ma1_len, self.para_ma3_len)
|
||||
msg = msg + u',MA{}死叉MA{}'.format(self.para_ma1_len, self.para_ma3_len)
|
||||
|
||||
if self.ma23_count == 1:
|
||||
msg = msg + u'MA{}金叉MA{}'.format(self.para_ma2_len, self.para_ma3_len)
|
||||
msg = msg + u',MA{}金叉MA{}'.format(self.para_ma2_len, self.para_ma3_len)
|
||||
elif self.ma23_count == -1:
|
||||
msg = msg + u'MA{}死叉MA{}'.format(self.para_ma2_len, self.para_ma3_len)
|
||||
msg = msg + u',MA{}死叉MA{}'.format(self.para_ma2_len, self.para_ma3_len)
|
||||
|
||||
if self.para_ema1_len > 0 and len(self.line_ema1) > 0:
|
||||
msg = msg + u',EMA({0}):{1}'.format(self.para_ema1_len, self.line_ema1[-1])
|
||||
@ -1016,7 +1036,7 @@ class CtaLineBar(object):
|
||||
round(self.line_upper_atan[-1], self.round_n) if len(self.line_upper_atan) > 0 else 0,
|
||||
round(self.line_lower_atan[-1], self.round_n) if len(self.line_lower_atan) > 0 else 0)
|
||||
|
||||
if (self.para_boll2_len > 0 or self.para_boll2_tb_len > 0) and len(self.line_boll_upper) > 0:
|
||||
if (self.para_boll2_len > 0 or self.para_boll2_tb_len > 0) and len(self.line_boll2_upper) > 0:
|
||||
msg = msg + u',Boll2({}):std:{},m:{},u:{},l:{}'. \
|
||||
format(self.para_boll2_len, round(self.line_boll_std[-1], self.round_n),
|
||||
round(self.line_boll2_middle[-1], self.round_n),
|
||||
@ -1092,6 +1112,7 @@ class CtaLineBar(object):
|
||||
def first_tick(self, tick: TickData):
|
||||
""" K线的第一个Tick数据"""
|
||||
|
||||
# 1、当前新合成的line_bar的第一个tick 数据,创建新的cur_bar,并更新其属性
|
||||
self.cur_bar = BarData(
|
||||
gateway_name=tick.gateway_name,
|
||||
symbol=tick.symbol,
|
||||
@ -1130,13 +1151,14 @@ class CtaLineBar(object):
|
||||
# K线的日期时间(去除秒)设为第一个Tick的时间
|
||||
self.cur_bar.datetime = self.cur_bar.datetime.replace(second=0, microsecond=0)
|
||||
self.cur_bar.time = self.cur_bar.datetime.strftime('%H:%M:%S')
|
||||
self.cur_bar.volume = tick.volume
|
||||
self.cur_bar.volume = tick.last_volume
|
||||
if self.cur_trading_day != self.cur_bar.trading_day or not self.line_bar:
|
||||
# bar的交易日与记录的当前交易日不一致:
|
||||
self.cur_trading_day = self.cur_bar.trading_day
|
||||
|
||||
self.is_first_tick = True # 标识该Tick属于该Bar的第一个tick数据
|
||||
|
||||
# 6、将生成的正在合成的self.cur_bar 推入到line_bar队列
|
||||
self.line_bar.append(self.cur_bar) # 推入到lineBar队列
|
||||
|
||||
def generate_bar(self, tick: TickData):
|
||||
@ -1159,6 +1181,7 @@ class CtaLineBar(object):
|
||||
# 处理日内的间隔时段最后一个tick,如10:15分,11:30分,15:00 和 2:30分
|
||||
endtick = False
|
||||
if not self.is_7x24:
|
||||
# 标记日内的间隔时段最后一个tick,如10:15分,11:30分,15:00 和 2:30分
|
||||
if (tick.datetime.hour == 10 and tick.datetime.minute == 15) \
|
||||
or (tick.datetime.hour == 11 and tick.datetime.minute == 30) \
|
||||
or (tick.datetime.hour == 15 and tick.datetime.minute == 00) \
|
||||
@ -1235,6 +1258,7 @@ class CtaLineBar(object):
|
||||
# 触发OnBar事件
|
||||
self.on_bar(lastBar)
|
||||
|
||||
# 6、没有产生新bar,更新当前正在合成的lastBar属性
|
||||
else:
|
||||
# 更新当前最后一个bar
|
||||
self.is_first_tick = False
|
||||
@ -1244,7 +1268,12 @@ class CtaLineBar(object):
|
||||
lastBar.low_price = min(lastBar.low_price, tick.last_price)
|
||||
lastBar.close_price = tick.last_price
|
||||
lastBar.open_interest = tick.open_interest
|
||||
lastBar.volume += tick.volume
|
||||
|
||||
# 更新bar的 bar内成交量,老版,将tick的volume,减去上一bar的dayVolume
|
||||
# volume_change = tick.volume - self.last_tick.volume
|
||||
# lastbar.volume += max(volume_change, 0)
|
||||
# 更新 bar内成交量volume 新版根据tick内成交量运算
|
||||
lastBar.volume += tick.last_volume
|
||||
|
||||
# 更新Bar的颜色
|
||||
if lastBar.close_price > lastBar.open_price:
|
||||
@ -1267,18 +1296,19 @@ class CtaLineBar(object):
|
||||
return
|
||||
count_len = min(self.para_pre_len, self.bar_len)
|
||||
|
||||
# 2.计算前inputPreLen周期内(不包含当前周期)的Bar高点和低点
|
||||
# 2.计算前self.para_pre_len周期内的Bar高点和低点(不包含当前周期,因为当前正在合成的bar
|
||||
# 还未触发on_bar,不会存入开高低收序列)
|
||||
preHigh = max(self.high_array[-count_len:])
|
||||
preLow = min(self.low_array[-count_len:])
|
||||
if np.isnan(preHigh) or np.isnan(preLow):
|
||||
return
|
||||
# 保存
|
||||
if len(self.line_pre_high) > self.max_hold_bars:
|
||||
# 保存前高值到 前高序列
|
||||
if len(self.line_pre_high) > self.max_hold_bars: # 维持最大缓存数量 超过则删除最前面
|
||||
del self.line_pre_high[0]
|
||||
self.line_pre_high.append(preHigh)
|
||||
|
||||
# 保存
|
||||
if len(self.line_pre_low) > self.max_hold_bars:
|
||||
# 保存前低值到 前低序列
|
||||
if len(self.line_pre_low) > self.max_hold_bars: # 维持最大缓存数量 超过则删除最前面
|
||||
del self.line_pre_low[0]
|
||||
self.line_pre_low.append(preLow)
|
||||
|
||||
|
@ -242,14 +242,18 @@ class XtpMdApi(MdApi):
|
||||
self.connect_status: bool = False
|
||||
self.login_status: bool = False
|
||||
|
||||
|
||||
def onDisconnected(self, reason: int) -> None:
|
||||
""""""
|
||||
self.connect_status = False
|
||||
self.login_status = False
|
||||
self.gateway.write_log(f"行情服务器连接断开, 原因{reason}")
|
||||
|
||||
n = self.login()
|
||||
n = self.login(
|
||||
self.server_ip,
|
||||
self.server_port,
|
||||
self.userid,
|
||||
self.password,
|
||||
self.protocol)
|
||||
|
||||
if n:
|
||||
self.session_id = n
|
||||
|
@ -21,13 +21,13 @@ class UiSnapshot(object):
|
||||
|
||||
pass
|
||||
|
||||
def show(self, snapshot_file: str):
|
||||
def show(self, snapshot_file: str, d=None):
|
||||
|
||||
if d is None:
|
||||
if not os.path.exists(snapshot_file):
|
||||
print(f'{snapshot_file}不存在', file=sys.stderr)
|
||||
return
|
||||
|
||||
d = None
|
||||
with bz2.BZ2File(snapshot_file, 'rb') as f:
|
||||
d = pickle.load(f)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user