import pandas as pd from typing import Dict,List from scr.pattern_detect import find_RoundingBottom from scr.plotting import view_gride_chart
数据读取
- 时间范围:2014-01-01至2023-02-07
- 价格数据为后复权数据
data:pd.DataFrame = pd.read_csv('data/data.csv',index_col=[0,1],parse_dates=[0])
形态匹配
形态定义
- 取当日向前追溯两年的股价数据进行核回归,根据核回归的结果找到所有局部极值点,对于每个极小值点Plow𝑃𝑙𝑜𝑤,找到其前面一个极大值点;
- 在这个极大值点的邻域中(本文取前后20天范围内)找到股价序列的最大值,作为前一盘整区的高点,记为Phigh𝑃ℎ𝑖𝑔ℎ,定义Phigh𝑃ℎ𝑖𝑔ℎ到Plow𝑃𝑙𝑜𝑤的水平距离为圆弧的半弦长𝑑(要求𝑑大于10天);
- 定义在PlowP𝑙𝑜𝑤前后𝑑天范围内的股价序列为s,收益率绝对值序列为r,检验是否满足圆弧底形态的条件:
- s在PlowPlow左(右)侧下跌(上涨)的所占比例大于某一参数(本文取0.4);
- r的均值小于某一参数(本文取0.03);
- (Phigh/Plow−1)/d(Pℎ𝑖𝑔ℎ⁄Plow−1)/𝑑、(Pbuy/Plow−1)/d(P𝑏𝑢𝑦⁄Plow−1)/𝑑小于某一参数(本文取0.03);
- 若识别为圆弧底形态,则在s的右半部分寻找是否存在大于PhighPℎ𝑖𝑔ℎ且已经突破200日均线的点,若存在,则将第一个突破PhighPℎ𝑖𝑔ℎ的点作为买入点Pbuy𝑃𝑏𝑢𝑦。同时要求(1−p)∗(Phigh−Plow)<Pbuy−Plow<(1+p)∗(Phigh−Plow)(1−p)∗(Pℎ𝑖𝑔ℎ−𝑃𝑙𝑜𝑤)<𝑃𝑏𝑢𝑦−𝑃𝑙𝑜𝑤<(1+p)∗(Pℎ𝑖𝑔ℎ−𝑃𝑙𝑜𝑤)(本文中p取0.3);
下面为出现圆弧底时对应的买入/卖出点
- 若开仓后的某日回归曲线中Plow后面出现一个极大值点,则把当日作为卖出点𝑃𝑙𝑜𝑤后面出现一个极大值点,则把当日作为卖出点𝑃_{𝑠𝑒𝑙𝑙}$;
- 如果下跌幅度超过10%则触发止损条件,卖出股票;
- 对于其他极小值点-极大值点组合,重复上述过程。
除了找到极值点用到了核回归的结果,其他步骤用的都是实际的价格数据.
查找2023-02-07日当天符合圆弧底形态的股票
output: Dict = { code: find_RoundingBottom( slice_df.reset_index(level=1, drop=True), code=code ) for code, slice_df in data.groupby(level='code') }
可视化结果
output_df:pd.DataFrame = pd.DataFrame(output,index=['是否圆弧底','是否符合买入点']).T
output_df.head()
.dataframe tbody tr th:only-of-type { vertical-align: middle; } .dataframe tbody tr th { vertical-align: top; } .dataframe thead th { text-align: right; }
是否圆弧底 | 是否符合买入点 | |
---|---|---|
000001.SZ | False | False |
000002.SZ | False | False |
000004.SZ | False | False |
000005.SZ | False | False |
000006.SZ | False | True |
# 获取符合形态的股票 rounding_bottom:pd.DataFrame = output_df.query("是否圆弧底==True") # 符合圆弧底形态的股票代码 codes:List = rounding_bottom.index.tolist()
cols:int = 2 size:int = len(codes) rows:int = size//2 + 1 if size%2 else size/2 view_gride_chart(codes,data,rows=rows,cols=cols,figsize=(20,rows*5+5))