多因子模型系列9-阿里巴巴与101个alpha

根据worldquant发表的论文《101 Formulaic Alphas 》 ,其中公式化地给出了101个alpha因子。论文地址在这:https://arxiv.org/pdf/1601.00991.pdf  他们根据数据挖掘的方法发掘了101个alpha,据说里面80%的因子仍然还行之有效并运行在他们的production中。

对于worldquant的websim回测系统进行了模拟,可改变alpha表达式自行编写expression形式的alpha进行回测。如:alpha=1/close.

对其中的函数进行如下解释:

  • 可分为横截面函数和时间序列函数两大类,其中时间序列函数名多为以ts_开头
  • 大部分函数命名方式较为直观
  • abs(x) log(x)分别表示x的绝对值和x的自然对数
  • rank(x)表示某股票x值在横截面上的升序排名序号,并将排名归一到[0,1]的闭区间
  • delay(x,d)表示x值在d天前的值
  • delta(x,d)表示x值的最新值减去x值在d天前的值
  • correlation(x,y,d) covariance(x,y,d)分别表示x和y在长度为d的时间窗口上的Pearson相关系数和协方差
  • ts_min(x,d) ts_max(x,d) ts_argmax(x,d) ts_argmin(x,d) ts_rank(x) sum(x,d) stddev(x,d)等均可以通过函数名称了解其作用
  • 具体函数详情见Available Operators

alpha值意义:在每个迭代或者说在每一个交易日,通过计算表达式得到的 每一只股票的Alpha 值,可以得出进行买卖的工具(股票)数量。Alpha  不是表示想要花多少钱买卖,而是在当日的资金比例。

Neutralization(中性化): 中性化是一种将我们的策略按照市场、行业或子行业进行中性化的操作。当设置 Neutralization=“market” (中性化=整个市场)时,它会进行以下操作:

alpha = alpha – mean(alpha)

基本上,它使 Alpha 向量的均值为零,使得市场上的“净”头寸为零。换句话说,多头头寸和空头头寸相互完全抵消,使我们的策略完全市场中性化。

当设置 Neutralization=“industry”或“sub-industry”(中性化=行业或子行业),那么所有在 Alpha 向量中的金融工具将会按照行业或者子行业分成数个小组,然后对每个小组进行中性化。

if i = **Subindustry 中性化:将i这只股票的alpha值减去子行业alpha的均值

alpha(i) = alpha(i) – mean((alpha.subindustry(i)))

中性化(Neutralization)指的是将原始的Alpha值放入不同组,然后在各组内进行标准化(Normalization,指用每个数值减去平均值)的一种操作。 一个组可以是整个市场。 或者根据其他分类来定义组,例如行业或者子行业(基于申银万国行业)。 这样做是为了避免收益受所选组的走向影响,而只注重于股票未来的相对收益。 中性化操作之后,整个投资组合处于中性仓位(多头和空头各占一半)。 这种做法可防止投资组合受市场剧烈波动的影响,还能过滤一些虚假信号。

这里有一个简单的例子,假设 Alpha = close(收盘价格)。
假设您的样本空间里面有 5 只股票(A、B、C、D、E),而在某个特定的日期(20100104)它们的收盘价分别如下(以美元计):

金融工具(股票):  A    B    C    D    E

收     盘   价:             6    5     2    8     4

现在,您想要使用这些收盘价来计算下一个交易日的 Alpha 权重。 您首先要做的就是写出 Alpha 表达式,在这里即 Alpha = close。因此您首先要有一个构建一个“close”(收盘价)的向量,即(6, 5, 2, 8, 4)。【注:如果您的表达式是 Alpha = 1 / close,那么您需要构建的向量也必须是“1 / close”,即(1/6, 1/5, 1/2, 1/8, 1/4) = (0.167, 0.2, 0.5, 0.125, 0.25)。】

现在您有了向量(6,5,2,8,4),但这不并是权重向量。权重的向量需要经过标准化处理到1。因此我们将每个元素除以它们的总和(= 25),得到的元素总和等于 1。
于是得到了新的向量:(6 / 25, 5 / 25, 2 / 25, 8 / 25, 4 / 25) = (0.24, 0.20, 0.08, 0.32, 0.16)。此向量的总和是 1。这就是我们的投资组合。我们将每个元素再乘以资金规模(2000 万),就能得到我们需要在每只股票上投资的金额。

这是我们将 Neutralization(中性化)设定为“None”得到的结果。不过这种方法会让我们的策略受到市场风险的影响。于是,我们设置 Neutralization = “Market”(中性化 = “市场”)。在这种情况下,我们首先再一次构建一个“close”(收盘价)的向量 = (6, 5, 2, 8, 4)。
现在我们使其 “mean-neutral (均值中性化)”,也就是将每个元素减去他们的均值(=5),使得向量的总和为 0。
于是得到了均值中性化的向量: (1, 0, -3, 3, -1)。您会发现此时所有元素的总和为零。

现在,若要对其进行标准化处理,我们忽略数值的正负,使元素总和为 1。首先我们计算元素绝对值的总和(= 1 + 0 + 3 + 3 + 1 = 8)。现在我们的将每个元素除以它们的总和,得到 (1 / 8, 0 / 8, -3 / 8, 3 / 8, -1 / 8) = (+0.125, 0, -0.375, +0.375, -0.125)。
现在,这就是标准化均值中性的权重向量。我们把它乘以资金规模 2000 万美元,就得到了我们在每只股票上需要投资的金额,如果数值为正,则表明对其建立多头头寸,如果数值为负,则表明对其建立空头头寸。此外,因为所有的正值相加等于 0.5,而负值相加等于 -0.5,这表明我们在多头头寸上投资了 1000 万美元,在空头头寸上也投资了 1000 万美元,满足了中性化策略的要求。

收益图

风险指标

源代码

# 可以自己import我们平台支持的第三方python模块,比如pandas、numpy等。
import numpy as np 
import pandas as pd 
from numpy import abs 
from numpy import log
from numpy import sign
from scipy.stats import rankdata

# 在这个方法中编写任何的初始化逻辑。context对象将会在你的算法策略的任何方法之间做传递。
def init(context):
    # 初始化待买股票池
    context.stock_pool=[]
    # 初始化卖空股票池
    context.stock_short=[]
    # 初始化购买权重
    context.weight=[]
    # 初始化卖空股票权重
    context.short_weight=[]
    # 获取市场所有股票
    context.stock=index_components('399958.XSHE')
    # context.stock=all_instruments(type='CS').order_book_id
    # 设置可以做空,但根据回测决定是否使用做空
    context.short_selling_allowed = True
    scheduler.run_daily(stoploss)
    context.drawdown= 0.1 # 回撤限度 10% 
    context.maxvalue=pd.DataFrame()
    pass

def stoploss(context,bar_dict):
    
    for stock in context.portfolio.positions:
        market_value=context.portfolio.positions[stock].market_value# 该股市场价值 单位(RMB)
        bought_value=context.portfolio.positions[stock].bought_value#该股初始价值 
        if stock in context.maxvalue:
            stockdic=context.maxvalue[stock]
            print(stock+'已卖出')
            maxvalue=stockdic[0]
            
            del context.maxvalue[stock]
            
            #currSP=context.initSPM*(1+math.floor((maxvalue/bought_value-1)/context.step)*context.increment) #阶梯止损算法 例: 该股市值增加10%, 止盈比例提高 5% 
            
            temp=pd.DataFrame({str(stock):[max(maxvalue,market_value)]})
            context.maxvalue=pd.concat([context.maxvalue,temp], axis=1, join='inner') # 更新其盘中最高价值和先阶段比例。 
            drawdown=1-market_value/max(maxvalue,market_value)
            
            print(str(stock)+'的成本为:' +str( bought_value) +', 最高价值为:'+str(maxvalue)+'现价值为:'+ str(market_value))
            print(str(stock) +'的现 回撤为: ' +str(drawdown*100)+ '%')
            #logger.info ( type(market_value))
            #logger.info(type(ontext.maxvalue[stock].values)))
            
            if drawdown>context.drawdown:# 现价低于 原价一定比例
                order_target_percent(stock,0)
                print(str(stock)+'回撤大于'+ str(context.drawdown*100)+ '%'+'  触发止损')
                del context.maxvalue[stock]
        
    pass 

def createdic(context,bar_dict,stock):
    if stock not in context.maxvalue.columns:
        temp=pd.DataFrame({str(stock):[context.portfolio.positions[stock].bought_value]})    
        context.maxvalue = pd.concat([context.maxvalue, temp], axis=1, join='inner')
    print(context.maxvalue)
    
# 计算alpha时会使用的函数
def ts_num(df,window=10):
    return df.rolling(window).sum()

def sma(df,window=10):
    return df.rolling(window).mean()

def stddev(df,window=10):
    return df.rolling(window).std()

def correlation(x,y,window=10):
    return x.rolling(window).corr(y)

def covariance(x,y,window=10):
    return x.rolling(window).cov(y)

def rolling_rank(na):
    return rankdata(na)[-1]

def ts_rank(window=10):
    return rolling(window).apply(rolling_rank)

def rolling_prod(na):
    return na.prod(na)
    
def product(df,window=10):
    return df.rolling(window).apply(rolling_prod)

def ts_min(df,window=10):
    return df.rolling(window).min()
    
def ts_max(df,window=10):
    return df.rolling(window).max()

def delta(df,period=1):
    return df.diff(period)
    
def delay(df,period=1):
    return df.shift(period)

def rank(df):
    return df.rank(axis=1,pct=True)

def scale(df,k=1):
    return df.mul(k).div(np.abs(df).sum())

def ts_argmax(df,window=10):
    return df.rolling(window).apply(np.argmax)+1

def ts_argmin(df,window=10):
    return df.rolling(window).apply(np.argmin)+1
    
def decay_linear(df,period=10):
    if df.isnull().values.any():
        df.fillna(method='ffill',inplace=True)
        df.fillna(method='dfill',inplace=True)
        df.fillna(value=0,inplace=True)
    na_lwma=np.zeros_like(df)
    na_lwma[:period,:]=df.ix[:period,:]
    na_series = df.as_matrix()
    divisor = df.as_matrix()
    y =(np.arrange(period)+1)*1.0/divisor
    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)
# 定义计算alpha值的类
class Alphas(object):
    def __init__(self, pn_data):
        """
        :传入参数 pn_data: pandas.Panel
        """
        # 获取历史数据
        self.open = pn_data['OpeningPx']
        self.high = pn_data['HighPx']
        self.low = pn_data['LowPx']
        self.close = pn_data['ClosingPx']
        self.volume = pn_data['TotalVolumeTraded']
        self.returns = self.close.pct_change()
    
    #   每个因子的计算公式:
    #   alpha001:(rank(Ts_ArgMax(SignedPower(((returns < 0) ? stddev(returns, 20) : close), 2.), 5)) -0.5) 
    
    def alpha001(self):
        inner = self.close
        inner[self.returns < 0] = stddev(self.returns, 20)
        return rank(ts_argmax(inner ** 2, 5))
        
    #  alpha002:(-1 * correlation(rank(delta(log(volume), 2)), rank(((close - open) / open)), 6)) 
    
    def alpha002(self):
        df = -1 * correlation(rank(delta(log(self.volume), 2)), rank((self.close - self.open) / self.open), 6)
        return df.replace([-np.inf, np.inf], 0).fillna(value=0)

    # alpha003:(-1 * correlation(rank(open), rank(volume), 10))  
    
    def alpha003(self):
        df = -1 * correlation(rank(self.open), rank(self.volume), 10)
        return df.replace([-np.inf, np.inf], 0).fillna(value=0)
    
    # alpha004: (-1 * Ts_Rank(rank(low), 9)) 
    
    def alpha004(self):
        return -1 * ts_rank(rank(self.low), 9)
    
    #  alpha006: (-1 * correlation(open, volume, 10)) 
    
    def alpha006(self):
        df = -1 * correlation(self.open, self.volume, 10)
        return df.replace([-np.inf, np.inf], 0).fillna(value=0)


    # alpha007: ((adv20 < volume) ? ((-1 * ts_rank(abs(delta(close, 7)), 60)) * sign(delta(close, 7))) : (-1* 1)) 

    def alpha007(self):
        adv20 = sma(self.volume, 20)
        alpha = -1 * ts_rank(abs(delta(self.close, 7)), 60) * sign(delta(self.close, 7))
        alpha[adv20 >= self.volume] = -1
        return alpha
    
    # alpha008: (-1 * rank(((sum(open, 5) * sum(returns, 5)) - delay((sum(open, 5) * sum(returns, 5)),10)))) 
    
    def alpha008(self):
        return -1 * (rank(((ts_sum(self.open, 5) * ts_sum(self.returns, 5)) -
                          delay((ts_sum(self.open, 5) * ts_sum(self.returns, 5)), 10))))
    
    # alpha009:((0 < ts_min(delta(close, 1), 5)) ? delta(close, 1) : ((ts_max(delta(close, 1), 5) < 0) ?delta(close, 1) : (-1 * delta(close, 1)))) 
    
    def alpha009(self):
        delta_close = delta(self.close, 1)
        cond_1 = ts_min(delta_close, 5) > 0
        cond_2 = ts_max(delta_close, 5) < 0
        alpha = -1 * delta_close
        alpha[cond_1 | cond_2] = delta_close
        return alpha
    
    # alpha010: rank(((0 < ts_min(delta(close, 1), 4)) ? delta(close, 1) : ((ts_max(delta(close, 1), 4) < 0)? delta(close, 1) : (-1 * delta(close, 1))))) 
    
    def alpha010(self):
        delta_close = delta(self.close, 1)
        cond_1 = ts_min(delta_close, 4) > 0
        cond_2 = ts_max(delta_close, 4) < 0
        alpha = -1 * delta_close
        alpha[cond_1 | cond_2] = delta_close
        return alpha
    
    #  alpha012:(sign(delta(volume, 1)) * (-1 * delta(close, 1))) 
    
    def alpha012(self):
        return sign(delta(self.volume, 1)) * (-1 * delta(self.close, 1))
    
    # alpha013:(-1 * rank(covariance(rank(close), rank(volume), 5))) 
    
    def alpha013(self):
        return -1 * rank(covariance(rank(self.close), rank(self.volume), 5))

    #  alpha014:((-1 * rank(delta(returns, 3))) * correlation(open, volume, 10)) 
    
    def alpha014(self):
        df = correlation(self.open, self.volume, 10)
        df = df.replace([-np.inf, np.inf], 0).fillna(value=0)
        return -1 * rank(delta(self.returns, 3)) * df

    # alpha015:(-1 * sum(rank(correlation(rank(high), rank(volume), 3)), 3)) 
    
    def alpha015(self):
        df = correlation(rank(self.high), rank(self.volume), 3)
        df = df.replace([-np.inf, np.inf], 0).fillna(value=0)
        return -1 * ts_sum(rank(df), 3)

    #  alpha016:(-1 * rank(covariance(rank(high), rank(volume), 5))) 
    
    def alpha016(self):
        return -1 * rank(covariance(rank(self.high), rank(self.volume), 5))

    # alpha017: (((-1 * rank(ts_rank(close, 10))) * rank(delta(delta(close, 1), 1))) *rank(ts_rank((volume / adv20), 5))) 

    def alpha017(self):
        adv20 = sma(self.volume, 20)
        return -1 * (rank(ts_rank(self.close, 10)) *
                     rank(delta(delta(self.close, 1), 1)) *
                     rank(ts_rank((self.volume / adv20), 5)))
    
    # alpha018: (-1 * rank(((stddev(abs((close - open)), 5) + (close - open)) + correlation(close, open,10)))) 
        
    def alpha018(self):
        df = correlation(self.close, self.open, 10)
        df = df.replace([-np.inf, np.inf], 0).fillna(value=0)
        return -1 * (rank((stddev(abs((self.close - self.open)), 5) + (self.close - self.open)) +
                          df))

    #  alpha019:((-1 * sign(((close - delay(close, 7)) + delta(close, 7)))) * (1 + rank((1 + sum(returns,250)))))

    def alpha019(self):
        return ((-1 * sign((self.close - delay(self.close, 7)) + delta(self.close, 7))) *
                (1 + rank(1 + ts_sum(self.returns, 250))))

    # alpha020: (((-1 * rank((open - delay(high, 1)))) * rank((open - delay(close, 1)))) * rank((open -delay(low, 1))))

    def alpha020(self):
        return -1 * (rank(self.open - delay(self.high, 1)) *
                     rank(self.open - delay(self.close, 1)) *
                     rank(self.open - delay(self.low, 1)))

    # alpha012: ((((sum(close, 8) / 8) + stddev(close, 8)) < (sum(close, 2) / 2)) ? (-1 * 1) : (((sum(close,2) / 2) < ((sum(close, 8) / 8) - stddev(close, 8))) ? 1 : (((1 < (volume / adv20)) || ((volume /adv20) == 1)) ? 1 : (-1 * 1)))) 

    def alpha021(self):
        cond_1 = sma(self.close, 8) + stddev(self.close, 8) < sma(self.close, 2)
        cond_2 = sma(self.volume, 20) / self.volume < 1
        alpha = pd.DataFrame(np.ones_like(self.close), index=self.close.index,
                             columns=self.close.columns)
        alpha[cond_1 | cond_2] = -1
        return alpha

    # alpha022:(-1 * (delta(correlation(high, volume, 5), 5) * rank(stddev(close, 20)))) 

    def alpha022(self):
        df = correlation(self.high, self.volume, 5)
        df = df.replace([-np.inf, np.inf], 0).fillna(value=0)
        return -1 * delta(df, 5) * rank(stddev(self.close, 20))

    # alpha023: (((sum(high, 20) / 20) < high) ? (-1 * delta(high, 2)) : 0) 

    def alpha023(self):
        cond = sma(self.high, 20) < self.high
        alpha = pd.DataFrame(np.zeros_like(self.close), index=self.close.index,
                             columns=self.close.columns)
        alpha[cond] = -1 * delta(self.high, 2)
        return alpha

    # alpha024: ((((delta((sum(close, 100) / 100), 100) / delay(close, 100)) < 0.05) ||((delta((sum(close, 100) / 100), 100) / delay(close, 100)) == 0.05)) ? (-1 * (close - ts_min(close,100))) : (-1 * delta(close, 3)))  

    def alpha024(self):
        cond = delta(sma(self.close, 100), 100) / delay(self.close, 100) <= 0.05
        alpha = -1 * delta(self.close, 3)
        alpha[cond] = -1 * (self.close - ts_min(self.close, 100))
        return alpha
    
    #   alpha026:(-1 * ts_max(correlation(ts_rank(volume, 5), ts_rank(high, 5), 5), 3)) 
    def alpha026(self):
        df = correlation(ts_rank(self.volume, 5), ts_rank(self.high, 5), 5)
        df = df.replace([-np.inf, np.inf], 0).fillna(value=0)
        return -1 * ts_max(df, 3)

    # alpha028:scale(((correlation(adv20, low, 5) + ((high + low) / 2)) - close)) 
    
    def alpha028(self):
        adv20 = sma(self.volume, 20)
        df = correlation(adv20, self.low, 5)
        df = df.replace([-np.inf, np.inf], 0).fillna(value=0)
        return scale(((df + ((self.high + self.low) / 2)) - self.close))
    
    # alpha029:(min(product(rank(rank(scale(log(sum(ts_min(rank(rank((-1 * rank(delta((close - 1),5))))), 2), 1))))), 1), 5) + ts_rank(delay((-1 * returns), 6), 5)) 
    def alpha029(self):
        return (ts_min(rank(rank(scale(log(ts_sum(rank(rank(-1 * rank(delta((self.close - 1), 5)))), 2))))), 5) +
                ts_rank(delay((-1 * self.returns), 6), 5))
    
    # alpha0230:(((1.0 - rank(((sign((close - delay(close, 1))) + sign((delay(close, 1) - delay(close, 2)))) +sign((delay(close, 2) - delay(close, 3)))))) * sum(volume, 5)) / sum(volume, 20)) 
    
    def alpha030(self):
        delta_close = delta(self.close, 1)
        inner = sign(delta_close) + sign(delay(delta_close, 1)) + sign(delay(delta_close, 2))
        return ((1.0 - rank(inner)) * ts_sum(self.volume, 5)) / ts_sum(self.volume, 20)

    # alpha031:((rank(rank(rank(decay_linear((-1 * rank(rank(delta(close, 10)))), 10)))) + rank((-1 *delta(close, 3)))) + sign(scale(correlation(adv20, low, 12)))) 
    def alpha031(self):
        adv20 = sma(self.volume, 20)
        df = correlation(adv20, self.low, 12)
        df = df.replace([-np.inf, np.inf], 0).fillna(value=0)
        return ((rank(rank(rank(decay_linear((-1 * rank(rank(delta(self.close, 10)))), 10)))) +
                 rank((-1 * delta(self.close, 3)))) + sign(scale(df)))

    # alpha033: rank((-1 * ((1 - (open / close))^1))) 
    
    def alpha033(self):
        return rank(-1 + (self.open / self.close))
    
    # alpha034: rank(((1 - rank((stddev(returns, 2) / stddev(returns, 5)))) + (1 - rank(delta(close, 1))))) 
    
    def alpha034(self):
        inner = stddev(self.returns, 2) / stddev(self.returns, 5)
        inner = inner.replace([-np.inf, np.inf], 1).fillna(value=1)
        return rank(2 - rank(inner) - rank(delta(self.close, 1)))
    
    # alpha035:((Ts_Rank(volume, 32) * (1 - Ts_Rank(((close + high) - low), 16))) * (1 -Ts_Rank(returns, 32))) 
    
    def alpha035(self):
        return ((ts_rank(self.volume, 32) *
                 (1 - ts_rank(self.close + self.high - self.low, 16))) *
                (1 - ts_rank(self.returns, 32)))

    # alpha037:(rank(correlation(delay((open - close), 1), close, 200)) + rank((open - close))) 
    
    def alpha037(self):
        return rank(correlation(delay(self.open - self.close, 1), self.close, 200)) + rank(self.open - self.close)
    
    # alpha038: ((-1 * rank(Ts_Rank(close, 10))) * rank((close / open))) 
    
    def alpha038(self):
        inner = self.close / self.open
        inner = inner.replace([-np.inf, np.inf], 1).fillna(value=1)
        return -1 * rank(ts_rank(self.open, 10)) * rank(inner)

    # alpha039:((-1 * rank((delta(close, 7) * (1 - rank(decay_linear((volume / adv20), 9)))))) * (1 +rank(sum(returns, 250)))) 

    def alpha039(self):
        adv20 = sma(self.volume, 20)
        return ((-1 * rank(delta(self.close, 7) * (1 - rank(decay_linear(self.volume / adv20, 9))))) *
                (1 + rank(ts_sum(self.returns, 250))))
    
    # alpha040: ((-1 * rank(stddev(high, 10))) * correlation(high, volume, 10)) 
    
    def alpha040(self):
        return -1 * rank(stddev(self.high, 10)) * correlation(self.high, self.volume, 10)

    # alpha43: (ts_rank((volume / adv20), 20) * ts_rank((-1 * delta(close, 7)), 8)) 

    def alpha043(self):
        adv20 = sma(self.volume, 20)
        return ts_rank(self.volume / adv20, 20) * ts_rank((-1 * delta(self.close, 7)), 8)

    # alpha04: (-1 * correlation(high, rank(volume), 5)) 

    def alpha044(self):
        df = correlation(self.high, rank(self.volume), 5)
        df = df.replace([-np.inf, np.inf], 0).fillna(value=0)
        return -1 * df
    
    # alpha045: (-1 * ((rank((sum(delay(close, 5), 20) / 20)) * correlation(close, volume, 2)) *rank(correlation(sum(close, 5), sum(close, 20), 2)))) 
    
    def alpha045(self):
        df = correlation(self.close, self.volume, 2)
        df = df.replace([-np.inf, np.inf], 0).fillna(value=0)
        return -1 * (rank(sma(delay(self.close, 5), 20)) * df *
                     rank(correlation(ts_sum(self.close, 5), ts_sum(self.close, 20), 2)))

    # alpha046: ((0.25 < (((delay(close, 20) - delay(close, 10)) / 10) - ((delay(close, 10) - close) / 10))) ?(-1 * 1) : (((((delay(close, 20) - delay(close, 10)) / 10) - ((delay(close, 10) - close) / 10)) < 0) ? 1 :((-1 * 1) * (close - delay(close, 1))))) 

    def alpha046(self):
        inner = ((delay(self.close, 20) - delay(self.close, 10)) / 10) - ((delay(self.close, 10) - self.close) / 10)
        alpha = (-1 * delta(self.close))
        alpha[inner < 0] = 1
        alpha[inner > 0.25] = -1
        return alpha

    # alpha049:(((((delay(close, 20) - delay(close, 10)) / 10) - ((delay(close, 10) - close) / 10)) < (-1 *0.1)) ? 1 : ((-1 * 1) * (close - delay(close, 1))))

    def alpha049(self):
        inner = (((delay(self.close, 20) - delay(self.close, 10)) / 10) - ((delay(self.close, 10) - self.close) / 10))
        alpha = (-1 * delta(self.close))
        alpha[inner < -0.1] = 1
        return alpha
    
    # alpha051:(((((delay(close, 20) - delay(close, 10)) / 10) - ((delay(close, 10) - close) / 10)) < (-1 *0.05)) ? 1 : ((-1 * 1) * (close - delay(close, 1)))) 
    
    def alpha051(self):
        inner = (((delay(self.close, 20) - delay(self.close, 10)) / 10) - ((delay(self.close, 10) - self.close) / 10))
        alpha = (-1 * delta(self.close))
        alpha[inner < -0.05] = 1
        return alpha

    # alpha052: ((((-1 * ts_min(low, 5)) + delay(ts_min(low, 5), 5)) * rank(((sum(returns, 240) -sum(returns, 20)) / 220))) * ts_rank(volume, 5)) 

    def alpha052(self):
        return (((-1 * delta(ts_min(self.low, 5), 5)) *
                 rank(((ts_sum(self.returns, 240) - ts_sum(self.returns, 20)) / 220))) * ts_rank(self.volume, 5))

    # alpha053:(-1 * delta((((close - low) - (high - close)) / (close - low)), 9)) 

    def alpha053(self):
        inner = (self.close - self.low).replace(0, 0.0001)
        return -1 * delta((((self.close - self.low) - (self.high - self.close)) / inner), 9)

    # alpha054:((-1 * ((low - close) * (open^5))) / ((low - high) * (close^5))) 

    def alpha054(self):
        inner = (self.low - self.high).replace(0, -0.0001)
        return -1 * (self.low - self.close) * (self.open ** 5) / (inner * (self.close ** 5))
        
    # alpha055: (-1 * correlation(rank(((close - ts_min(low, 12)) / (ts_max(high, 12) - ts_min(low,12)))), rank(volume), 6)) 
    
    def alpha055(self):
        divisor = (ts_max(self.high, 12) - ts_min(self.low, 12)).replace(0, 0.0001)
        inner = (self.close - ts_min(self.low, 12)) / (divisor)
        df = correlation(rank(inner), rank(self.volume), 6)
        return -1 * df.replace([-np.inf, np.inf], 0).fillna(value=0)
    
    # alpha060: (0 - (1 * ((2 * scale(rank(((((close - low) - (high - close)) / (high - low)) * volume)))) -scale(rank(ts_argmax(close, 10)))))) 
    
    def alpha060(self):
        divisor = (self.high - self.low).replace(0, 0.0001)
        inner = ((self.close - self.low) - (self.high - self.close)) * self.volume / divisor
        return - ((2 * scale(rank(inner))) - scale(rank(ts_argmax(self.close, 10))))

# 在交易前计算所有股票alpha因子值,取最高的10组进行买入,这里也可以取最低的10组进行卖空操作
def before_trading(context):
    # 获取当前交易日日期
    date=str(context.now)[0:10]
    # 获取10个交易日前信息,根据选取因子所需计算的日期决定
    for i in range(1,10):
        date=get_previous_trading_date(date)
    # 获取股票历史数据
    pn_data=get_price(context.stock, start_date=date, end_date=None, frequency='1d', fields=None, adjust_type='pre', skip_suspended=False)
    # 实例化Alpha对象
    alpha=Alphas(pn_data)  
    # 用户所选取的因子,返回所有股票的该因子值,这里选取001作为示范,用户可修改为其他自己感兴趣的因子
    alpha_use=alpha.alpha002()
    # 取得交易日前一天的因子值
    result=alpha_use.tail(1)
    # 将空值赋为0
    result[np.isnan(result)] = 0
    result=result.T
    # 获取上一交易日日期
    today=str(context.now)[0:10]
    yesterday=get_previous_trading_date(today)
    # 将前一天因子值排序后取出因子值最高的前10只股股票
    stock=result.sort(columns=yesterday,ascending=True)[-5:]
    # 将前一天因子值排序后取出因子值最低的前10只股股票
    stock_short=result.sort(columns=yesterday,ascending=True)[0:10]
    context.short_weight=stock_short.values/sum(stock.values)
    # 计算每只股票的权重,按照因子大小计算权重
    context.weight=stock.values/sum(stock.values)
    # 将选出的股票加入到待买股票池中
    context.stock_pool=stock.index
    # 将选出来的卖空股票加入带卖空股票池
    context.stock_short=stock_short.index
    
def handle_bar(context, bar_dict):
    # 获取权重的计数器
    i=0
    # 获取当前持有股票
    hand_stock=context.portfolio.positions
    # 当前的现金,用于做空时使用,只做多时不考虑
    cash=context.portfolio.cash
    # 当当前持有的股票不在待买股票池中,亦即因子值跌出前10,就清仓。
    # for stock in hand_stock:
    #     if stock not in context.stock_pool:
    #         order_target_percent(stock,0)
    # 买入待买股票池中的股票,买入权重为因子值大小
    for stock in context.stock_pool:
        weight=float(context.weight[i])
        # order_target_value(stock,weight*cash)
        order_target_percent(stock,weight)
        createdic(context,bar_dict,stock)
        i+=1
    # for stock in context.stock_short:
    #     weight=float(context.short_weight[i])
    #     order_target_value(stock,-1*weight*cash)
    #     i+=1

 

 

 

多因子模型系列目录

1.多因子模型系列1-数据预处理之离群值处理
2. 多因子模型系列2-多因子模型的步骤梳理
3. 多因子模型系列3-Fama Franch三因子及其拓展五因子模型
4. 多因子模型系列4-验证Fama French三因子分解的有效性
5. 多因子模型系列5-套利定价模型的应用
6. 多因子模型系列6-沪深300指数的风格因子暴露度分析
7. 多因子模型系列7-多因子模型水平测试题试答
8. 多因子模型系列8-基于组合权重优化的风格中性多因子选股策略框架
当前阅读> 9. 多因子模型系列9-阿里巴巴与101个alpha
10. 多因子模型系列10-因子分析
11. 多因子模型系列11-绩效分析之Brinson模型