1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| from tools.dbtools import *
# 计算相似度的行情区间 start_date = datetime(2020, 1, 1, tzinfo=pytz.utc) end_date = datetime(2023, 1, 1, tzinfo=pytz.utc) start_date_str= start_date.strftime("%Y-%m-%d") end_date_str= end_date.strftime("%Y-%m-%d")
def low_correlation_set(symbols=[],max_nan_days = 100,min_price_var=5.0,similar_threshold = 0.5): # max_nan_days: 最大nan行情,不添加此筛选,会选出长期停牌标的 # min_price_var: 过滤掉低方差标的,不添加此筛选,会选出小波动标的(大多为债基etf) # similar_threshold: 相似度阈值,高于此取值认为相似的 choose_set = set() # 低相关度标的集合 # 标的行情 yfdata=MySQLData.download(symbols,start_dt=start_date_str,end_dt=end_date_str) # 自带工具类查询
ohlcv = yfdata.concat() price = ohlcv['Close'] # 收盘价
# 过滤掉停牌次数过多的标的 price_nan=price.isna().sum()>=max_nan_days for key,value in price_nan.items(): if value: price.drop(columns=key,inplace=True) # 过滤掉波动过小的标的 price_var=price.var()<min_price_var for key,value in price_var.items(): if value: price.drop(columns=key,inplace=True)
# 相似度计算 returns = price.pct_change() return_corr=returns.corr() corr_stack=return_corr.stack() corr_stack=corr_stack.sort_values() #相关度排序
# 低相关度股票组合 for idx in range(0,corr_stack.size,2): # 相似度矩阵corr是对称矩阵,stack后存在一半的重复记录,0-1或2-3其实对应同一个标的,类似pair(a,b)和(b,a)的关系,只取偶数避免重复计算 pair_stock=corr_stack.index[idx] if corr_stack[idx]<similar_threshold: for stock in pair_stock: if stock in choose_set: continue; isBreak=False for base_stock in choose_set: if corr_stack[(base_stock,stock)]>similar_threshold: isBreak=True # 说明和已经选中的某标的相似度过高 break if not isBreak: # 和选中的标的均不相似 choose_set.add(stock) return choose_set
|