因子挖掘之表达式引擎构建:二元滑动计算函数探讨。

01 因子挖掘之因子表达式

图片

因子表达式无外乎四类: 

一元直接计算:比如abs, log; 

二元直接计算的:比如+,-,*,/比大小之类的; 

一元rolling:比如ts_max, delta。

还有就是二元滑动:比如rolling_corr, rolling_std。

最后一种比较麻烦,Pandas原生不支持,或者说性能不好。

gip unary_ops = [Abs, Log]
binary_ops = [Add, Sub, Mul, Div, Greater, Less]
rolling_ops = [Ref, Mean, Sum, Std, Var, Max, Min, Med, Mad, Delta, WMA, EMA]
rolling_binary_ops = [Cov, Corr]

就以最后一种为例:

def rolling_binary(cls, day):
    def _calc(a, b):
        n = len(a)
        return np.array([f'{cls.__name__}({a[i]},{b[i]},{day})' for i in range(n)])
    return _calc

这里的计算函数,按最后一个维度展开,其实类似group_by_symbol

因为数据是三维叠加的。

昨天在群里和星友们讨论的问题——qlib支持不支持截面,但有同学说DeepAlpha是支持的呀,应该它把所有数据搁到一起了。——不好意思,这种方式,仍然不支持截面,比如rank(a)

class RollingOperator(Operator):
    def __init__(self, operand: Union[Expression, float], delta_time: Union[int, DeltaTime]) -> None:
        self._operand = operand if isinstance(operand, Expression) else Constant(operand)
        if isinstance(delta_time, DeltaTime):
            delta_time = delta_time._delta_time
        self._delta_time = delta_time

    @classmethod
    def n_args(cls) -> int: return 2

    @classmethod
    def category_type(cls) -> Type['Operator']: return RollingOperator

    def evaluate(self, data: StockData, period: slice = slice(0, 1)) -> Tensor:
        start = period.start - self._delta_time + 1
        stop = period.stop
        # L: period length (requested time window length)
        # W: window length (dt for rolling)
        # S: stock count
        values = self._operand.evaluate(data, slice(start, stop))   # (L+W-1, S)
        values = values.unfold(0, self._delta_time, 1)              # (L, S, W)
        return self._apply(values)

三维矩阵来存储数据,不直观还容易出错。

因此,咱们的因子表达式使用group by symbol和 group by symbol统一的范式,清晰简单。

WorldQuant101的3号因子,只要使用rank(open)和rank(volume)求相关系数,结果都是None。

我检查过,如果计算correlation(open,volume)是没有问题的,说明计算函数correlation没有问题——这里怀疑是rank后数值太相近??

# Alpha#3: (-1 * correlation(rank(open), rank(volume), 10))
se = calc_expr(df, expr='(-1 * correlation(rank(open), rank(volume), 10))')
df['alpha_03'] = se

另外一个点,

series_left.rolling(10).corr(right)可以实现两个序列的滑动相关计算,但这里不支持自定义函数,比如计算rsrs, numpy的内置函数是可以的(这里有认知的同学,欢迎留言探讨)

@calc_by_symbol
def correlation(left: pd.Series, right: pd.Series, periods=20):
    #es: pd.Series = pd.Series(index=left.index)

  res = left.rolling(window=periods).corr(right)
    #left.rolling(window=periods).apply(func=func,right)
    res.loc[
        np.isclose(left.rolling(periods, min_periods=1).std(), 0, atol=2e-05)
        | np.isclose(right.rolling(periods, min_periods=1).std(), 0, atol=2e-05)
        ] = np.nan
    return res

吾日三省吾身

什么算“躬身入局”?

做一款产品,一定要自己写代码才算吗?

这个显然不是,至少一款成功的产品,它的核心是用户需求与商业模式。

之所以问这个问题,是想起来,有一群比较成功的自媒体人,他们写的东西关于个人成长,比如彭小六。

他读了很多书以后,书的内容本身“并没有起作用”,而是开始教大家读书的方法。

还有另外一个兄弟,坚持学习外语,然后有所悟,他甚至不是教大家学外语,而是教大家“坚持的方法论”。

国际时事分析,对于多数人,就是茶余饭后的谈资,当然,你说做全球化的二级市场投资,关注一下黄金和国际油价的影响因素倒有可能。

芒格说:“宏观是我们必须承受的,而微观才是我们有所作为的”。

必须承受的大势,更应该了解并顺势而为。可以有所作为的微观,就是躬身入局。

所谓“抬头看天,低走走路”。

路只能自己走。

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/103411
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 2024 年 7 月 29 日
下一篇 2024 年 7 月 29 日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注