Files
World_Quant_Alphas/WQ_Alphas_Analysis.py
T

632 lines
27 KiB
Python
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
Created on Tue Feb 21 17:38:39 2017
@author: LZJF
"""
import pandas as pd
import numpy as np
import matplotlib as mpl
# import statsmodels.api as sm
import os
mpl.style.use('ggplot')
os.chdir('C:\cStrategy\Factor')
def import_data(name):
data = pd.read_csv('%s.csv' % name, index_col=0)
data.index = pd.to_datetime([str(i) for i in data.index])
return data
def pearson(x, y, skipna=False):
upside = ((x - x.mean()) * (y - y.mean())).sum(skipna=skipna)
downside = np.sqrt((np.square(x - x.mean()).sum()) *
(np.square(y - y.mean()).sum(skipna=skipna)))
return upside / downside
def save_factor(factor, factor_id, no_zdt):
if no_zdt:
factor_name = 'alpha#%s_no_zdt_1D' % factor_id
else:
factor_name = 'alpha#%s_origin_1D' % factor_id
factor.index.name = factor_name
to_file = 'F:\Strategies\World_Quant_Alphas/#%s' % factor_id
if not os.path.exists(to_file):
os.mkdir(to_file)
else:
pass
factor.to_csv(to_file + '/%s.csv' % factor_name)
print '保存完成'
def rolling_stop(stop, window):
temp = pd.DataFrame(index=stop.columns)
for i in stop.index:
one = stop[:i][-window:].notnull().any(axis=0)
temp[i] = one
return temp.T
def rolling_rank(data, window):
temp = pd.DataFrame(index=data.columns)
for i in data.index:
one = data[:i][-window:].rank(axis=0, pct=True).iloc[-1]
temp[i] = one
return temp.T
def rolling_new(data, window):
temp = pd.DataFrame(index=data.columns)
for i in data.index:
one = data[:i][-window:].isnull().any(axis=0)
temp[i] = one
return temp.T
def linear_decay(data, window):
result = pd.DataFrame(np.nan, index=data.index, columns=data.columns)
weight = np.arange(window) + 1.
weight = weight / weight.sum()
for i in range(window, data.shape[0]):
t = data.index[i]
result.ix[t,:] = data[i-window:i].T.dot(weight)
return result
def factor_cal(data, factor_id, no_zdt=False, no_st=False, no_new=False):
high = data['high']
low = data['low']
close = data['close']
OPEN = data['OPEN']
value = data['value']
volume = data['volume']
stop = data['stop']
st = data['st']
fcf = data['fcf']
asset_debt = data['asset_debt']
price_adj_f = data['price_adj_f']
adj_OPEN = OPEN * price_adj_f
adj_close = close * price_adj_f
adj_high = high * price_adj_f
adj_low = low * price_adj_f
adj_volume = volume / price_adj_f
returns = adj_close.pct_change()
print '开始计算'
if factor_id == '001':
returns = adj_close.pct_change()
returns[returns < 0] = returns.rolling(window=20).std()
ts_argmax = np.square(returns).rolling(window=5).apply(np.argmax) + 1
factor = ts_argmax.rank(axis=1, pct=True) - 0.5
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '002':
temp1 = np.log(adj_volume).diff(2)
temp1_rank = temp1.rank(axis=1, pct=True)
temp2 = (close - OPEN) / OPEN
temp2_rank = temp2.rank(axis=1, pct=True)
factor = pd.DataFrame()
for t in temp1_rank.index:
day_factor = -1 * pearson(temp1_rank[:t][-6:], temp2_rank[:t][-6:])
factor[t] = day_factor
factor = factor.T
elif factor_id == '003':
open_rank = OPEN.rank(axis=1, pct=True)
volume_rank = volume.replace(0, np.nan).rank(axis=1, pct=True)
factor = pd.DataFrame()
for t in open_rank.index:
day_factor = -1 * pearson(open_rank[:t][-10:], volume_rank[:t][-10:])
factor[t] = day_factor
factor = factor.T
factor[stop.notnull()] = np.nan
elif factor_id == '004':
low_rank = adj_low.rank(axis=1, pct=True)
factor = -1 * rolling_rank(low_rank, 9)
factor[rolling_stop(stop, 9)] = np.nan
elif factor_id == '005':
vwap = value / adj_volume
be_half = (adj_OPEN - vwap.rolling(window=10).mean()).rank(axis=1, pct=True)
af_half = (adj_close - vwap).rank(axis=1, pct=True)
factor = -1 * be_half * af_half
elif factor_id == '006':
factor = pd.DataFrame()
adj_volume = adj_volume.replace(0, np.nan)
for t in OPEN.index:
day_factor = -1 * pearson(adj_OPEN[:t][-10:], adj_volume[:t][-10:])
factor[t] = day_factor
factor = factor.T
elif factor_id == '007':
factor = -1 * rolling_rank(np.abs(adj_close.diff(7)), 60) * np.sign(adj_close.diff(7))
factor[adj_volume.rolling(window=20).mean() > volume] = -1
elif factor_id == '008':
temp = OPEN.rolling(window=5).sum() * returns.rolling(window=5).sum()
factor = -1 * (temp - temp.diff(10)).rank(axis=1, pct=True)
# temp - temp.diff(10) 不就是10日前的temp吗? SB啊!
factor[stop.notnull()] = np.nan
elif factor_id == '009':
cond_1 = adj_close.diff().rolling(window=5).min() > 0
cond_2 = adj_close.diff().rolling(window=5).max() < 0
factor = -1 * adj_close.diff()
factor[cond_1 | cond_2] = adj_close.diff()
elif factor_id == '010':
cond_1 = adj_close.diff().rolling(window=4).min() > 0
cond_2 = adj_close.diff().rolling(window=4).max() < 0
factor = -1 * adj_close.diff()
factor[cond_1 | cond_2] = adj_close.diff()
elif factor_id == '011':
vwap = value / adj_volume
temp1 = (vwap - adj_close).rolling(window=3).max().rank(aixs=1, pct=True)
temp2 = (vwap - adj_close).rolling(window=3).min().rank(axis=1, pct=True)
temp3 = adj_volume.diff(3).rank(axis=1, pct=True)
factor = (temp1 + temp2) * temp3
factor[rolling_stop(stop, 3)] = np.nan
elif factor_id == '012':
factor = -1 * np.sign(adj_volume.diff()) * adj_close.diff()
factor[stop.notnull()] = np.nan
elif factor_id == '013':
close_rank = adj_close.rank(axis=1, pct=True)
volume_rank = adj_volume.rank(axis=1, pct=True)
factor = -1 * (close_rank.rolling(window=5).cov(volume_rank)).rank(axis=1, pct=True)
factor[rolling_stop(stop, 5)] = np.nan
elif factor_id == '014':
temp1 = adj_OPEN.rolling(window=10).corr(adj_volume)
temp2 = returns.diff(3).rank(axis=1, pct=True)
factor = -1 * temp2 * temp1
factor[rolling_stop(stop, 10)] = np.nan
elif factor_id == '015':
high_rank = adj_high.rank(axis=1, pct=True)
volume_rank = adj_volume.rank(axis=1, pct=True)
temp1 = high_rank.rolling(window=3).corr(volume_rank)
factor = -1 * temp1.rank(axis=1, pct=True).rolling(window=3).sum()
factor[rolling_stop(stop, 3)] = np.nan
elif factor_id == '016':
high_rank = adj_high.rank(axis=1, pct=True)
volume_rank = adj_volume.rank(axis=1, pct=True)
factor = -1 * high_rank.rolling(window=5).cov(volume_rank)
factor[rolling_stop(stop, 5)] = np.nan
elif factor_id == '017':
temp1 = rolling_rank(adj_close, 10).rank(axis=1, pct=True)
temp2 = adj_close.diff(1).diff(1).rank(axis=1, pct=True)
temp3 = rolling_rank(adj_volume / adj_volume.rolling(window=20).mean(), 5).rank(axis=1, pct=True)
factor = -1 * temp1 * temp2 * temp3
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '018':
temp1 = adj_close.rolling(window=10).corr(adj_OPEN).replace([-np.inf, np.inf], np.nan)
temp2 = np.abs(adj_close - adj_OPEN).rolling(window=5).std()
factor = -1 * (temp2 + temp1 + adj_close - adj_OPEN).rank(axis=1, pct=True)
factor[rolling_stop(stop, 10)] = np.nan
elif factor_id == '019':
factor = -1 * np.sign(adj_close.diff(7)) * (1 + returns.rolling(window=250).sum())
factor[rolling_stop(stop, 8)] = np.nan
elif factor_id == '020':
temp1 = (adj_OPEN - adj_high.diff(1)).rank(axis=1, pct=True)
temp2 = (adj_OPEN - adj_close.diff(1)).rank(axis=1, pct=True)
temp3 = (adj_OPEN - adj_low.diff(1)).rank(axis=1, pct=True)
factor = -1 * temp1 * temp2 * temp3
factor[rolling_stop(stop, 2)] = np.nan
elif factor_id == '021':
cond_1 = adj_close.rolling(window=8).mean() + adj_close.rolling(window=8).std() < adj_close.rolling(window=2).mean()
cond_2 = adj_close.rolling(window=8).mean() - adj_close.rolling(window=8).std() > adj_close.rolling(window=2).mean()
cond_3 = adj_volume / adj_volume.rolling(window=20).mean() >= 1
cond_4 = adj_volume / adj_volume.rolling(window=20).mean() < 1
factor = pd.DataFrame(np.nan, index=adj_close.index, columns=adj_close.columns)
factor[cond_1] = -1
factor[cond_2] = 1
factor[np.logical_and(np.logical_not(np.logical_or(cond_1, cond_2)), cond_3)] = 1
factor[np.logical_and(np.logical_not(np.logical_or(cond_1, cond_2)), cond_4)] = -1
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '022':
part_1 = adj_high.rolling(window=5).corr(adj_volume).diff(5)
part_2 = adj_close.rolling(window=20).std().rank(axis=1, pct=True)
factor = -1 * part_1 * part_2
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '023':
factor = pd.DataFrame(np.nan, index=adj_high.index, columns=adj_high.columns)
factor[adj_high > adj_high.rolling(window=20).mean()] = -1 * adj_high.diff(2)
factor[adj_high <= adj_high.rolling(window=20).mean()] = 0
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '024':
cond_1 = adj_close.rolling(window=100).mean().diff(100) / adj_close.shift(100) <= 0.05
factor = -1 * adj_close.diff(3)
factor[cond_1] = -1 * (adj_close - adj_close.rolling(window=100).min())
factor[rolling_stop(stop, 3)] = np.nan
elif factor_id == '025':
part_1 = -1 * returns * adj_volume.rolling(window=20).mean()
part_2 = (value / adj_volume) * (adj_high - adj_close)
factor = (part_1 * part_2).rank(axis=1, pct=True)
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '026':
volume_rank = rolling_rank(adj_volume, 5)
high_rank = rolling_rank(adj_high, 5)
factor = -1 * volume_rank.rolling(window=5).corr(high_rank).rolling(window=3).max()
elif factor_id == '027':
factor = pd.DataFrame(np.nan, index=volume.index, columns=volume.columns)
volume_rank = adj_volume.rank(axis=1, pct=True)
vwap_rank = (value / adj_volume).rank(axis=1, pct=True)
corr_ = volume_rank.rolling(window=6).corr(vwap_rank)
corr_rank = corr_.rolling(window=2).mean().rank(axis=1, pct=True)
cond_1 = corr_rank > 0.5
cond_2 = corr_rank <= 0.5
factor[cond_1] = -1
factor[cond_2] = 1
factor[rolling_stop(stop, 6)] = np.nan
elif factor_id == '028':
part_1 = adj_volume.rolling(window=20).mean().rolling(window=5).corr(adj_low)
part_2 = (adj_high + adj_low) / 2 - adj_close
factor = part_1 + part_2
factor = (factor.T / factor.sum(axis=1)).T
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '029':
temp1 = rolling_rank(-1 * returns.shift(6), 5)
close_rank = (-1 * (adj_close - 1).diff(5).rank(axis=1, pct=True)).rank(axis=1, pct=True)
temp2 = np.log(close_rank.rolling(window=2).min())
temp3 = (temp2.T / temp2.sum(axis=1)).T.rank(axis=1, pct=True)
factor = temp3.rolling(window=5).min() + temp1
factor[rolling_stop(stop, 6)] = np.nan
elif factor_id == '030':
sign_1 = np.sign(adj_close.diff())
sign_2 = np.sign(adj_close.diff().shift())
sign_3 = np.sign(adj_close.diff().shift(2))
sign_rank = (sign_1 + sign_2 + sign_3)
factor = (1 - sign_rank) * adj_volume.rolling(window=5).sum() / adj_volume.rolling(window=20).sum()
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '031':
close_rank_1 = adj_close.diff(10).rank(axis=1, pct=True)
decay_linear_rank = decay_linear(-1 * close_rank_1, 10).rank(axis=1, pct=True)
close_rank_2 = (-1 * adj_close.diff(3)).rank(axis=1, pct=True)
corr_ = adj_volume.rolling(window=20).mean().rolling(window=12).corr(adj_low)
corr_sign = np.sign((corr_.T / corr_.summ(axis=1)).T)
factor = decay_linear_rank + close_rank_2 + corr_sign
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '032':
temp1 = adj_close.rolling(window=7).mean() - adj_close
part_1 = (temp1.T / temp.sum(axis=1)).T
vwap = value / adj_volume
temp2 = vwap.rolling(window=230).corr(adj_close.shift(5))
part_2 = (temp2.T / temp2.sum(axis=1)).T
factor = part_1 + 20 * part_2
factor[rolling_stop(stop, 7)] = np.nan
elif factor_id == '033':
factor = (OPEN / close - 1).rank(axis=1, pct=True)
factor[stop.notnull()] = np.nan
elif factor_id == '034':
temp1 = returns.rolling(window=2).std() / returns.rolling(window=5).std()
close_rank = adj_close.diff().rank(axis=1, pct=True)
factor = (1 - temp1.rank(axis=1, pct=True) + 1 - close_rank).rank(axis=1, pct=True)
factor[rolling_stop(stop, 5)] = np.nan
elif factor_id == '035':
volume_rank = rolling_rank(adj_volume, 32)
xx_rank = rolling_rank(adj_close + adj_high - adj_low, 16)
returns_rank = rolling_rank(returns, 32)
factor = volume_rank * (1- xx_rank) * (1 - returns_rank)
factor[rolling_stop(stop, 32)] = np.nan
elif factor_id == '036':
part_1 = (adj_close - adj_OPEN).rolling(window=15).corr(adj_volume.shift(1)).rank(axis=1, pct=True)
part_2 = (adj_OPEN - adj_close).rank(axis=1, pct=True)
part_3 = rolling_rank(-1 * returns.shift(6), 5).rank(axis=1, pct=True)
part_4 = (value / adj_volume).rolling(window=6).corr(adj_volume.rolling(window=20).mean()).rank(axis=1, pct=True)
part_5 = ((adj_close.rolling(window=200).mean() - adj_OPEN) * (adj_close - adj_OPEN)).rank(axis=1, pct=True)
factor = 2.21 * part_1 + 0.7 * part_2 + 0.73 * part_3 + part_4 + 0.6 * part_5
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '037':
corr_ = (adj_OPEN - adj_close).shift().rolling(window=200).corr(adj_close)
factor = corr_.rank(axis=1, pct=True) + (adj_OPEN - adj_close).rank(axis=1, pct=True)
factor[stop.notnull()] = np.nan
elif factor_id == '038':
part_1 = rolling_rank(adj_close, 10).rank(axis=1, pct=True)
part_2 = (close / OPEN).rank(axis=1, pct=True)
factor = -1 * part_1 * part_2
factor[rolling_stop(stop, 10)] = np.nan
elif factor_id == '039':
temp1 = adj_volume / adj_volume.rolling(window=20).mean()
decay_linear_rank = decay_linear(temp1, 9).rank(axis=1, pct=True)
part_1 = (adj_close.diff(7) * (1 - decay_linear_rank)).rank(axis=1, pct=True)
part_2 = returns.rolling(window=250).sum().rank(axis=1, pct=True)
factor = -1 * part_1 * (1 + part_2)
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '040':
factor = -1 * adj_high.rolling(window=10).std().rank(axis=1, pct=True) * adj_high.rolling(window=10).corr(adj_volume)
factor[rolling_stop(stop, 10)] = np.nan
elif factor_id == '041':
factor = ((high * low) ** 0.5 - (value / volume) * 10)
factor[stop.notnull()] = np.nan
elif factor_id == '042':
vwap = value / volume
factor = (vwap - close).rank(axis=1, pct=True) / (vwap + close).rank(axis=1, pct=True)
factor[stop.notnull()] = np.nan
elif factor_id == '043':
part_1 = rolling_rank(adj_volume / adj_volume.rolling(window=20).mean(), 20)
part_2 = rolling_rank(-1 * adj_close.diff(7), 8)
factor = part_1 * part_2
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '044':
factor = -1 * adj_high.rolling(window=5).corr(adj_volume.rank(axis=1, pct=True))
factor[rolling_stop(stop, 5)] = np.nan
elif factor_id == '045':
part_1 = adj_close.shift(5).rolling(window=20).mean().rank(axis=1, pct=True)
part_2 = adj_close.rolling(window=2).corr(adj_volume)
temp1 = adj_close.rolling(window=5).sum()
temp2 = adj_close.rolling(window=20).sum()
part_3 = temp1.rolling(window=2).corr(temp2).rank(axis=1, pct=True)
factor = -1 * part_1 * part_2 * part_3
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '046':
factor = -1 * adj_close.diff(1)
temp1 = (adj_close.shift(20) - adj_close.shift(10)) / 10
temp2 = (adj_close.shift(10) - adj_close) / 10
cond_1 = temp1 - temp2 > 0.25
cond_2 = temp1 - temp2 < 0
factor[cond_2] = 1
factor[cond_1] = -1
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '047':
part_1 = (1 / adj_close).rank(axis=1, pct=True) * adj_volume / adj_volume.rolling(window=20).mean()
part_2 = adj_high * (adj_high - adj_close).rank(axis=1, pct=True) / adj_high.rolling(window=5).mean()
vwap = value / adj_volume
part_3 = vwap.diff(5).rank(axis=1, pct=True)
factor = part_1 * part_2 * part_3
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '049':
factor = -1 * adj_close.diff()
temp1 = (adj_close.shift(20) - adj_close.shift(10)) / 10
temp2 = (adj_close.shift(10) - adj_close) / 10
factor[temp1 - temp2 < 0.1] = 1
factor[rolling_stop(stop, 20)] = np.nan
elif factor_id == '050':
volume_rank = adj_volume.rank(axis=1, pct=True)
vwap_rank = (value / adj_volume).rank(axis=1, pct=True)
corr_ = volume_rank.rolling(window=5).corr(vwap_rank)
factor = -1 * rolling_rank(corr_.rank(axis=1, pct=True), 5)
factor[rolling_stop(stop, 5)] = np.nan
elif factor_id == '055':
numerator = adj_close - adj_low.rolling(window=12).min()
denominator = adj_high.rolling(window=12).max() - adj_low.rolling(window=12).min()
fraction = numerator / denominator
fraction[rolling_stop(stop, 12)] = np.nan
fraction_rank = fraction.rank(axis=1, pct=True)
volume_rank = volume.replace(0, np.nan).rank(axis=1, pct=True)
factor = pd.DataFrame()
for t in fraction_rank.index:
day_factor = -1 * pearson(fraction_rank[:t][-6:],
volume_rank[:t][-6:])
day_factor.name = t
factor[t] = day_factor
factor = factor.T
elif factor_id == '101':
factor = (close - OPEN) / ((high - low) + 0.001)
factor[stop.notnull()] = np.nan
elif factor_id == 'vol':
returns = adj_close.pct_change()
factor = pd.DataFrame()
for t in returns.index:
not_stop = stop[:t][-21:].isnull().all(axis=0)
vol = adj_close[:t][-21:].pct_change()[1:].std(skipna=False)
vol = pd.Series(np.where(not_stop, vol, np.nan), index=not_stop.index)
vol.index.name = t
factor[t] = vol
factor = factor.T
elif factor_id == 'PeterLynch':
fcf[fcf < 0] = np.nan
asset_debt[asset_debt < 0] = np.nan
factor = (close / fcf).rank(axis=1, pct=True) * asset_debt.rank(axis=1, pct=True)
else:
print 'factor id is wrong'
# 将涨跌停股票的因子设为na
if no_zdt:
increase_stop = np.round(close * 1.1, 2).shift(1)
decrease_stop = np.round(close * 0.9, 2).shift(1)
bool_temp = np.logical_or(close == increase_stop, decrease_stop == close)
factor = np.where(bool_temp, np.nan, factor)
factor = pd.DataFrame(factor, columns=close.columns, index=close.index)
# 将st股票的因子值设为na
if no_st:
factor[st.notnull()] = np.nan
# 将st股票(上市小于63天)的因子设为na
if no_new:
factor[rolling_new(close, 63)] = np.nan
print '计算完成\n保存因子'
save_factor(factor, factor_id, no_zdt)
return factor
def factor_summary(factor, period=1):
percentiles = np.arange(0.1, 1, 0.1)
summary = pd.DataFrame()
for i in range(0, len(factor.index), period):
t = factor.index[i]
summary[t] = factor.ix[t].dropna().describe(percentiles)
return summary.T
def ic(factor, return_mode, period, data, by_day=False):
close = data['close']
OPEN = data['OPEN']
price_adj_f = data['price_adj_f']
adj_close = close * price_adj_f
adj_OPEN = OPEN * price_adj_f
if return_mode == 'close-close':
returns = adj_close.pct_change(period).shift(-period).stack()
elif return_mode == 'close-open':
returns = (adj_close.shift(-(period-1)) / adj_OPEN - 1).shift(-period).stack()
elif return_mode == 'open-open':
returns = adj_OPEN.pct_change(period).shift(-(period + 1)).stack()
else:
print 'mode must be \'close-close\', \'close-open\', \'open-open\''
returns.name = 'returns'
factor = factor.stack()
factor.name = 'factor'
temp = pd.concat([returns, factor], axis=1).dropna(axis=0, how='any')
if by_day:
ic_list = []
days = temp.index.levels[0]
for t in days:
ic_list.append(temp.ix[t].corr().iloc[0][1])
ic_series = pd.Series(ic_list, index=days)
return ic_series
else:
return temp.corr().iloc[0][1]
def group_analysis(factor, data, return_mode, period=1, bins=10, cut_mode='quantile'):
close = data['close']
OPEN = data['OPEN']
price_adj_f = data['price_adj_f']
adj_close = close * price_adj_f
adj_OPEN = OPEN * price_adj_f
if return_mode == 'close-close':
returns = adj_close.pct_change()
# elif return_mode == 'close-open':
# returns = (adj_close.shift / adj_OPEN - 1)
elif return_mode == 'open-open':
returns = adj_OPEN.pct_change()
else:
print 'mode must be \'close-close\', \'close-open\', \'open-open\''
days = len(factor.index)
group_mean = pd.DataFrame()
group_return = pd.DataFrame()
stock_num = pd.DataFrame()
for i in range(0, days, period):
t = factor.index[i]
temp = factor.ix[t].dropna()
if cut_mode == 'quantile':
temp.sort_values(ascending=True, inplace=True)
temp[:] = range(len(temp))
# 根据实际数值大小分组,可能某一个数值的股票数量太多,两个bin的边界相同
# 这里把因子排序,并用一个从1开始的序列替代原数值,在分组较多时,可能不准确
groups = pd.qcut(temp, bins, labels=False)
elif cut_mode == 'interval':
groups = pd.cut(temp, bins, labels=False)
group_mean[t] = factor.ix[t].dropna().groupby(groups).mean()
stock_num[t] = factor.ix[t].dropna().groupby(groups).count()
if return_mode == 'close-close':
period_returns = returns.ix[t:].ix[1: period+1].groupby(groups, axis=1).mean()
elif return_mode == 'open-open':
period_returns = returns.ix[t:].ix[2: period+2].groupby(groups, axis=1).mean()
group_return = pd.concat([group_return, period_returns])
a_return = returns.mean(axis=1)
a_mean = factor.mean(axis=1)
# group_mean.index = group_mean.index + 1
# group_return.index = group_return.index + 1
group_mean.index.name = 'Group'
group_mean = group_mean.T
group_mean['Factor Average'] = a_mean
group_return.columns.name = 'Group'
group_return['Simple Average'] = a_return
stock_num.index.name = 'Group'
stock_num = stock_num.T
return {'group_mean': group_mean, 'group_return': group_return, 'stock_num': stock_num}
def _analysis(factor, data, return_mode, stock_number, ascending=True, period=1):
close = data['close']
OPEN = data['OPEN']
price_adj_f = data['price_adj_f']
adj_close = close * price_adj_f
adj_OPEN = OPEN * price_adj_f
if return_mode == 'close-close':
returns = adj_close.pct_change(period).shift(-period)
elif return_mode == 'close-open':
returns = (adj_close.shift(-(period-1)) / adj_OPEN - 1).shift(-period)
elif return_mode == 'open-open':
returns = adj_OPEN.pct_change(period).shift(-(period + 1))
else:
print 'mode must be \'close-close\', \'close-open\', \'open-open\''
days = len(factor.index)
_mean = []
_return = []
_t = []
stocks = pd.DataFrame()
factors = pd.DataFrame()
for i in range(0, days, period):
t = factor.index[i]
_t.append(t)
temp = factor.ix[t].dropna()
temp.sort_values(ascending=ascending, inplace=True)
stock_to_hold = temp[:stock_number].index
stocks[t] = stock_to_hold
factors[t] = temp[stock_to_hold]
_return.append(returns.ix[t][stock_to_hold].mean())
_mean.append(temp[stock_to_hold].mean())
_mean = pd.Series(_mean, index=_t, name='factor_mean')
_return = pd.Series(_return, index=_t, name='mean_return')
return {'factor_mean': _mean, 'mean_return': _return,
'stocks': stocks.T, 'factors': factors.T}
high = import_data('LZ_GPA_QUOTE_THIGH')
low = import_data('LZ_GPA_QUOTE_TLOW')
close = import_data('LZ_GPA_QUOTE_TCLOSE')
OPEN = import_data('LZ_GPA_QUOTE_TOPEN')
value = import_data('LZ_GPA_QUOTE_TVALUE')
volume = import_data('LZ_GPA_QUOTE_TVOLUME')
stop = import_data('LZ_GPA_SLCIND_STOP_FLAG')
price_adj_f = import_data('LZ_GPA_CMFTR_CUM_FACTOR')
st = import_data('LZ_GPA_SLCIND_ST_FLAG')
fcf = import_data('LZ_GPA_FIN_IND_FCFFPS')
asset_debt = import_data('LZ_GPA_FIN_IND_DEBTTOASSETS')
data = {'high': high,
'low': low,
'close': close,
'OPEN': OPEN,
'value': value,
'volume': volume,
'stop': stop,
'st': st,
'fcf': fcf,
'asset_debt': asset_debt,
'price_adj_f': price_adj_f}
factor = factor_cal(data, '028', no_zdt=False, no_st=False, no_new=False)
factor_006 = factor_cal(data, '006', no_zdt=False)
factors = pd.concat([factor.stack(), factor_006.stack()], axis=1)
days = factors.index.levels[0]
for d in days:
print factors.ix[d].corr().iloc[0][1]
factor_ = factor_cal()
factor_.to_csv('F:\Factors\Volatility/LowVol_nostop_adj.csv')
factor_ = factor_.rolling(window=12).mean()
temp_ = factor_.stack()
temp_.plot(kind='hist', bins=20)
temp_[temp_>0.1]
summary = factor_summary(factor_['2013-01-01':].dropna(axis=0, how='all'))
summary.ix[:, ['mean', 'std', '10%', '90%']].plot(figsize=(10, 10))
ic_series = ic(factor_, 'close-close', 20, data, by_day=True)
title = '60 days moving average of IC (absolute value)'
np.abs(ic_series).rolling(window=60).mean().plot(figsize=(14, 7), title=title)
temp = np.abs(factor_.T - factor_.mean(axis=1)).T
factor_name = 'alpha#101_nozdt_abs_1D'
temp.index.name = factor_name
temp.to_csv('F:\Strategies\World_Quant_Alphas\#%s\%s.csv' %
('101', factor_name))
stt = factor_['2013-01-07':].dropna(axis=0, how='all')
stt = np.abs(stt.T - stt.mean(axis=1)).T
stt.mean(axis=1).mean()
a = group_analysis(stt, data, 'close-close', period=20, bins=10, cut_mode='quantile')
a['group_return'].mean().plot(kind='bar')
a['group_mean'].mean().plot()
(a['group_return'] + 1).cumprod().plot(figsize=(14, 7))
a['group_mean']['Factor Average'].plot(figsize=(14, 7))
a['group_return'].columns.name
a = _analysis(stt, data, 'close-close', stock_number=50, ascending=True, period=10)
a['mean_return'].mean()
a['factor_mean'].min()
(a['mean_return'] + 1).cumprod().plot(figsize=(14, 7))
a['stocks'].to_csv('F:\Strategies\World_Quant_Alphas/10_stocks.csv')
a['factors'].head()