This commit is contained in:
jack
2025-11-25 09:45:49 +08:00
parent ad98c97949
commit 41ef816a81
34 changed files with 1518 additions and 1 deletions
@@ -0,0 +1,619 @@
from scipy.stats import rankdata
from dateutil import parser
import numpy as np
import numpy.linalg as la
import pandas as pd
from datetime import datetime
import scipy.stats as stats
import matplotlib.pyplot as plt
from WindPy import * # 万矿数据接口
w.start()
## 内置函数
# 行业中性化
def neutral(data,ind):
stocks = list(data.index)
data_ = pd.DataFrame(ind.Data,index=['INDUSTRY'],columns=ind.Codes).T
data_med = pd.get_dummies(data_,columns=['INDUSTRY'])
X= np.array(data_med)
y = data.values
beta_ols = la.inv(X.T.dot(X)).dot(X.T).dot(y)
residual = y - X.dot(beta_ols)
return residual
def IndNeutralize(vwap,ind):
vwap_ = vwap.fillna(value = 0)
ind = w.wss(stocks, "industry_citic","unit=1;tradeDate="+ind.Times[0].strftime("%Y%m%d")+";industryType=1")
for i in range(len(vwap_)):
vwap_.iloc[i] = neutral(vwap_.iloc[i],ind)
return vwap_
# 移动求和
def ts_sum(df, window):
return df.rolling(window).sum()
# 移动平均
def sma(df, window):
return df.rolling(window).mean()
# 移动标准差
def stddev(df, window):
return df.rolling(window).std()
# 移动相关系数
def correlation(x, y, window):
return x.rolling(window).corr(y)
# 移动协方差
def covariance(x, y, window):
return x.rolling(window).cov(y)
# 在过去d天的时序排名
def rolling_rank(na):
return rankdata(na)[-1]
def ts_rank(df,window):
return df.rolling(window).apply(rolling_rank)
# 过去d天的时序乘积
def rolling_prod(na):
return np.prod(na)
def product(df, window):
return df.rolling(window).apply(rolling_prod)
# 过去d天最小值
def ts_min(df, window):
return df.rolling(window).min()
# 过去d天最大值
def ts_max(df, window):
return df.rolling(window).max()
# 当天取值减去d天前的值
def delta(df, period):
return df.diff(period)
# d天前的值,滞后值
def delay(df, period):
return df.shift(period)
# 截面数据排序,输出boolean值
def rank(df):
return df.rank(pct=True,axis=1)
# 缩放时间序列,使其和为1
def scale(df, k=1):
return df.mul(k).div(np.abs(df).sum())
# 过去d天最大值的位置
def ts_argmax(df, window):
return df.rolling(window).apply(np.argmax) + 1
# 过去d天最小值的位置
def ts_argmin(df, window):
return df.rolling(window).apply(np.argmin) + 1
# 线性衰减的移动平均加权
def decay_linear(df, period):
if df.isnull().values.any():
df.fillna(method='ffill', inplace=True)
df.fillna(method='bfill', inplace=True)
df.fillna(value=0, inplace=True)
na_lwma = np.zeros_like(df) # 生成与df大小相同的零数组
na_lwma[:period, :] = df.iloc[:period, :] # 赋前period项的值
na_series = df.as_matrix()
# 计算加权系数
divisor = period * (period + 1) / 2
y = (np.arange(period) + 1) * 1.0 / divisor
# 从第period项开始计算数值
for row in range(period - 1, df.shape[0]):
x = na_series[row - period + 1: row + 1, :]
na_lwma[row, :] = (np.dot(x.T, y))
return pd.DataFrame(na_lwma,index = df.index,columns = df.columns)
## 因子函数
def alpha1(close,returns):
x = close
x[returns < 0] = stddev(returns,20)
alpha = rank(ts_argmax(x ** 2, 5))-0.5
return alpha.fillna(value = 0)
def alpha2(Open,close,volume):
r1 = rank(delta(np.log(volume), 2))
r2 = rank((close - Open) / Open)
alpha = -1 * correlation(r1,r2,6)
return alpha.fillna(value = 0)
def alpha3(Open,volume):
r1 = rank(Open)
r2 = rank(volume)
alpha = -1 * correlation(r1,r2,10)
return alpha.replace([-np.inf, np.inf], 0).fillna(value = 0)
def alpha4(low):
r = rank(low)
alpha = -1 * ts_rank(r,9)
return alpha.fillna(value = 0)
def alpha5(Open,vwap,close):
alpha = (rank((Open - (ts_sum(vwap, 10) / 10))) * (-1 * abs(rank((close - vwap)))))
return alpha.fillna(value = 0)
def alpha6(Open, volume):
alpha = -1 * correlation(Open, volume, 10)
return alpha.replace([-np.inf, np.inf], 0).fillna(value = 0)
def alpha7(volume,close):
adv20 = sma(volume, 20)
alpha = -1 * ts_rank(abs(delta(close, 7)), 60) * np.sign(delta(close, 7))
alpha[adv20 >= volume] = -1
return alpha.fillna(value = 0)
def alpha8(Open,returns):
x1 = (ts_sum(Open, 5) * ts_sum(returns, 5))
x2 = delay((ts_sum(Open, 5) * ts_sum(returns, 5)), 10)
alpha = -1 * rank(x1-x2)
return alpha.fillna(value = 0)
def alpha9(close):
delta_close = delta(close, 1)
x1 = ts_min(delta_close, 5) > 0
x2 = ts_max(delta_close, 5) < 0
alpha = -1 * delta_close
alpha[x1 | x2] = delta_close
return alpha.fillna(value = 0)
def alpha10(close):
delta_close = delta(close, 1)
x1 = ts_min(delta_close, 4) > 0
x2 = ts_max(delta_close, 4) < 0
x = -1 * delta_close
x[x1 | x2] = delta_close
alpha = rank(x)
return alpha.fillna(value = 0)
def alpha11(vwap,close,volume):
x1 = rank(ts_max((vwap - close), 3))
x2 = rank(ts_min((vwap - close), 3))
x3 = rank(delta(volume, 3))
alpha = (x1 + x2) * x3
return alpha.fillna(value = 0)
def alpha12(volume,close):
alpha = np.sign(delta(volume, 1)) * (-1 * delta(close, 1))
return alpha.fillna(value = 0)
def alpha13(volume,close):
alpha = -1 * rank(covariance(rank(close), rank(volume), 5))
return alpha.fillna(value = 0)
def alpha14(Open,volume,returns):
x1 = correlation(Open, volume, 10).replace([-np.inf, np.inf], 0).fillna(value=0)
x2 = -1 * rank(delta(returns, 3))
alpha = x1 * x2
return alpha.fillna(value = 0)
def alpha15(high,volume):
x1 = correlation(rank(high), rank(volume), 3).replace([-np.inf, np.inf], 0).fillna(value=0)
alpha = -1 * ts_sum(rank(x1), 3)
return alpha.fillna(value = 0)
def alpha16(high,volume):
alpha = -1 * rank(covariance(rank(high), rank(volume), 5))
return alpha.fillna(value = 0)
def alpha17(volume,close):
adv20 = sma(volume, 20)
x1 = rank(ts_rank(close, 10))
x2 = rank(delta(delta(close, 1), 1))
x3 = rank(ts_rank((volume / adv20), 5))
alpha = -1 * (x1 * x2 * x3)
return alpha.fillna(value = 0)
def alpha18(close,Open):
x = correlation(close, Open, 10).replace([-np.inf, np.inf], 0).fillna(value=0)
alpha = -1 * (rank((stddev(abs((close - Open)), 5) + (close - Open)) + x))
return alpha.fillna(value = 0)
def alpha19(close,returns):
x1 = (-1 * np.sign((close - delay(close, 7)) + delta(close, 7)))
x2 = (1 + rank(1 + ts_sum(returns, 250)))
alpha = x1 * x2
return alpha.fillna(value = 0)
def alpha20(Open,high,close,low):
alpha = -1 * (rank(Open - delay(high, 1)) * rank(Open - delay(close, 1)) * rank(Open - delay(low, 1)))
return alpha.fillna(value = 0)
def alpha21(volume,close):
x1 = sma(close, 8) + stddev(close, 8) < sma(close, 2)
x2 = sma(close, 8) - stddev(close, 8) > sma(close, 2)
x3 = sma(volume, 20) / volume < 1
alpha = pd.DataFrame(np.ones_like(close), index = close.index,columns = close.columns)
alpha[x1 | x3] = -1 * alpha
return alpha
def alpha22(high,volume,close):
x = correlation(high, volume, 5).replace([-np.inf, np.inf], 0).fillna(value=0)
alpha = -1 * delta(x, 5) * rank(stddev(close, 20))
return alpha.fillna(value = 0)
def alpha23(high,close):
x = sma(high, 20) < high
alpha = pd.DataFrame(np.zeros_like(close),index = close.index,columns = close.columns)
alpha[x] = -1 * delta(high, 2).fillna(value = 0)
return alpha
def alpha24(close):
x = delta(sma(close, 100), 100) / delay(close, 100) <= 0.05
alpha = -1 * delta(close, 3)
alpha[x] = -1 * (close - ts_min(close, 100))
return alpha.fillna(value = 0)
def alpha25(volume,returns,vwap,high,close):
adv20 = sma(volume, 20)
alpha = rank((((-1 * returns) * adv20) * vwap) * (high - close))
return alpha.fillna(value = 0)
def alpha26(volume,high):
x = correlation(ts_rank(volume, 5), ts_rank(high, 5), 5).replace([-np.inf, np.inf], 0).fillna(value=0)
alpha = -1 * ts_max(x, 3)
return alpha.fillna(value = 0)
def alpha27(volume,vwap):
alpha = rank((sma(correlation(rank(volume), rank(vwap), 6), 2) / 2.0))
alpha[alpha > 0.5] = -1
alpha[alpha <= 0.5] = 1
return alpha.fillna(value = 0)
def alpha28(volume,high,low,close):
adv20 = sma(volume, 20)
x = correlation(adv20, low, 5).replace([-np.inf, np.inf], 0).fillna(value=0)
alpha = scale(((x + ((high + low) / 2)) - close))
return alpha.fillna(value = 0)
def alpha29(close,returns):
x1 = ts_min(rank(rank(scale(np.log(ts_sum(rank(rank(-1 * rank(delta((close - 1), 5)))), 2))))), 5)
x2 = ts_rank(delay((-1 * returns), 6), 5)
alpha = x1 + x2
return alpha.fillna(value = 0)
def alpha30(close,volume):
delta_close = delta(close, 1)
x = np.sign(delta_close) + np.sign(delay(delta_close, 1)) + np.sign(delay(delta_close, 2))
alpha = ((1.0 - rank(x)) * ts_sum(volume, 5)) / ts_sum(volume, 20)
return alpha.fillna(value = 0)
def alpha31(close,low,volume):
adv20 = sma(volume,20)
x1 = rank(rank(rank(decay_linear((-1 * rank(rank(delta(close, 10)))), 10))))
x2 = rank((-1 * delta(close, 3)))
x3 = np.sign(scale(correlation(adv20, low, 12).replace([-np.inf, np.inf], 0).fillna(value=0)))
alpha = x1 + x2 + x3
return alpha.fillna(value = 0)
def alpha32(close,vwap):
x = correlation(vwap, delay(close, 5),230).replace([-np.inf, np.inf], 0).fillna(value=0)
alpha = scale(((sma(close, 7)) - close)) + 20 * scale(x)
return alpha.fillna(value = 0)
def alpha33(Open,close):
alpha = rank(-1 + (Open / close))
return alpha
def alpha34(close,returns):
x = (stddev(returns, 2) / stddev(returns, 5)).fillna(value = 0)
alpha = rank(2 - rank(x) - rank(delta(close, 1)))
return alpha.fillna(value = 0)
def alpha35(volume,close,high,low,returns):
x1 = ts_rank(volume, 32)
x2 = 1 - ts_rank(close + high - low, 16)
x3 = 1 - ts_rank(returns, 32)
alpha = (x1 * x2 * x3).fillna(value = 0)
return alpha
def alpha36(Open,close,volume,returns,vwap):
adv20 = sma(volume, 20)
x1 = 2.21 * rank(correlation((close - Open), delay(volume, 1), 15))
x2 = 0.7 * rank((Open- close))
x3 = 0.73 * rank(ts_rank(delay((-1 * returns), 6), 5))
x4 = rank(abs(correlation(vwap,adv20, 6)))
x5 = 0.6 * rank((sma(close, 200) - Open) * (close - Open))
alpha = x1 + x2 + x3 + x4 + x5
return alpha.fillna(value = 0)
def alpha37(Open,close):
alpha = rank(correlation(delay(Open - close, 1), close, 200)) + rank(Open - close)
return alpha.fillna(value = 0)
def alpha38(close,Open):
x = (close / Open).replace([-np.inf, np.inf], 0).fillna(value=0)
alpha = -1 * rank(ts_rank(Open, 10)) * rank(x)
return alpha.fillna(value = 0)
def alpha39(volume,close,returns):
adv20 = sma(volume, 20)
x = -1 * rank(delta(close, 7)) * (1 - rank(decay_linear((volume / adv20), 9)))
alpha = x *(1 + rank(ts_sum(returns, 250)))
return alpha.fillna(value = 0)
def alpha40(high,volume):
alpha = -1 * rank(stddev(high, 10)) * correlation(high, volume, 10)
return alpha.fillna(value = 0)
def alpha41(high,low,vwap):
alpha = pow((high * low),0.5) - vwap
return alpha
def alpha42(vwap,close):
alpha = rank((vwap - close)) / rank((vwap + close))
return alpha
def alpha43(volume,close):
adv20 = sma(volume, 20)
alpha = ts_rank(volume / adv20, 20) * ts_rank((-1 * delta(close, 7)), 8)
return alpha.fillna(value = 0)
def alpha44(high,volume):
alpha = -1 *correlation(high, rank(volume), 5).replace([-np.inf, np.inf], 0).fillna(value=0)
return alpha
def alpha45(close,volume):
x = correlation(close, volume, 2).replace([-np.inf, np.inf], 0).fillna(value=0)
alpha = -1 * (rank(sma(delay(close, 5), 20)) * x * rank(correlation(ts_sum(close, 5), ts_sum(close, 20), 2)))
return alpha.fillna(value = 0)
def alpha46(close):
x = ((delay(close, 20) - delay(close, 10)) / 10) - ((delay(close, 10) - close) / 10)
alpha = (-1 * (close - delay(close, 1)))
alpha[x < 0] = 1
alpha[x > 0.25] = -1
return alpha.fillna(value = 0)
def alpha47(volume,close,high,vwap):
adv20 = sma(volume, 20)
alpha = ((rank((1 / close)) * volume) / adv20) * ((high * rank((high - close))) / sma(high, 5)) - rank((vwap - delay(vwap, 5)))
return alpha.fillna(value = 0)
def alpha49(close):
x = (((delay(close, 20) - delay(close, 10)) / 10) - ((delay(close, 10) - close) / 10))
alpha = (-1 * delta(close,1))
alpha[x < -0.1] = 1
return alpha.fillna(value = 0)
def alpha50(volume,vwap):
alpha = -1 * ts_max(rank(correlation(rank(volume), rank(vwap), 5)), 5)
return alpha.fillna(value = 0)
def alpha51(close):
inner = (((delay(close, 20) - delay(close, 10)) / 10) - ((delay(close, 10) - close) / 10))
alpha = (-1 * delta(close,1))
alpha[inner < -0.05] = 1
return alpha.fillna(value = 0)
def alpha52(returns,volume,low):
x = rank(((ts_sum(returns, 240) - ts_sum(returns, 20)) / 220))
alpha = -1 * delta(ts_min(low, 5), 5) * x * ts_rank(volume, 5)
return alpha.fillna(value = 0)
def alpha53(close,high,low):
alpha = -1 * delta((((close - low) - (high - close)) / (close - low).replace(0, 0.0001)), 9)
return alpha.fillna(value = 0)
def alpha54(Open,close,high,low):
x = (low - high).replace(0, -0.0001)
alpha = -1 * (low - close) * (Open ** 5) / (x * (close ** 5))
return alpha
def alpha55(high,low,close,volume):
x = (close - ts_min(low, 12)) / (ts_max(high, 12) - ts_min(low, 12)).replace(0, 0.0001)
alpha = -1 * correlation(rank(x), rank(volume), 6).replace([-np.inf, np.inf], 0).fillna(value=0)
return alpha
def alpha56(returns,cap):
alpha = 0 - (1 * (rank((sma(returns, 10) / sma(sma(returns, 2), 3))) * rank((returns * cap))))
return alpha.fillna(value = 0)
def alpha57(close,vwap):
alpha = 0 - 1 * ((close - vwap) / decay_linear(rank(ts_argmax(close, 30)), 2))
return alpha.fillna(value = 0)
def alpha60(close,high,low,volume):
x = ((close - low) - (high - close)) * volume / (high - low).replace(0, 0.0001)
alpha = - ((2 * scale(rank(x))) - scale(rank(ts_argmax(close, 10))))
return alpha.fillna(value = 0)
def alpha61(volume,vwap):
adv180 = sma(volume, 180)
alpha = rank((vwap - ts_min(vwap, 16))) < rank(correlation(vwap, adv180, 18))
return alpha
def alpha62(volume,high,low,Open,vwap):
adv20 = sma(volume, 20)
x1 = rank(correlation(vwap, ts_sum(adv20, 22), 10))
x2 = rank(((rank(Open) + rank(Open)) < (rank(((high + low) / 2)) + rank(high))))
alpha = x1 < x2
return alpha*-1
def alpha64(high,low,Open,volume,vwap):
adv120 = sma(volume, 120)
x1 = rank(correlation(ts_sum(((Open * 0.178404) + (low * (1 - 0.178404))), 13),ts_sum(adv120, 13), 17))
x2 = rank(delta(((((high + low) / 2) * 0.178404) + (vwap * (1 -0.178404))), 3.69741))
alpha = x1 < x2
return alpha*-1
def alpha65(volume,vwap,Open):
adv60 = sma(volume, 60)
x1 = rank(correlation(((Open * 0.00817205) + (vwap * (1 - 0.00817205))), ts_sum(adv60,9), 6))
x2 = rank((Open - ts_min(Open, 14)))
alpha = x1 < x2
return alpha*-1
def alpha66(vwap,low,Open,high):
x1 = rank(decay_linear(delta(vwap, 4), 7))
x2 = (((low* 0.96633) + (low * (1 - 0.96633))) - vwap) / (Open - ((high + low) / 2))
alpha = (x1 + ts_rank(decay_linear(x2, 11), 7)) * -1
return alpha.fillna(value = 0)
def alpha68(volume,high,close,low):
adv15 = sma(volume, 15)
x1 = ts_rank(correlation(rank(high), rank(adv15), 9), 14)
x2 = rank(delta(((close * 0.518371) + (low * (1 - 0.518371))), 1.06157))
alpha = x1 < x2
return alpha*-1
def alpha71(volume,close,low,Open,vwap):
adv180 = sma(volume, 180)
x1 = ts_rank(decay_linear(correlation(ts_rank(close, 3), ts_rank(adv180,12), 18), 4), 16)
x2 = ts_rank(decay_linear((rank(((low + Open) - (vwap + vwap))).pow(2)), 16), 4)
alpha = x1
alpha[x1 < x2] = x2
return alpha.fillna(value = 0)
def alpha72(volume,high,low,vwap):
adv40 = sma(volume, 40)
x1 = rank(decay_linear(correlation(((high + low) / 2), adv40, 9), 10))
x2 = rank(decay_linear(correlation(ts_rank(vwap, 4), ts_rank(volume, 19), 7), 3))
alpha = (x1 / x2.replace(0, 0.0001)).fillna(value = 0)
return alpha
def alpha73(vwap,Open,low):
x1 = rank(decay_linear(delta(vwap, 5), 3))
x2 = delta(((Open * 0.147155) + (low * (1 - 0.147155))), 2) / ((Open *0.147155) + (low * (1 - 0.147155)))
x3 = ts_rank(decay_linear((x2 * -1), 3), 17)
alpha = x1
alpha[x1 < x3] = x3
return -1 * alpha.fillna(value = 0)
def alpha74(volume,close,high,vwap):
adv30 = sma(volume, 30)
x1 = rank(correlation(close, ts_sum(adv30, 37), 15))
x2 = rank(correlation(rank(((high * 0.0261661) + (vwap * (1 - 0.0261661)))), rank(volume), 11))
alpha = x1 < x2
return alpha*-1
def alpha75(volume,vwap,low):
adv50 = sma(volume, 50)
alpha = rank(correlation(vwap, volume, 4)) < rank(correlation(rank(low), rank(adv50), 12))
return alpha
def alpha77(volume,high,low,vwap):
adv40 = sma(volume, 40)
x1 = rank(decay_linear(((((high + low) / 2) + high) - (vwap + high)), 20))
x2 = rank(decay_linear(correlation(((high + low) / 2), adv40, 3), 6))
alpha = x1
alpha[x1 > x2] = x2
return alpha.fillna(value = 0)
def alpha78(volume,low,vwap):
adv40 = sma(volume, 40)
x1 = rank(correlation(ts_sum(((low * 0.352233) + (vwap * (1 - 0.352233))), 20), ts_sum(adv40, 20),7))
x2 = rank(correlation(rank(vwap), rank(volume), 6))
alpha = x1.pow(x2)
return alpha.fillna(value = 0)
def alpha81(volume,vwap):
adv10 = sma(volume, 10)
x1 = rank(np.log(product(rank((rank(correlation(vwap, ts_sum(adv10, 50), 8)).pow(4))), 15)))
x2 = rank(correlation(rank(vwap), rank(volume), 5))
alpha = x1 < x2
return alpha*-1
def alpha83(high,low,close,volume):
x = rank(delay(((high - low) / (ts_sum(close, 5) / 5)), 2)) * rank(rank(volume))
alpha = x / (((high - low) / (ts_sum(close, 5) / 5)) / (vwap - close))
return alpha.fillna(value = 0)
def alpha84(vwap,close):
alpha = pow(ts_rank((vwap - ts_max(vwap, 15)), 21), delta(close,5))
return alpha.fillna(value = 0)
def alpha85(volume,high,close,low):
adv30 = sma(volume, 30)
x1 = rank(correlation(((high * 0.876703) + (close * (1 - 0.876703))), adv30,10))
alpha = x1.pow(rank(correlation(ts_rank(((high + low) / 2), 4), ts_rank(volume, 10), 7)))
return alpha.fillna(value = 0)
def alpha86(volume,close,Open,vwap):
adv20 = sma(volume, 20)
x1 = ts_rank(correlation(close, sma(adv20, 15), 6), 20)
x2 = rank(((Open+ close) - (vwap + Open)))
alpha = x1 < x2
return alpha*-1
def alpha88(volume,Open,low,high,close):
adv60 = sma(volume, 60)
x1 = rank(decay_linear(((rank(Open) + rank(low)) - (rank(high) + rank(close))),8))
x2 = ts_rank(decay_linear(correlation(ts_rank(close, 8), ts_rank(adv60,21), 8), 7), 3)
alpha = x1
alpha[x1 > x2] = x2
return alpha.fillna(value = 0)
def alpha92(volume,high,low,close,Open):
adv30 = sma(volume, 30)
x1 = ts_rank(decay_linear(((((high + low) / 2) + close) < (low + Open)), 15), 19)
x2 = ts_rank(decay_linear(correlation(rank(low), rank(adv30), 8), 7),7)
alpha = x1
alpha[x1 > x2] = x2
return alpha.fillna(value = 0)
def alpha94(volume,vwap):
adv60 = sma(volume, 60)
x = rank((vwap - ts_min(vwap, 12)))
alpha = x.pow(ts_rank(correlation(ts_rank(vwap,20), ts_rank(adv60, 4), 18), 3))* -1
return alpha.fillna(value = 0)
def alpha95(volume,high,low,Open):
adv40 = sma(volume, 40)
x = ts_rank((rank(correlation(sma(((high + low)/ 2), 19), sma(adv40, 19), 13)).pow(5)), 12)
alpha = rank((Open - ts_min(Open, 12))) < x
return alpha.fillna(value = 0)
def alpha96(volume,vwap,close):
adv60 = sma(volume, 60)
x1 = ts_rank(decay_linear(correlation(rank(vwap), rank(volume), 4),4), 8)
x2 = ts_rank(decay_linear(ts_argmax(correlation(ts_rank(close, 7),ts_rank(adv60, 4), 4), 13), 14), 13)
alpha = x1
alpha[x1 < x2] = x2
return alpha.fillna(value = 0)
def alpha98(volume,Open,vwap):
adv5 = sma(volume, 5)
adv15 = sma(volume, 15)
x1 = rank(decay_linear(correlation(vwap, sma(adv5, 26), 5), 7))
alpha = x1 - rank(decay_linear(ts_rank(ts_argmin(correlation(rank(Open), rank(adv15), 21), 9),7), 8))
return alpha.fillna(value = 0)
def alpha99(volume,high,low):
adv60 = sma(volume, 60)
x1 = rank(correlation(ts_sum(((high + low) / 2), 20), ts_sum(adv60,20), 9))
x2 = rank(correlation(low, volume, 6))
alpha = x1 < x2
return alpha*-1
def alpha101(close,Open,high,low):
alpha = (close - Open) / ((high - low) + 0.001)
return alpha
def alpha48(close,ind):
r1 = (correlation(delta(close, 1), delta(delay(close, 1), 1), 250) * delta(close, 1)) / close
r2 = ts_sum((pow((delta(close, 1) / delay(close, 1)),2)), 250)
alpha = IndNeutralize(r1, ind) / r2
return alpha.fillna(value = 0)
def alpha58(vwap,volume,ind):
x = IndNeutralize(vwap, ind)
alpha = -1 * ts_rank(decay_linear(correlation(x, volume, 4), 8), 6)
return alpha.fillna(value = 0)
def alpha59(vwap,volume,ind):
x = IndNeutralize(((vwap * 0.728317) + (vwap * (1 - 0.728317))), ind)
alpha = -1 * ts_rank(decay_linear(correlation(x, volume, 4), 16), 8)
return alpha.fillna(value = 0)
def alpha63(volume,close,vwap,Open,ind):
adv180 = sma(volume, 180).fillna(value = 0)
r1 = rank(decay_linear(delta(IndNeutralize(close, ind), 2), 8))
r2 = rank(decay_linear(correlation(((vwap * 0.318108) + (Open * (1 - 0.318108))), ts_sum(adv180, 37), 14), 12))
alpha = -1 * (r1 - r2)
return alpha.fillna(value = 0)
def alpha67(volume,vwap,high,ind):
adv20 = sma(volume, 20)
r = rank(correlation(IndNeutralize(vwap, ind), IndNeutralize(adv20, ind), 6))
alpha = pow(rank(high - ts_min(high, 2)),r) * -1
return alpha.fillna(value = 0)
def alpha69(volume,vwap,ind,close):
adv20 = sma(volume, 20)
r1 = rank(ts_max(delta(IndNeutralize(vwap, ind), 3), 5))
r2 = ts_rank(correlation(((close * 0.490655) + (vwap * (1 - 0.490655))), adv20, 5), 9)
alpha = pow(r1,r2) * -1
return alpha.fillna(value = 0)
def alpha70(close,ind,vwap):
adv50 = sma(volume, 50).fillna(value = 0)
r = ts_rank(correlation(IndNeutralize(close, ind), adv50, 18), 18)
alpha = pow(rank(delta(vwap, 1)),r) * -1
return alpha.fillna(value = 0)
def alpha76(volume,vwap,low,ind):
adv81 = sma(volume, 81).fillna(value = 0)
r1 = rank(decay_linear(delta(vwap, 1), 12))
r2 = ts_rank(decay_linear(ts_rank(correlation(IndNeutralize(low, ind), adv81, 8), 20), 17), 19)
alpha = r1
alpha[r1 < r2] = r2
return alpha.fillna(value = 0)
def alpha79(volume,close,Open,ind,vwap):
adv150 = sma(volume, 150).fillna(value = 0)
r1 = rank(delta(IndNeutralize(((close * 0.60733) + (Open * (1 - 0.60733))), ind), 1))
r2 = rank(correlation(ts_rank(vwap, 4), ts_rank(adv150, 9), 15))
alpha = (r1 < r2) * -1
return alpha.fillna(value = 0)
def alpha80(Open,high,ind):
adv10 = sma(volume, 10)
r1 = rank(np.sign(delta(IndNeutralize(((Open * 0.868128) + (high * (1 - 0.868128))), ind), 4)))
r2 = ts_rank(correlation(high, adv10, 5), 6)
alpha = pow(r1,r2) * -1
return alpha.fillna(value = 0)
def alpha82(Open,volume,ind):
r1 = rank(decay_linear(delta(Open, 1), 15))
r2 = ts_rank(decay_linear(correlation(IndNeutralize(volume, ind), ((Open * 0.634196) + (Open * (1 - 0.634196))), 17), 7), 13)
alpha = r1
alpha[r1 > r2] = r2
return -1 * alpha.fillna(value = 0)
def alpha87(volume,close,vwap):
adv81 = sma(volume, 81).fillna(value = 0)
r1 = rank(decay_linear(delta(((close * 0.369701) + (vwap * (1 - 0.369701))), 2), 3))
r2 = ts_rank(decay_linear(abs(correlation(IndNeutralize(adv81, ind), close, 13)), 5), 14)
alpha = r1
alpha[r1 < r2] = r2
return -1 * alpha.fillna(value = 0)
def alpha89(low,vwap,ind):
adv10 = sma(volume, 10)
r1 = ts_rank(decay_linear(correlation(((low * 0.967285) + (low * (1 - 0.967285))), adv10, 7), 6), 4)
r2 = ts_rank(decay_linear(delta(IndNeutralize(vwap, ind), 3), 10), 15)
alpha = r1 - r2
return alpha.fillna(value = 0)
def alpha90(volume,close,ind,low):
adv40 = sma(volume, 40).fillna(value = 0)
r1 = rank((close - ts_max(close, 5)))
r2 = ts_rank(correlation(IndNeutralize(adv40, ind), low, 5), 3)
alpha = pow(r1,r2) * -1
return alpha.fillna(value = 0)
def alpha91(close,ind,volume,vwap):
adv30 = sma(volume, 30)
r1 = ts_rank(decay_linear(decay_linear(correlation(IndNeutralize(close, ind), volume, 10), 16), 4), 5)
r2 = rank(decay_linear(correlation(vwap, adv30, 4), 3))
alpha = (r1 - r2) * -1
return alpha.fillna(value = 0)
def alpha93(vwap,ind,volume,close):
adv81 = sma(volume, 81).fillna(value = 0)
r1 = ts_rank(decay_linear(correlation(IndNeutralize(vwap, ind), adv81, 17), 20), 8)
r2 = rank(decay_linear(delta(((close * 0.524434) + (vwap * (1 - 0.524434))), 3), 16))
alpha = r1 / r2
return alpha.fillna(value = 0)
def alpha97(volume,low,vwap,ind):
adv60 = sma(volume, 60).fillna(value = 0)
r1 = rank(decay_linear(delta(IndNeutralize(((low * 0.721001) + (vwap * (1 - 0.721001))), ind), 3), 20))
r2 = ts_rank(decay_linear(ts_rank(correlation(ts_rank(low, 8), ts_rank(adv60, 17), 5), 19), 16), 7)
alpha = (r1 - r2) * -1
return alpha.fillna(value = 0)
def alpha100(volume,close,low,high,ind):
adv20 = sma(volume, 20)
r1 = IndNeutralize(rank(((((close - low) - (high - close)) / (high - low)) * volume)), ind)
r2 = 1.5 * scale(IndNeutralize(r1, ind))
r3 = scale(IndNeutralize((correlation(close, rank(adv20), 5) - rank(ts_argmin(close, 30))), ind))
alpha = -1 * (r2 - r3) * (volume / adv20)
return alpha.fillna(value = 0)
@@ -0,0 +1,184 @@
from WindPy import *
import numpy as np
import pandas as pd
from datetime import datetime
import matplotlib.pyplot as plt
w.start()
## 获取股票池
s_date = '2014-01-01'
e_date = '2016-01-01'
date = w.tdays(s_date, e_date, "preiod = D").Data[0] # 日期函数
stocks = w.wset("sectorconstituent", "date="+e_date+";windcode=000906.SH").Data[1] # 中证800股票池
## 获取日频量价原始数据
close = w.wsd(stocks,'close',s_date,e_date,usedf = True)[1].reset_index().drop(columns = ['index'])
# 改日期索引为数字,考虑后文rolling函数应用的便捷性
returns = w.wsd(stocks,'pct_chg',s_date,e_date,usedf = True)[1].reset_index().drop(columns = ['index'])
Open = w.wsd(stocks,'open',s_date,e_date,usedf = True)[1].reset_index().drop(columns = ['index'])
low = w.wsd(stocks,'low',s_date,e_date,usedf = True)[1].reset_index().drop(columns = ['index'])
vwap = w.wsd(stocks,'vwap',s_date,e_date,usedf = True)[1].reset_index().drop(columns = ['index'])
high = w.wsd(stocks,'high',s_date,e_date,usedf = True)[1].reset_index().drop(columns = ['index'])
cap = w.wsd(stocks,'mkt_cap_ashare',s_date,e_date,usedf = True)[1].reset_index().drop(columns = ['index'])
volume = w.wsd(stocks,'volume',s_date,e_date,usedf = True)[1].reset_index().drop(columns = ['index'])
ind = w.wss(stocks, "industry_citic","unit=1;tradeDate="+date[0].strftime("%Y%m%d")+";industryType=1")
## 计算因子值
start_1 = datetime.now() # 记录计算用时
alpha_1 = alpha1(close,returns)
alpha_2 = alpha2(Open,close,volume)
alpha_3 = alpha3(Open,volume)
alpha_4 = alpha4(low)
alpha_5 = alpha5(Open,vwap,close)
alpha_6 = alpha6(Open, volume)
alpha_7 = alpha7(volume,close)
alpha_8 = alpha8(Open,returns)
alpha_9 = alpha9(close)
alpha_10 = alpha10(close)
alpha_11 = alpha11(vwap,close,volume)
alpha_12 = alpha12(volume,close)
alpha_13 = alpha13(volume,close)
alpha_14 = alpha14(Open,volume,returns)
alpha_15 = alpha15(high,volume)
alpha_16 = alpha16(high,volume)
alpha_17 = alpha17(volume,close)
alpha_18 = alpha18(close,Open)
alpha_19 = alpha19(close,returns)
alpha_20 = alpha20(Open,high,close,low)
alpha_21 = alpha21(volume,close)
alpha_22 = alpha22(high,volume,close)
alpha_23 = alpha23(high,close)
alpha_24 = alpha24(close)
alpha_25 = alpha25(volume,returns,vwap,high,close)
alpha_26 = alpha26(volume,high)
alpha_27 = alpha27(volume,vwap)
alpha_28 = alpha28(volume,high,low,close)
alpha_29 = alpha29(close,returns)
alpha_30 = alpha30(close,volume)
alpha_31 = alpha31(close,low,volume)
alpha_32 = alpha32(close,vwap)
alpha_33 = alpha33(Open,close)
alpha_34 = alpha34(close,returns)
alpha_35 = alpha35(volume,close,high,low,returns)
alpha_36 = alpha36(Open,close,volume,returns,vwap)
alpha_37 = alpha37(Open,close)
alpha_38 = alpha38(close,Open)
alpha_39 = alpha39(volume,close,returns)
alpha_40 = alpha40(high,volume)
alpha_41 = alpha41(high,low,vwap)
alpha_42 = alpha42(vwap,close)
alpha_43 = alpha43(volume,close)
alpha_44 = alpha44(high,volume)
alpha_45 = alpha45(close,volume)
alpha_46 = alpha46(close)
alpha_47 = alpha47(volume,close,high,vwap)
alpha_49 = alpha49(close)
alpha_50 = alpha50(volume,vwap)
alpha_51 = alpha51(close)
alpha_52 = alpha52(returns,volume,low)
alpha_53 = alpha53(close,high,low)
alpha_54 = alpha54(Open,close,high,low)
alpha_55 = alpha55(high,low,close,volume)
alpha_56 = alpha56(returns,cap)
alpha_57 = alpha57(close,vwap)
alpha_60 = alpha60(close,high,low,volume)
alpha_61 = alpha61(volume,vwap)
alpha_62 = alpha62(volume,high,low,Open,vwap)
alpha_64 = alpha64(high,low,Open,volume,vwap)
alpha_65 = alpha65(volume,vwap,Open)
alpha_66 = alpha66(vwap,low,Open,high)
alpha_68 = alpha41(high,low,vwap)
alpha_71 = alpha71(volume,close,low,Open,vwap)
alpha_72 = alpha72(volume,high,low,vwap)
alpha_73 = alpha73(vwap,Open,low)
alpha_74 = alpha74(volume,close,high,vwap)
alpha_75 = alpha75(volume,vwap,low)
alpha_77 = alpha77(volume,high,low,vwap)
alpha_78 = alpha78(volume,low,vwap)
alpha_81 = alpha81(volume,vwap)
alpha_83 = alpha83(high,low,close,volume)
alpha_84 = alpha84(vwap,close)
alpha_85 = alpha85(volume,high,close,low)
alpha_86 = alpha41(high,low,vwap)
alpha_88 = alpha88(volume,Open,low,high,close)
alpha_92 = alpha92(volume,high,low,close,Open)
alpha_94 = alpha94(volume,vwap)
alpha_95 = alpha95(volume,high,low,Open)
alpha_96 = alpha96(volume,vwap,close)
alpha_98 = alpha98(volume,Open,vwap)
alpha_99 = alpha99(volume,high,low)
alpha_100 = alpha41(high,low,vwap)
alpha_101 = alpha101(close,Open,high,low)
alpha_48 = alpha48(close,ind) # 这些因子涉及行业中性化,计算时间较长
alpha_58 = alpha58(vwap,volume,ind)
alpha_59 = alpha59(vwap,volume,ind)
alpha_63 = alpha63(volume,close,vwap,Open,ind)
alpha_67 = alpha67(volume,vwap,high,ind)
alpha_69 = alpha69(volume,vwap,ind,close)
alpha_70 = alpha70(close,ind,vwap)
alpha_76 = alpha76(volume,vwap,low,ind)
alpha_79 = alpha79(volume,close,Open,ind,vwap)
alpha_80 = alpha80(Open,high,ind)
alpha_82 = alpha82(Open,volume,ind)
alpha_87 = alpha87(volume,close,vwap)
alpha_89 = alpha89(low,vwap,ind)
alpha_90 = alpha90(volume,close,ind,low)
alpha_91 = alpha91(close,ind,volume,vwap)
alpha_93 = alpha93(vwap,ind,volume,close)
alpha_97 = alpha97(volume,low,vwap,ind)
alpha_100 = alpha100(volume,close,low,high,ind)
# 因子放入列表
data_alpha = [alpha_1,alpha_2,alpha_3,alpha_4,alpha_5,alpha_6,alpha_7,alpha_8,alpha_9,alpha_10,
alpha_11,alpha_12,alpha_13,alpha_14,alpha_15,alpha_16,alpha_17,alpha_18,alpha_19,alpha_20,
alpha_21,alpha_22,alpha_23,alpha_24,alpha_25,alpha_26,alpha_27,alpha_28,alpha_29,alpha_30,
alpha_31,alpha_32,alpha_33,alpha_34,alpha_35,alpha_36,alpha_37,alpha_38,alpha_39,alpha_40,
alpha_41,alpha_42,alpha_43,alpha_44,alpha_45,alpha_46,alpha_47,alpha_48,alpha_49,alpha_50,
alpha_51,alpha_52,alpha_53,alpha_54,alpha_55,alpha_56,alpha_57,alpha_58,alpha_59,alpha_60,
alpha_61,alpha_62,alpha_63,alpha_64,alpha_65,alpha_66,alpha_67,alpha_68,alpha_69,alpha_70,
alpha_71,alpha_72,alpha_73,alpha_74,alpha_75,alpha_76,alpha_77,alpha_78,alpha_79,alpha_80,
alpha_81,alpha_82,alpha_83,alpha_84,alpha_85,alpha_86,alpha_87,alpha_88,alpha_89,alpha_90,
alpha_91,alpha_92,alpha_93,alpha_94,alpha_95,alpha_96,alpha_97,alpha_98,alpha_99,alpha_100,alpha_101]
# 由于一些因子应用前几个月的数据进行计算,因此初始时期因子为错误值,所以取两年保留一年
for i in range(len(data_alpha)):
data_alpha[i] = data_alpha[i].iloc[245:] # 243,245,244,244,244/这些数字为某年交易日数量
df_101 = pd.concat(data_alpha) # 合并各因子的数据
df_101.to_csv('data/alpha.csv') # 储存数据至csv文件
## 提取数据并转换数据结构
# 因子数据转化为时间+股票的双重索引格式
def zhuanhuan(alpha_1,date,stocks,columns = ['alpha']):
alpha_year = alpha_1.fillna(value = 0)
alpha_year.set_index(date,inplace = True)
index = pd.MultiIndex.from_product([date,stocks],names = ['date', 'codes'])
df = pd.DataFrame(alpha_year.stack(),columns = columns)
alpha = pd.DataFrame(df.values,columns = columns,index = index)
return alpha
date_list = ['2014-01-01','2015-01-01','2016-01-01','2017-01-01','2018-01-01','2019-05-30'] # 测试区间,每年更换一次股票池
data_alpha = []
div = 101
# 从csv文件取出因子数据存进列表
for i in range(5):
data_ = pd.read_csv('data/data_alpha_re'+str(i+1)+'.csv')
data_.drop(data_.columns[0], axis=1, inplace=True)
data_alpha.append(data_)
# 将之前合并的因子进行分割,并转换数据结构为双重索引,存进二维列表
for i in range(5):
data = []
df = data_alpha[i]
n = int(len(df)/div)
date = w.wsd('000001.SZ','close',date_list[i],date_list[i+1],period = 'D',usedf = True)[1].index
stocks = w.wset("sectorconstituent", "date="+date_list[i+1]+";windcode=000906.SH").Data[1]
for j in range(div):
d = zhuanhuan(df.iloc[n*j:n*(j+1)],date,stocks,columns = ['alpha'+str(j+1)])
data.append(d)
data_alpha[i] = data
# 将各因子不同时期的数据进行合并,得到一维列表data存放各因子的双重索引可用数据
data = []
for j in range(div):
d = pd.concat([data_alpha[0][j],data_alpha[1][j],data_alpha[2][j],data_alpha[3][j],data_alpha[4][j]])
data.append(d)
@@ -0,0 +1,61 @@
## 股票池筛选,可交易,非新股,非PT,ST,涨跌停的股票
def get_stocks(trDate):
trDate = trDate.strftime('%Y-%m-%d')
stocks_800 = w.wset("sectorconstituent", "date="+trDate+";windcode=000906.SH").Data[1]
status = w.wss(stocks_800, "trade_status,maxupordown,riskwarning,ipo_date", tradeDate=trDate, usedf=True)[1]
date_least=w.tdaysoffset(-6,trDate,'Period=M').Data[0][0]
trade_codes=list(status[(status['TRADE_STATUS']=='交易')&(status['IPO_DATE']<=date_least)&(status['MAXUPORDOWN']==0)&(status['RISKWARNING']=='否')].index)
return trade_codes
trade_d = w.tdays("2014-01-02", "2019-05-30", Period='M',usedf=True).Data[0]
stock_valid = []
for i in range(len(trade_d)):
stock_valid.append(get_stocks(trade_d[i]))
stock_valid_df = pd.DataFrame(stock_valid,index = trade_d)
## 获取下期收益数据
Period = 'M'
# 时间列表设置避免取到重复数据
date_list = ['2014-01-02','2015-01-09','2016-01-08','2017-01-06','2018-01-05','2019-05-30']
date_listd = ['2015-01-08','2016-01-07','2017-01-05','2018-01-04','2019-04-30']
date_listw = ['2015-01-02','2016-01-01','2016-12-30','2017-12-29','2019-05-30']
date_listm = ['2015-01-01','2016-01-01','2017-01-01','2018-01-01','2019-04-30']
next_ret = []
bench_date = [] # 之后分层测试可视化需要用到
for i in range(5):
date = w.wsd('000001.SZ','close',date_list[i],date_listm[i],period = Period,usedf = True)[1].index
stocks = w.wset("sectorconstituent", "date="+date_listm[i]+";windcode=000906.SH").Data[1]
d1 = w.tdaysoffset(1, date[0], Period = Period,usedf=True).Data[0][0].strftime('%Y-%m-%d') # 时间往后推一个周期,并且格式转化为字符串
d2 = w.tdaysoffset(1, date[-1],Period = Period, usedf=True).Data[0][0].strftime('%Y-%m-%d')
bench_date.append(d1)
bench_date.append(d2)
next_ret_ = w.wsd(stocks, "pct_chg", d1, d2, usedf=True, Period = Period)[1].fillna(value = 0)
f = lambda x: x/100 # 万矿收益率数据单位为100%,这里换算成小数
next_ret_ = next_ret_.applymap(f)
next_ret.append(zhuanhuan(next_ret_,date,stocks,columns = ['NEXT_RET'])) # 转化下期收益数据为双重索引
next_ret = pd.concat(next_ret) # 合并5年的下期收益数据
## IC测试
def ic_fenxi(df,next_ret,alpha = ['alpha']):
d = list(next_ret.index.levels[0]) # 获取双索引中的日期索引
ic_s = []
df = df.fillna(value = 0) # 异常值填充为0
for i in range(len(date_)):
stock_v = stock_valid_df.loc[d[i]].dropna().values # 获取当期有效股票池
stock_v = list(set(stock_v) & set(df.loc[d[i]].index))
dff = df.loc[d[i]].loc[stock_v] # 提取当期可用因子值和下期收益数据
# dff = dff.sort_values(alpha,ascending=False).iloc[:round(len(dff)/10)] # 提取top组的数据分析
ic_s.append(dff['NEXT_RET'].corr(dff[alpha],method='spearman')) # 计算因子值与下期收益的秩相关系数,并存进ic值列表
ic_s = pd.Series(ic_s) # 列表转化为Series,从而能够计算各统计量
rate = len(ic_s[ic_s>=0])/len(ic_s) # ic值大于0的比例
IC_mean = ic_s.mean() # ic均值
IC_std = ic_s.std() # ic标准差
IC_IR = ic_s.mean()/ic_s.std() # ic_IR用来衡量因子有效性
stats = [IC_mean,IC_std,IC_IR,rate]
return stats
for i in range(len(data)):
d = list(next_ret.index.levels[0])
lc = data[i].loc[d] # 根据调仓频率筛选数据
lc['NEXT_RET'] = next_ret.NEXT_RET
list_ic = ic_fenxi(lc,next_ret,alpha = ['alpha'+str(i+1)]) # 计算IC统计量
print(list_ic)
@@ -0,0 +1,66 @@
## 分层测试
def return_fenxi(df,d,num,alpha = 'alpha'):
df.fillna(value = 0,inplace = True)
date_ = d
return_s = []
for i in range(len(date_)):
stock_v = stock_valid_df.loc[d[i]].dropna().values
stock_v = list(set(stock_v) & set(df.loc[d[i]].index))
dff = df.loc[d[i]].loc[stock_v]
x = dff[alpha]
if x.sum() != 0: # 筛选掉因子值异常期
df_i = dff.sort_values(alpha)
return_list = []
for j in range(num):
n1 = round(len(df_i)*j/num)
n2 = round(len(df_i)*(j+1)/num)
df_j = df_i.iloc[n1:n2]
return_j = df_j['NEXT_RET'].mean()+1
return_list.append(return_j)
return_s.append(return_list)
x = np.array(return_s).T # 二维列表转化为二维数组转置
return_s = [list(i) for i in x]
for i in range(num):
x = return_s[i]
for j in range(1,len(x)):
x[j] = x[j]*x[j-1]
return_s[i] = x
culmu = [re[-1] for re in return_s]
return culmu,return_s
def fencengceshi(data,next_ret,num):
data_re = []
data_re1 = []
for i in range(len(data)):
lc = data[i]
#lc.fillna(value = 0,inplace = True)
d = list(next_ret.index.levels[0])
lc = data[i].loc[d]
lc['NEXT_RET'] = next_ret.NEXT_RET
list_re1,list_re = return_fenxi(lc,d,num,alpha = data[i].columns[0])
data_re.append(list_re)
data_re1.append(list_re1)
print(data_re1[i]) # 各因子最终各组累计收益
return data_re
df = fencengceshi(data,next_ret,num=20) # 各因子分组累计收益序列
dff = fencengceshi(data,next_ret,num=1) # 计算等权基准线
## 各组收益时序图,top/middle/bottom
n = 1
x = df[n-1]
y1 = x[0]
y2 = x[num/2]
y3 = x[-1]
d = list(next_ret.index.levels[0])[-len(y1):]
bench = dff[1][0][-len(y1):]
plt.subplots(figsize=(15,5)) # 图的长宽设置
plt.plot(d,y1,label='Group1')
plt.plot(d,y2,label='Group2')
plt.plot(d,y3,label='Group3')
plt.plot(d,bench,label='ZZ800')
plt.legend()
plt.title('alpha'+str(n)+' 分层测试(月)')
plt.xlabel('回测区间')
plt.ylabel("净值")
@@ -0,0 +1,135 @@
from WindPy import *
import numpy as np
import pandas as pd
import numpy.linalg as la
import seaborn as sns
w.start()
## 组合多因子
lc = data.copy()
num_list = [42,44,36,15,4]
num_list = [i-1 for i in num_list]
m = []
alpha_m = lc[num_list[0]].copy()
for i in num_list[1:]:
alpha_m['alpha'+str(i+1)] = lc[i]['alpha'+str(i+1)]
## 因子数据预处理
# 因子相关系数热力图
fig=plt.figure(figsize=(10,6))
relations= alpha_m.corr()
sns.heatmap(relations,annot=True,linewidths=0.05,linecolor='white',annot_kws={'size':8,'weight':'bold'})
# 中位数去极值
def extreme_process_MAD(sample): # 输入的sample为时间截面的股票因子df数据
factor_name = list(sample.columns)
for name in factor_name:
x = sample[name]
median = x.median()
MAD = abs(x - median).median()
x[x>(median+3*1.4826*MAD)] = median+3*1.4826*MAD
x[x<(median-3*1.4826*MAD)] = median-3*1.4826*MAD
sample[name] = x
return sample
# 行业市值中性化
def data_scale_neutral(sample,date):
stocks = list(sample.index)
ind=w.wss(stocks, "industry_citic","unit=1;tradeDate="+date+";industryType=1", usedf=True)[1]
Incap=w.wss(stocks, "val_lnmv","unit=1;tradeDate="+date+";industryType=1", usedf=True)[1]
data_med = pd.get_dummies(ind,columns=['INDUSTRY_CITIC']) # 生成0-1变量矩阵
x = pd.concat([data_med,Incap],axis=1).dropna()
X= np.array(x)
sample = sample.loc[list(x.index)]
factor_name = list(sample.columns)
for name in factor_name:
y = np.array(sample[name])
if la.matrix_rank(X.T.dot(X)) == X.shape[1]:
beta_ols = la.inv(X.T.dot(X)).dot(X.T).dot(y) # 最小二乘法计算拟合值
residual = y - X.dot(beta_ols) # 取残差为中性化后的因子值
else:
residual = y
sample[name] = residual
return sample
# 标准化
def standardize(sample):
factor_name = list(sample.columns)
for name in factor_name:
x = sample[name]
sample[name] = (x - np.mean(x))/(np.std(x))
return sample
# 数据预处理
def data_process(sample,date):
sample = extreme_process_MAD(sample)
sample = data_scale_neutral(sample,date)
sample = standardize(sample)
return sample
# 回测筛选股票池
def get_stocks(trDate,A_stocks):
status = w.wss(A_stocks, "trade_status,maxupordown,riskwarning,ipo_date", tradeDate=trDate, usedf=True)[1]
date_least=w.tdaysoffset(-6,trDate,'Period=M').Data[0][0]
trade_codes=list(status[(status['TRADE_STATUS']=='交易')&(status['IPO_DATE']<=date_least)&(status['MAXUPORDOWN']==0)&(status['RISKWARNING']=='否')].index)
return trade_codes
# 最大化历史ICIR加权/历史IC均值加权
def IR_weight(bar_datetime_str,stocks,alpha_data):
Period="W"
begin_time = w.tdaysoffset(-12, bar_datetime_str, Period=Period, usedf=True).Data[0][0].strftime('%Y-%m-%d')
time_list = w.tdays(begin_time,bar_datetime_str,Period=Period, usedf=True).Data[0]
time_list = [time.strftime('%Y-%m-%d') for time in time_list]
IC_s = []
IC = []
next_ret = w.wsd(stocks, "pct_chg", begin_time, bar_datetime_str, usedf=True, Period = Period)[1].fillna(value = 0).iloc[1:]
for i in range(12):
factor = alpha_data.loc[time_list[i]].reset_index().set_index(['codes']).drop(columns = ['date']).loc[stocks] # 转化为股票单层索引
factor_name = list(factor.columns)
ic_s = []
for name in factor_name:
try:
ic_s.append(factor[name].corr(next_ret.iloc[i],method='spearman'))
except:
ic_s.append(factor[name].corr(next_ret.iloc[i-1],method='spearman'))
IC_s.append(ic_s)
IC_s = np.array(IC_s).T
W = np.cov(IC_s)
for i in range(len(IC_s)):
IC.append(IC_s[i].mean())
IC_IR = np.dot(W,np.array(IC))
return IC_IR # np.array(IC)
# 最大化历史收益率加权
def rate_weight(bar_datetime_str,stocks,alpha_data,num=10):
Period="W"
begin_time = w.tdaysoffset(-12, bar_datetime_str, Period=Period, usedf=True).Data[0][0].strftime('%Y-%m-%d')
time_list = w.tdays(begin_time,bar_datetime_str,Period=Period, usedf=True).Data[0]
time_list = [time.strftime('%Y-%m-%d') for time in time_list]
IC_s = []
IC = []
next_ret = w.wsd(stocks, "pct_chg", begin_time, bar_datetime_str, usedf=True, Period = Period)[1].fillna(value = 0).iloc[1:]
for i in range(12):
factor = alpha_data.loc[time_list[i]].reset_index().set_index(['codes']).drop(columns = ['date']).loc[stocks]
factor_name = list(factor.columns)
ic_s = []
for name in factor_name:
g10 = list(factor.sort_values([name],ascending=False).iloc[:round(len(factor)/num)].index)
try:
ic_s = (next_ret.T.loc[g10]).T.iloc[i].mean()
except:
ic_s = (next_ret.T.loc[g10]).T.iloc[i-1].mean()
IC_s.append(ic_s)
IC_s = np.array(IC_s).T
for i in range(len(IC_s)):
IC.append(IC_s[i].mean())
rate = np.array(IC)
return rate
# 因子打分
def factor_sum(sample,weight_list):
factor_name = list(sample.columns)
sample['alpha_sum'] = sample[factor_name[0]] * 0
for i in range(len(factor_name)):
sample['alpha_sum'] = sample['alpha_sum'] + sample[factor_name[i]] * weight_list[i]
return sample
@@ -0,0 +1,68 @@
from WindPy import *
from datetime import *
from WindAlgo import *
from scipy.stats import rankdata
import numpy as np
import pandas as pd
from datetime import datetime
import scipy.stats as stats
import numpy.linalg as la
w.start()
alpha_data = alpha_m
def initialize(context):
context.capital = 10000000 # 回测的初始资金
context.securities = w.wset("sectorconstituent", "date=20140101;windcode=000906.SH").Data[1]
context.start_date = "20140104" # 回测开始时间
context.end_date = "20190530" # 回测结束时间
context.commission = 0.0003 # 手续费
context.alpha_data = alpha_data
context.benchmark = '000906.SH' # 设置回测基准
def handle_data(bar_datetime, context, bar_data):
pass
def my_schedule1(bar_datetime, context, bar_data):
bar_datetime_str = bar_datetime.strftime('%Y-%m-%d')
stock800 = w.wset("sectorconstituent", "date="+bar_datetime_str+";windcode=000906.SH").Data[1]
stocks = get_stocks(bar_datetime_str,stock800) # 获取筛选后的股票池
## 提取因子数据法
data = context.alpha_data.loc[bar_datetime_str].reset_index().set_index(['codes']).drop(columns = ['date']) #提取因子数据并调整结构
stock_v = list(set(stocks) & set(data.index))
data = data.loc[stock_v].dropna(axis=0) # 筛选出有效股票池对应数据
profit = w.wss(stock_v, "fa_oigr_ttm,pe_ttm", tradeDate=bar_datetime_str, usedf=True)[1] # 加入财务因子
profit.index = data.index
data['1/PEG'] = profit['FA_OIGR_TTM']/profit['PE_TTM']
data = data_process(data,bar_datetime_str) # 数据预处理
weight = [] # 因子加权权重
data = factor_sum(data,weight) # 因子打分
## 回测中计算法
# start_time = w.tdaysoffset(-5, bar_datetime_str,usedf=True).Data[0][0].strftime('%Y-%m-%d')
# close = w.wsd(stocks,'close',start_time,bar_datetime_str,usedf = True)[1].reset_index().drop(columns = ['index'])
# vwap = w.wsd(stocks,'vwap',start_time,bar_datetime_str,usedf = True)[1].reset_index().drop(columns = ['index'])
# alpha = {'alpha':alpha42(vwap,close).iloc[-1]}
# data = pd.DataFrame(alpha,index=stocks)
data = data.sort_values([data.columns.values[-1]],ascending=False) # 按打分大小排序
code_list = list(data[:round(len(stocks)/5)].index) # 选出top组股票
wa.change_securities(code_list) # 改变证券池
context.securities = code_list
list_sell = list(wa.query_position().get_field('code')) # 获取当前仓位股票池
for code in list_sell:
if code not in code_list:
volumn = wa.query_position()[code]['volume'] # 找到每个股票的持仓量
res = wa.order(code,volumn,'sell',price='close', volume_check=False)
def my_schedule2(bar_datetime, context,bar_data):
buy_code_list=list(set(context.securities)-(set(context.securities)-set(list(bar_data.get_field('code')))))
list_now = list(wa.query_position().get_field('code')) # 获取当前仓位股票池
for code in buy_code_list:
if code not in list_now:
res = wa.order_percent(code,1/len(buy_code_list),'buy',price='close', volume_check=False) # 等权买入
wa = BackTest(init_func = initialize, handle_data_func=handle_data) # 实例化回测对象
wa.schedule(my_schedule1, "w", 0) # w表示在每周执行一次策略,0表示偏移,表示月初第一个交易日往后0天
wa.schedule(my_schedule2, "w", 0)
res = wa.run(show_progress=True) # 调用run()函数开始回测,show_progress可用于指定是否显示回测净值曲线图
nav_df = wa.summary('nav') # 获取回测结果,回测周期内每一天的组合净值
@@ -0,0 +1,2 @@
# alpha101
基于万矿平台对alpha101因子进行测试并构造多因子策略