def load_codes(codes):
dfs = collections.OrderedDict()
for code in codes:
df = load_code(code)
df.index = df['_id']
del df['_id']
df.sort_values(by='trade_date',ascending=True)
if 'adj_factor' in list(df.columns):
for col in ['open', 'high', 'low', 'close']:
df[col] = df[col] * df['adj_factor'] #直接后复权了
del df['adj_factor']
if 'adj_nav' in df.columns:
df['rate'] = df['adj_nav'].pct_change()
elif 'close' in df.columns:
df['rate'] = df['close'].pct_change()
dfs[code] = df
return dfs
按trade_date从前往后排序,同时如果有复权因子,把OHLC的数据按后复权计算。然后把根据close字段及adj_nav(基金的复权净值) 使用 pandas的pct_change()计算日计收益率。
二、数据提取与合并
为了便于分析,会把多支证券的数据合并起来,常见的合并有如下几种:
a)纵向合并,日期取所有dataframe里最大的,而后按日期取并集,重新索引所有的dataframe。这样做是由于A股与美股交易的caledar不一样,如果不处理的话,放到一起会有一些日期为NaN。
def merge_dfs(dfs):
max_date = calc_max_date(dfs)
for code,df in dfs.items():
df = df[df['date'] > max_date]
dfs[code] = df
calendar = calc_calendar(dfs)
new_dfs = []
for code,df in dfs.items():
df.index = df['date']
del df['date'] #要选删掉,否则date会ffill
df = df.reindex(index=calendar, method='ffill')
df['date'] = df.index
df.index = df['date'] + '_' + df['symbol']
new_dfs.append(df)
df_all = pd.concat(new_dfs,axis=0)
df_all.dropna(inplace=True)
df_all.sort_index(inplace=True)
return df_all
得到如下合并好的数据集:
b)横向合并,把收益率合并,用于组合或多个时间序列做分析。
#在纵向的基础上,把rate合并出来
def dfs2rate(df_all,codes=None):
if codes:
symbols = codes
else:
symbols = df_all.symbol.unique()
prices = []
for s in symbols:
df = df_all[df_all['symbol']== s]
df.index = df['date']
se = df['rate']
se.name = s
prices.append(se)
return pd.concat(prices,axis=1)
c)纵向多索引,两个索引分别是date,symbol,这是因子分析框架alphalens需要的输入格式:
#纵向合成,并把Date,symbol作为多索引
def dfall_to_multiindex(df_all):
df = df_all.copy()
df['date'] = df['date'].apply(lambda x: datetime.strptime(x, '%Y%m%d'))
df.set_index(['date', 'symbol'], inplace=True)
df.sort_index(inplace=True)
return df
至此,数据准备工作基本完成,可以进行数据分析了。
(公众号: 七年实现财富自由(ailabx),用数字说基金,用基金做投资组合,践行财富自由之路)