思路:
股票数据日K下载完成(如果需要,关注后续:快速下载更新A股所有日K数据)
收集当天的除权、除息股票名称和代码:
def get_fq_data(): """ 除权除息当天的股票名称是以: XD,XR,DR开头命名的 """ from MG_re_tdx_zsorhy import get_stock_baisc use_li = ["exchange", "eastmoney", "hexun+"] # 从交易所、东财、和讯同花顺等完整免费获取 fq_stock_names = get_stock_baisc(use_lsit=use_li, to_conf=False, puf_data=True) fq_stock_names = fq_stock_names[fq_stock_names['name'].apply(lambda x: x[:2] in ['XD', 'XR', 'DR'])] return fq_stock_names
当前除权除息运行效果:
有了除权除息数据,默认按通达信gbbq文件的数据计算复权最快最准确;如果通达信gbbq未及时更新,可自动切换到baostock 提供的免费复权因子运算该名单股票的复权(两种方式都能前复权和后复权)
def get_query_adjust_factor(self, code="sh.601398", start_date="2015-01-01", end_date="2025-12-31"): """ @param code: 股票代码,sh或sz.+6位数字代码,或者指数代码,如:sh.601398; @param start_date: 开始日期 (格式:YYYY-MM-DD) @param end_date: 结束日期 (格式:YYYY-MM-DD) @return: 获取复权因子信息数据 """ # 登陆系统 # self.eDbs.login() # 显示登陆返回信息 # print('login respond error_code:' + lg.error_code) # print('login respond error_msg:' + lg.error_msg) rs_list = [] rs_factor = self.eDbs.query_adjust_factor(code=code, start_date=start_date, end_date=end_date) # 登出系统 # self.eDbs.logout() while (rs_factor.error_code == '0') & rs_factor.next(): rs_list.append(rs_factor.get_row_data()) if rs_list: result_factor = pd.DataFrame(rs_list, columns=rs_factor.fields) result_factor = result_factor.apply(pd.to_numeric, errors='ignore') result_factor['date'] = pd.to_datetime(result_factor['dividOperateDate']) result_factor.set_index('date', drop=True, inplace=True) else: result_factor = pd.DataFrame() return result_factor
运算复权:
完整代码请从资源下载 ....
def _adj_baostock(df_stock, pkl_cqcx, fqtype): # 如果数据有复权因子列则删除 if 'adj' in df_stock.columns: df_stock = df_stock.drop(['adj'], axis=1) # 赋值复权因子列 if fqtype == 'qfq': pkl_cqcx = pkl_cqcx.rename(columns={'foreAdjustFactor': 'adj'}) # 列改名,为了concat可以匹配 df_stock = pd.concat([df_stock, pkl_cqcx[['adj']][df_stock.index[0]:]], axis=1) elif fqtype == 'hfq': pkl_cqcx = pkl_cqcx.rename(columns={'backAdjustFactor': 'adj'}) # 列改名,为了update可以匹配 df_stock = pd.concat([df_stock, pkl_cqcx[['adj']][df_stock.index[0]:]], axis=1) # 清洗复权因子数据 df_stock = df_stock.fillna(method='ffill') # 向下填充无效值 # 再检查释放有无效值, 如果股票不是从上市日期开始的数据;则会前行数据是nan if df_stock['adj'].isnull().any(): df_stock = df_stock.fillna(method='backfill') # 向上填充无效值 init_fq = True # 是否需要运算复权 if fqtype == 'qfq': if df_stock['adj'].sum() == df_stock.shape[0]: # 前复权因子全部是1则不需要计算复权数据 init_fq = False elif fqtype == 'hfq': def BARSLASTCOUNT(S): # 统计连续满足S条件的周期数 rt = np.zeros(len(S) + 1) # BARSLASTCOUNT(CLOSE>OPEN)表示统计连续收阳的周期数 for i in range(len(S)): rt[i + 1] = rt[i] + 1 if S[i] else rt[i + 1] return rt[1:] if BARSLASTCOUNT(df_stock['adj'].values < 1) == df_stock.shape[0]: # 前复权因子全部不是1则不需要计算复权数据 init_fq = False # 获得复权数据 if init_fq: df_stock['open'] = df_stock['open'] * df_stock['adj'] df_stock['high'] = df_stock['high'] * df_stock['adj'] df_stock['low'] = df_stock['low'] * df_stock['adj'] df_stock['close'] = df_stock['close'] * df_stock['adj'] df_stock = df_stock.round({'open': 2, 'high': 2, 'low': 2, 'close': 2, }) # 指定列四舍五入 # baostok 复权完成 return df_stock def baostock_fq(pkl_cqcx, df_stock, fqtype='qfq'): # 保留流通股、换手率等数据 if '流通股' in df_stock.columns: df_original = df_stock[['流通股', '流通市值', '换手率']] df_stock = df_stock.drop(['流通股', '流通市值', '换手率'], axis=1) # 计算复权因子及得到复权数据 df_stock = _adj_baostock(df_stock, pkl_cqcx, fqtype) df_stock = pd.concat([df_stock, df_original], axis=1) return df_stock # 保留流通股、换手率等数据直接计算 df_stock = _adj_baostock(df_stock, pkl_cqcx, fqtype) # 复权处理完成 return df_stock
以上是baostock复权因子复权
完整代码请从资源下载 ....