From a5afa10d0bd3fdedb0fe7c46a06cd420503f24d9 Mon Sep 17 00:00:00 2001 From: msincenselee Date: Sat, 6 Nov 2021 14:03:55 +0800 Subject: [PATCH] =?UTF-8?q?[=E6=96=B0=E5=A2=9E]=20=E8=82=A1=E7=A5=A8+?= =?UTF-8?q?=E7=BC=A0=E8=AE=BA=E5=BE=97=E4=BD=BF=E7=94=A8=E4=BE=8B=E5=AD=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- examples/stock/demo_03.py | 187 ++++++++++++++++++++++++ examples/stock/demo_03_dist.csv | 5 + examples/stock/demo_04.py | 173 ++++++++++++++++++++++ examples/stock/demo_04_dist.csv | 6 + examples/stock/demo_05.py | 162 +++++++++++++++++++++ examples/stock/demo_05_dist.csv | 15 ++ examples/stock/demo_06.py | 221 +++++++++++++++++++++++++++++ examples/stock/demo_06_dist.csv | 3 + examples/stock/display_snapshot.py | 78 ++++++++++ 9 files changed, 850 insertions(+) create mode 100644 examples/stock/demo_03.py create mode 100644 examples/stock/demo_03_dist.csv create mode 100644 examples/stock/demo_04.py create mode 100644 examples/stock/demo_04_dist.csv create mode 100644 examples/stock/demo_05.py create mode 100644 examples/stock/demo_05_dist.csv create mode 100644 examples/stock/demo_06.py create mode 100644 examples/stock/demo_06_dist.csv create mode 100644 examples/stock/display_snapshot.py diff --git a/examples/stock/demo_03.py b/examples/stock/demo_03.py new file mode 100644 index 00000000..392d5384 --- /dev/null +++ b/examples/stock/demo_03.py @@ -0,0 +1,187 @@ +# flake8: noqa + +# 示例代码 +# 从本地bar_data目录下,读取某股票日线数据,前复权后,推送到K线,识别出顶、底分型,并识别出其强弱,在UI界面上展示出来 + +import os +import sys +import json +from datetime import datetime + +vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +if vnpy_root not in sys.path: + print(f'sys.path append({vnpy_root})') + sys.path.append(vnpy_root) + +os.environ["VNPY_TESTING"] = "1" + +from vnpy.data.tdx.tdx_common import FakeStrategy +from vnpy.component.cta_line_bar import CtaDayBar +from vnpy.trader.ui.kline.ui_snapshot import UiSnapshot +from vnpy.trader.utility import append_data +from vnpy.trader.ui import create_qapp +from vnpy.data.common import get_stock_bars + +# 本示例中,输出的dist文件,主要用于图形显示一些逻辑 +demo_03_dist = 'demo_03_dist.csv' + + +class DemoStrategy(FakeStrategy): + # 输出csv的head + dist_fieldnames = ['datetime', 'vt_symbol', 'volume', 'price', + 'operation'] + + def __init__(self, *args, **kwargs): + + super().__init__() + + # 最后一个找到的符合要求的分型index + self.last_found_fx = None + + # 如果之前存在,移除 + if os.path.exists(demo_03_dist): + self.write_log(f'移除{demo_03_dist}') + os.remove(demo_03_dist) + + self.vt_symbol = kwargs.get('vt_symbol') + + # 创建一个日线bar的 kline对象 + setting = {} + setting['name'] = f'{self.vt_symbol}_D1' + setting['bar_interval'] = 1 + setting['para_ma1_len'] = 55 # 双均线 + setting['para_ma2_len'] = 89 + setting['para_macd_fast_len'] = 12 # 激活macd + setting['para_macd_slow_len'] = 26 + setting['para_macd_signal_len'] = 9 + setting['para_active_chanlun'] = True # 激活缠论 + setting['is_stock'] = True + setting['price_tick'] = 1 + setting['underly_symbol'] = self.vt_symbol.split('.')[0] + self.kline = CtaDayBar(strategy=self, cb_on_bar=self.on_bar, setting=setting) + + def on_bar(self, *args, **kwargs): + """ + 重构on_bar函数,实现demo的分型强弱判断 + :param args: + :param kwargs: + :return: + """ + # 至少要有分型 + if len(self.kline.fenxing_list) == 0: + return + + cur_fx = self.kline.fenxing_list[-1] + + # 如果的分型已经处理过了,就不再计算 + if cur_fx.index == self.last_found_fx: + return + + # 分型是非实时的,已经走完的 + if cur_fx.is_rt: + return + + # 分型前x根bar + pre_bars = [bar for bar in self.kline.line_bar[-10:] if + bar.datetime.strftime('%Y-%m-%d %H:%M:%S') < cur_fx.index] + + if len(pre_bars) == 0: + return + pre_bar = pre_bars[-1] + + # 分型后x根bar + extra_bars = \ + [bar for bar in self.kline.line_bar[-10:] if bar.datetime.strftime('%Y-%m-%d %H:%M:%S') > cur_fx.index] + + # 分型后,有三根bar + if len(extra_bars) < 3: + return + + # 处理顶分型 + if cur_fx.direction == 1: + # 顶分型后第一根bar的低点,没有超过前bar的低点 + if extra_bars[0].low_price >= pre_bar.low_price: + return + + # 找到正确形态,第二、第三根bar,都站在顶分型之下 + if pre_bar.low_price >= extra_bars[1].high_price > extra_bars[2].high_price: + self.last_found_fx = cur_fx.index + append_data(file_name=demo_03_dist, + field_names=self.dist_fieldnames, + dict_data={ + 'datetime': extra_bars[-1].datetime, + 'vt_symbol': self.vt_symbol, + 'volume': 0, + 'price': extra_bars[-1].high_price, + 'operation': '强顶分' + }) + + # 处理底分型 + if cur_fx.direction == -1: + # 底分型后第一根bar的高点,没有超过前bar的高点 + if extra_bars[0].high_price <= pre_bar.high_price: + return + + # 找到正确形态,第二、第三根bar,都站在底分型之上 + if pre_bar.high_price <= extra_bars[1].low_price < extra_bars[2].low_price: + self.last_found_fx = cur_fx.index + append_data(file_name=demo_03_dist, + field_names=self.dist_fieldnames, + dict_data={ + 'datetime': extra_bars[-1].datetime, + 'vt_symbol': self.vt_symbol, + 'volume': 0, + 'price': extra_bars[-1].low_price, + 'operation': '强底分' + }) + + +if __name__ == '__main__': + + # 股票代码.交易所 + vt_symbol = '600000.SSE' + + t1 = DemoStrategy(vt_symbol=vt_symbol) + + # 获取股票得日线数据,返回数据类型是barData + print('加载数据') + bars, msg = get_stock_bars(vt_symbol=vt_symbol, freq='1d', start_date='2019-01-01') + + if len(msg) > 0: + print(msg) + sys.exit(0) + + display_month = None + # 推送bar到kline中 + for bar in bars: + if bar.datetime.month != display_month: + t1.write_log(f'推送:{bar.datetime.year}年{bar.datetime.month}月数据') + display_month = bar.datetime.month + t1.kline.add_bar(bar, bar_is_completed=True) + + # 获取kline的切片数据 + data = t1.kline.get_data() + # 暂时不显示段、中枢等 + data.pop('duan_list', None) + data.pop('bi_zs_list', None) + data.pop('duan_zs_list', None) + + snapshot = { + 'strategy': "demo", + 'datetime': datetime.now(), + "kline_names": [t1.kline.name], + "klines": {t1.kline.name: data}} + + # 创建一个GUI界面应用app + qApp = create_qapp() + + # 创建切片回放工具窗口 + ui = UiSnapshot() + + # 显示切片内容 + ui.show(snapshot_file="", + d=snapshot, # 切片数据 + dist_file=demo_03_dist, # 本地dist csv文件 + dist_include_list=['强底分','强顶分']) # 指定输出的文字内容 + + sys.exit(qApp.exec_()) diff --git a/examples/stock/demo_03_dist.csv b/examples/stock/demo_03_dist.csv new file mode 100644 index 00000000..2ce400a9 --- /dev/null +++ b/examples/stock/demo_03_dist.csv @@ -0,0 +1,5 @@ +datetime,vt_symbol,volume,price,operation +2019-04-02 09:30:00,600000.SSE,0,107.52293310892577,强底分 +2019-04-24 09:30:00,600000.SSE,0,110.91541829027662,强顶分 +2020-01-09 09:30:00,600000.SSE,0,120.77593836872654,强顶分 +2020-01-17 09:30:00,600000.SSE,0,119.41563013287603,强顶分 diff --git a/examples/stock/demo_04.py b/examples/stock/demo_04.py new file mode 100644 index 00000000..b858f558 --- /dev/null +++ b/examples/stock/demo_04.py @@ -0,0 +1,173 @@ +# flake8: noqa + +# 示例代码 +# 从本地bar_data目录下,读取某股票日线数据,前复权后,推送到K线,识别出分笔、线段,并找出首次破坏线段的分笔位置,标注在图上 + +import os +import sys +import json +from datetime import datetime + +vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +if vnpy_root not in sys.path: + print(f'sys.path append({vnpy_root})') + sys.path.append(vnpy_root) + +os.environ["VNPY_TESTING"] = "1" + +from vnpy.data.tdx.tdx_common import FakeStrategy +from vnpy.component.cta_line_bar import CtaDayBar +from vnpy.trader.ui.kline.ui_snapshot import UiSnapshot +from vnpy.trader.utility import append_data +from vnpy.trader.ui import create_qapp +from vnpy.data.common import get_stock_bars + +# 本示例中,输出的dist文件,主要用于图形显示一些逻辑 +demo_04_dist = 'demo_04_dist.csv' + + +class DemoStrategy(FakeStrategy): + # 输出csv的head + dist_fieldnames = ['datetime', 'vt_symbol', 'volume', 'price', + 'operation'] + + def __init__(self, *args, **kwargs): + + super().__init__() + + # 最后一个找到的符合要求的分笔位置 + self.last_found_bi = None + + # 如果之前存在,移除 + if os.path.exists(demo_04_dist): + self.write_log(f'移除{demo_04_dist}') + os.remove(demo_04_dist) + + self.vt_symbol = kwargs.get('vt_symbol') + + # 创建一个日线bar的 kline对象 + setting = {} + setting['name'] = f'{self.vt_symbol}_D1' + setting['bar_interval'] = 1 + setting['para_ma1_len'] = 55 # 双均线 + setting['para_ma2_len'] = 89 + setting['para_macd_fast_len'] = 12 # 激活macd + setting['para_macd_slow_len'] = 26 + setting['para_macd_signal_len'] = 9 + setting['para_active_chanlun'] = True # 激活缠论 + setting['is_stock'] = True + setting['price_tick'] = 1 + setting['underly_symbol'] = self.vt_symbol.split('.')[0] + self.kline = CtaDayBar(strategy=self, cb_on_bar=self.on_bar, setting=setting) + + def on_bar(self, *args, **kwargs): + """ + 重构on_bar函数,实现demo的判断逻辑 + :param args: + :param kwargs: + :return: + """ + if self.kline.cur_duan is None: + return + + # 当前笔的start == 找到的一笔 + if self.kline.cur_bi.start == self.last_found_bi: + return + + # 处理上涨线段 + if self.kline.cur_duan.direction == 1: + # 当前一笔,起点== 线段的结束 + if self.kline.cur_duan.end != self.kline.cur_bi.start: + return + + if len(self.kline.cur_duan.bi_list) <=3: + return + + # 找到次高的分笔位置 + second_high = max([bi.high for bi in self.kline.cur_duan.bi_list[:-2] if bi.direction == 1]) + + if self.kline.cur_bi.low < second_high: + self.last_found_bi = self.kline.cur_bi.start + append_data(file_name=demo_04_dist, + field_names=self.dist_fieldnames, + dict_data={ + 'datetime': self.kline.cur_datetime, + 'vt_symbol': self.vt_symbol, + 'volume': 0, + 'price': self.kline.cur_bi.low, + 'operation': '上升段破坏点' + }) + + # 处理下跌线段 + if self.kline.cur_duan.direction == -1: + # 当前一笔,起点== 线段的结束 + if self.kline.cur_duan.end != self.kline.cur_bi.start: + return + + if len(self.kline.cur_duan.bi_list) <= 3: + return + + # 找到次低的分笔位置 + second_low = min([bi.low for bi in self.kline.cur_duan.bi_list[:-2] if bi.direction == -1]) + + if self.kline.cur_bi.high > second_low: + self.last_found_bi = self.kline.cur_bi.start + append_data(file_name=demo_04_dist, + field_names=self.dist_fieldnames, + dict_data={ + 'datetime': self.kline.cur_datetime, + 'vt_symbol': self.vt_symbol, + 'volume': 0, + 'price': self.kline.cur_bi.high, + 'operation': '下跌段破坏点' + }) + + +if __name__ == '__main__': + + # 股票代码.交易所 + vt_symbol = '600000.SSE' + + t1 = DemoStrategy(vt_symbol=vt_symbol) + + # 获取股票得日线数据,返回数据类型是barData + print('加载数据') + bars, msg = get_stock_bars(vt_symbol=vt_symbol, freq='1d', start_date='2019-01-01') + + if len(msg) > 0: + print(msg) + sys.exit(0) + + display_month = None + # 推送bar到kline中 + for bar in bars: + if bar.datetime.month != display_month: + t1.write_log(f'推送:{bar.datetime.year}年{bar.datetime.month}月数据') + display_month = bar.datetime.month + t1.kline.add_bar(bar, bar_is_completed=True) + + # 获取kline的切片数据 + data = t1.kline.get_data() + # 暂时不显示中枢等 + data.pop('bi_zs_list', None) + data.pop('duan_zs_list', None) + + snapshot = { + 'strategy': "demo", + 'datetime': datetime.now(), + "kline_names": [t1.kline.name], + "klines": {t1.kline.name: data}} + + # 创建一个GUI界面应用app + qApp = create_qapp() + + # 创建切片回放工具窗口 + ui = UiSnapshot() + + # 显示切片内容 + ui.show(snapshot_file="", + d=snapshot, # 切片数据 + dist_file=demo_04_dist, # 本地dist csv文件 + dist_include_list=['上升段破坏点','下跌段破坏点']) # 指定输出的文字内容 + + sys.exit(qApp.exec_()) diff --git a/examples/stock/demo_04_dist.csv b/examples/stock/demo_04_dist.csv new file mode 100644 index 00000000..388408ec --- /dev/null +++ b/examples/stock/demo_04_dist.csv @@ -0,0 +1,6 @@ +datetime,vt_symbol,volume,price,operation +2020-04-28 09:30:00,600000.SSE,0,101.2458,下跌段破坏点 +2020-11-11 09:30:00,600000.SSE,0,93.181114,下跌段破坏点 +2021-03-02 09:30:00,600000.SSE,0,102.02312,上升段破坏点 +2021-04-16 09:30:00,600000.SSE,0,100.85714,上升段破坏点 +2021-09-13 09:30:00,600000.SSE,0,92.1123,下跌段破坏点 diff --git a/examples/stock/demo_05.py b/examples/stock/demo_05.py new file mode 100644 index 00000000..0bc3a8d6 --- /dev/null +++ b/examples/stock/demo_05.py @@ -0,0 +1,162 @@ +# flake8: noqa + +# 示例代码 +# 从本地bar_data目录下,读取某股票日线数据,前复权后,推送到K线,识别出其中枢类型,标注在图上 + +import os +import sys +import json +from datetime import datetime + +vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +if vnpy_root not in sys.path: + print(f'sys.path append({vnpy_root})') + sys.path.append(vnpy_root) + +os.environ["VNPY_TESTING"] = "1" + +from vnpy.data.tdx.tdx_common import FakeStrategy +from vnpy.component.cta_line_bar import CtaDayBar +from vnpy.trader.ui.kline.ui_snapshot import UiSnapshot +from vnpy.trader.utility import append_data +from vnpy.trader.ui import create_qapp +from vnpy.data.common import get_stock_bars + +# 本示例中,输出的dist文件,主要用于图形显示一些逻辑 +demo_05_dist = 'demo_05_dist.csv' + + +class DemoStrategy(FakeStrategy): + # 输出csv的head + dist_fieldnames = ['datetime', 'vt_symbol', 'volume', 'price', + 'operation'] + + def __init__(self, *args, **kwargs): + + super().__init__() + + # 最后一个找到的符合要求的分笔位置 + self.last_found_bi = None + + # 最后一个处理得中枢开始位置 + self.last_found_zs = None + + # 最后一个中枢得判断类型 + self.last_found_type = None + + # 如果之前存在,移除 + if os.path.exists(demo_05_dist): + self.write_log(f'移除{demo_05_dist}') + os.remove(demo_05_dist) + + self.vt_symbol = kwargs.get('vt_symbol') + + # 创建一个日线bar的 kline对象 + setting = {} + setting['name'] = f'{self.vt_symbol}_D1' + setting['bar_interval'] = 1 + setting['para_ma1_len'] = 55 # 双均线 + setting['para_ma2_len'] = 89 + setting['para_macd_fast_len'] = 12 # 激活macd + setting['para_macd_slow_len'] = 26 + setting['para_macd_signal_len'] = 9 + setting['para_active_chanlun'] = True # 激活缠论 + setting['is_stock'] = True + setting['price_tick'] = 1 + setting['underly_symbol'] = self.vt_symbol.split('.')[0] + self.kline = CtaDayBar(strategy=self, cb_on_bar=self.on_bar, setting=setting) + + def on_bar(self, *args, **kwargs): + """ + 重构on_bar函数,实现demo的判断逻辑 + :param args: + :param kwargs: + :return: + """ + if self.kline.cur_duan is None: + return + + if self.kline.cur_bi_zs is None: + return + + # 当前笔的start == 上一次判断过得 + if self.kline.cur_bi.start == self.last_found_bi: + return + + # 当前笔中枢与上一个笔中枢得开始不同,可能是个新得笔中枢 + if self.kline.cur_bi_zs.start != self.last_found_zs: + # 设置为最新判断中枢 + self.last_found_zs = self.kline.cur_bi_zs.start + # 设置中枢得最后一笔开始时间,为最新判断时间 + self.last_found_bi = self.kline.cur_bi_zs.bi_list[-1].start + # 设置中枢得类型为None + self.last_found_type = None + return + + # K线最后一笔得开始 = 中枢最后一笔得结束 + if self.kline.cur_bi.start == self.kline.cur_bi_zs.bi_list[-1].end: + # 获得类型 + zs_type = self.kline.cur_bi_zs.get_type() + + # 记录下,这一笔已经执行过判断了 + self.last_found_bi = self.kline.cur_bi.start + + # 不一致时,才写入 + if zs_type != self.last_found_type: + self.last_found_type = zs_type + append_data(file_name=demo_05_dist, + field_names=self.dist_fieldnames, + dict_data={ + 'datetime': self.kline.cur_datetime, + 'vt_symbol': self.vt_symbol, + 'volume': 0, + 'price': self.kline.cur_bi_zs.low, + 'operation': zs_type + }) + + +if __name__ == '__main__': + + # 股票代码.交易所 + vt_symbol = '600000.SSE' + + t1 = DemoStrategy(vt_symbol=vt_symbol) + + # 获取股票得日线数据,返回数据类型是barData + print('加载数据') + bars, msg = get_stock_bars(vt_symbol=vt_symbol, freq='1d', start_date='2019-01-01') + + if len(msg) > 0: + print(msg) + sys.exit(0) + + display_month = None + # 推送bar到kline中 + for bar in bars: + if bar.datetime.month != display_month: + t1.write_log(f'推送:{bar.datetime.year}年{bar.datetime.month}月数据') + display_month = bar.datetime.month + t1.kline.add_bar(bar, bar_is_completed=True) + + # 获取kline的切片数据 + data = t1.kline.get_data() + + snapshot = { + 'strategy': "demo", + 'datetime': datetime.now(), + "kline_names": [t1.kline.name], + "klines": {t1.kline.name: data}} + + # 创建一个GUI界面应用app + qApp = create_qapp() + + # 创建切片回放工具窗口 + ui = UiSnapshot() + + # 显示切片内容 + ui.show(snapshot_file="", + d=snapshot, # 切片数据 + dist_file=demo_05_dist, # 本地dist csv文件 + dist_include_list=['close','enlarge','balance','attact', 'defend']) # 指定输出的文字内容 + + sys.exit(qApp.exec_()) diff --git a/examples/stock/demo_05_dist.csv b/examples/stock/demo_05_dist.csv new file mode 100644 index 00000000..5c8b1f1c --- /dev/null +++ b/examples/stock/demo_05_dist.csv @@ -0,0 +1,15 @@ +datetime,vt_symbol,volume,price,operation +2019-08-08 09:30:00,600000.SSE,0,103.18809,close +2019-08-15 09:30:00,600000.SSE,0,103.18809,defend +2019-11-22 09:30:00,600000.SSE,0,109.01899,defend +2019-12-18 09:30:00,600000.SSE,0,103.18809,defend +2020-01-06 09:30:00,600000.SSE,0,103.18809,defend +2020-05-13 09:30:00,600000.SSE,0,99.3025,attact +2020-06-02 09:30:00,600000.SSE,0,99.3025,close +2020-06-12 09:30:00,600000.SSE,0,99.3025,defend +2020-12-08 09:30:00,600000.SSE,0,90.84916,enlarge +2021-01-25 09:30:00,600000.SSE,0,90.84916,close +2021-02-02 09:30:00,600000.SSE,0,90.84916,enlarge +2021-02-08 09:30:00,600000.SSE,0,90.84916,close +2021-05-28 09:30:00,600000.SSE,0,100.66281,enlarge +2021-09-22 09:30:00,600000.SSE,0,87.15689,enlarge diff --git a/examples/stock/demo_06.py b/examples/stock/demo_06.py new file mode 100644 index 00000000..decd4cc5 --- /dev/null +++ b/examples/stock/demo_06.py @@ -0,0 +1,221 @@ +# flake8: noqa + +# 示例代码 +# 从本地bar_data目录下,读取某股票日线数据,前复权后,推送到K线,识别出其趋势线段、盘整线段、趋势背驰信号点,标注在图上 + +import os +import sys +import json +from datetime import datetime + +vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +if vnpy_root not in sys.path: + print(f'sys.path append({vnpy_root})') + sys.path.append(vnpy_root) + +os.environ["VNPY_TESTING"] = "1" + +from vnpy.data.tdx.tdx_common import FakeStrategy +from vnpy.component.cta_line_bar import CtaDayBar +from vnpy.trader.ui.kline.ui_snapshot import UiSnapshot +from vnpy.trader.utility import append_data +from vnpy.trader.ui import create_qapp +from vnpy.data.common import get_stock_bars + +# 本示例中,输出的dist文件,主要用于图形显示一些逻辑 +demo_06_dist = 'demo_06_dist.csv' + + +class DemoStrategy(FakeStrategy): + # 输出csv的head + dist_fieldnames = ['datetime', 'vt_symbol', 'volume', 'price', + 'operation'] + + def __init__(self, *args, **kwargs): + + super().__init__() + + # 最后一个执行检查的分笔开始位置 + self.last_check_bi = None + + # 最后一个检查线段 + self.last_found_duan = None + + # 最后一个判断类型(趋势、盘整) + self.last_found_type = None + + # 最后一个判断背驰的分型信号 + self.last_found_beichi = None + + # 如果之前存在,移除 + if os.path.exists(demo_06_dist): + self.write_log(f'移除{demo_06_dist}') + os.remove(demo_06_dist) + + self.vt_symbol = kwargs.get('vt_symbol') + + # 创建一个日线bar的 kline对象 + setting = {} + setting['name'] = f'{self.vt_symbol}_D1' + setting['bar_interval'] = 1 + setting['para_ma1_len'] = 55 # 双均线 + setting['para_ma2_len'] = 89 + setting['para_macd_fast_len'] = 12 # 激活macd + setting['para_macd_slow_len'] = 26 + setting['para_macd_signal_len'] = 9 + setting['para_active_chanlun'] = True # 激活缠论 + setting['is_stock'] = True + setting['price_tick'] = 1 + setting['underly_symbol'] = self.vt_symbol.split('.')[0] + self.kline = CtaDayBar(strategy=self, cb_on_bar=self.on_bar, setting=setting) + + def on_bar(self, *args, **kwargs): + """ + 重构on_bar函数,实现demo的判断逻辑 + :param args: + :param kwargs: + :return: + """ + if self.kline.cur_duan is None or self.kline.cur_bi_zs is None: + return + + cur_fx = self.kline.fenxing_list[-1] + # 分型未结束,不做判断 + if cur_fx.is_rt: + return + + # 当前段与上一次检查的段,开始时间不同,执行检查 + if self.kline.cur_duan.start != self.last_found_duan: + + # 判断条件: + # 当前线段后出现一个分笔 + # 当前线段的结束时间比最后一个中枢晚 + if self.kline.cur_duan.end == self.kline.cur_bi.start \ + and self.kline.cur_duan.end > self.kline.cur_bi_zs.end\ + and self.kline.cur_bi.start != self.last_check_bi: + + # 判断是否盘整, 当前线段比上一线段短 + if self.kline.pre_duan and self.kline.pre_duan.height * 0.62 > self.kline.cur_duan.height: + # 获取该线段start -> end 之间,存在的中枢 + zs_list = [zs for zs in self.kline.bi_zs_list if zs.start > self.kline.cur_duan.start and zs.end < self.kline.cur_duan.end] + # 存在的一个中枢 + if len(zs_list) == 1: + # 记录该笔已经检查过 + self.last_check_bi = self.kline.cur_bi.start + + # 盘整名称,price位置 + if self.kline.cur_duan.direction == 1: + self.last_found_type = '下跌盘整' + price = self.kline.cur_duan.high + else: + self.last_found_type = '上涨盘整' + price = self.kline.cur_duan.low + + # 写入记录 + append_data(file_name=demo_06_dist, + field_names=self.dist_fieldnames, + dict_data={ + 'datetime': datetime.strptime(self.kline.cur_duan.end, '%Y-%m-%d %H:%M:%S'), + 'vt_symbol': self.vt_symbol, + 'volume': 0, + 'price': price, + 'operation': self.last_found_type + }) + + # 判断是否趋势 + if self.kline.is_contain_zs_inside_duan(direction=self.kline.cur_duan.direction, + cur_duan=self.kline.cur_duan, + zs_num=2): + # 记录检查的一笔 + self.last_check_bi = self.kline.cur_bi.start + # 记录检查的线段 + self.last_found_duan = self.kline.cur_duan.start + + # 趋势名称、价格 + if self.kline.cur_duan.direction == 1: + self.last_found_type = '上涨趋势' + price = self.kline.cur_duan.high + else: + self.last_found_type = '下跌趋势' + price = self.kline.cur_duan.low + + # 记录数据 + append_data(file_name=demo_06_dist, + field_names=self.dist_fieldnames, + dict_data={ + 'datetime': datetime.strptime(self.kline.cur_duan.end, '%Y-%m-%d %H:%M:%S'), + 'vt_symbol': self.vt_symbol, + 'volume': 0, + 'price': price, + 'operation': self.last_found_type + }) + + # 判断是否走势背驰 + if self.kline.is_zs_beichi_inside_duan(direction=self.kline.cur_duan.direction, + cur_duan=self.kline.cur_duan): + if cur_fx.index != self.last_found_beichi: + self.last_found_beichi = cur_fx.index + # 趋势名称、价格 + if self.kline.cur_duan.direction == 1: + self.last_found_type = '上涨背驰' + price = self.kline.cur_duan.high + else: + self.last_found_type = '下跌背驰' + price = self.kline.cur_duan.low + + # 记录数据 + append_data(file_name=demo_06_dist, + field_names=self.dist_fieldnames, + dict_data={ + 'datetime': datetime.strptime(self.kline.cur_duan.end, '%Y-%m-%d %H:%M:%S'), + 'vt_symbol': self.vt_symbol, + 'volume': 0, + 'price': price, + 'operation': self.last_found_type + }) + +if __name__ == '__main__': + + # 股票代码.交易所 + vt_symbol = '600000.SSE' + + t1 = DemoStrategy(vt_symbol=vt_symbol) + + # 获取股票得日线数据,返回数据类型是barData + print('加载数据') + bars, msg = get_stock_bars(vt_symbol=vt_symbol, freq='1d', start_date='2019-01-01') + + if len(msg) > 0: + print(msg) + sys.exit(0) + + display_month = None + # 推送bar到kline中 + for bar in bars: + if bar.datetime.month != display_month: + t1.write_log(f'推送:{bar.datetime.year}年{bar.datetime.month}月数据') + display_month = bar.datetime.month + t1.kline.add_bar(bar, bar_is_completed=True) + + # 获取kline的切片数据 + data = t1.kline.get_data() + + snapshot = { + 'strategy': "demo", + 'datetime': datetime.now(), + "kline_names": [t1.kline.name], + "klines": {t1.kline.name: data}} + + # 创建一个GUI界面应用app + qApp = create_qapp() + + # 创建切片回放工具窗口 + ui = UiSnapshot() + + # 显示切片内容 + ui.show(snapshot_file="", + d=snapshot, # 切片数据 + dist_file=demo_06_dist, # 本地dist csv文件 + dist_include_list=['上涨趋势','下跌趋势','上涨盘整','下跌盘整','上涨背驰','下跌背驰']) # 指定输出的文字内容 + + sys.exit(qApp.exec_()) diff --git a/examples/stock/demo_06_dist.csv b/examples/stock/demo_06_dist.csv new file mode 100644 index 00000000..80e887df --- /dev/null +++ b/examples/stock/demo_06_dist.csv @@ -0,0 +1,3 @@ +datetime,vt_symbol,volume,price,operation +2020-07-31 09:30:00,600000.SSE,0,100.17699,下跌背驰 +2021-02-19 09:30:00,600000.SSE,0,108.04734,下跌盘整 diff --git a/examples/stock/display_snapshot.py b/examples/stock/display_snapshot.py new file mode 100644 index 00000000..d577f5ac --- /dev/null +++ b/examples/stock/display_snapshot.py @@ -0,0 +1,78 @@ +# flake8: noqa + +# 示例代码 +# 从策略保存K线数据中,读取某一K线,并显示 + +import os +import sys +import json + +vnpy_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..')) +if vnpy_root not in sys.path: + print(f'sys.path append({vnpy_root})') + sys.path.append(vnpy_root) + +os.environ["VNPY_TESTING"] = "1" + +from vnpy.data.tdx.tdx_common import FakeStrategy +from vnpy.data.tdx.tdx_stock_data import * +from vnpy.component.cta_line_bar import CtaMinuteBar +from vnpy.trader.ui.kline.ui_snapshot import UiSnapshot +from vnpy.trader.ui import create_qapp +from vnpy.data.common import get_stock_bars + +snapshot_file_name = 'prod/stock_pb/data/stock_clone_value_klines.pkb2' +kline_name = '601012.SSE_D1' +def get_klines(pkb2_files): + """ + 从缓存加载K线数据 + :param kline_names: 指定需要加载的k线名称列表 + :param vt_symbol: 指定股票代码, + 如果使用该选项,加载 data/klines/strategyname_vtsymbol_klines.pkb2 + 如果空白,加载 data/strategyname_klines.pkb2 + :return: + """ + if not os.path.exists(pkb2_files): + return {} + + try: + with bz2.BZ2File(pkb2_files, 'rb') as f: + klines = pickle.load(f) + + return klines + except Exception as ex: + print(f'加载缓存K线数据失败:{str(ex)}') + return {} + +if __name__ == "__main__": + + # 创建一个假的策略 + t1 = FakeStrategy() + + file_name = os.path.abspath(os.path.join(vnpy_root,snapshot_file_name)) + klines = get_klines(file_name) + + print(f'kline names:{klines.keys()}') + + kline = klines.get(kline_name,None) + if kline: + # 获取kline的切片数据 + data = kline.get_data() + snapshot = { + 'strategy': "demo", + 'datetime': datetime.now(), + "kline_names": [kline.name], + "klines": {kline.name: data}} + + # 创建一个GUI界面应用app + qApp = create_qapp() + + # 创建切片回放工具窗口 + ui = UiSnapshot() + # 显示切片内容 + ui.export(snapshot_file="", + d=snapshot, + export_file='s.png') + #sys.exit(qApp.exec_()) + else: + print(f'not found {kline_name}')