还在买白酒?算法工程师们,量化投资了解一下

文 | 阿财@知乎 

本文已获作者授权,禁止二次转载

赚取你认知中的Alpha

坚持用量化的观点去看待宇宙的终极问题:买不买,卖不卖。

很多人的在互联网这一片方寸之地,表现出来的行为是矛盾的。举个例子,相信技术指标在交易实践毫无用处的人(前面几篇文章里评论者不乏这样的观点)应该不会看知乎上讨论和教学量化的文章,他们就坚持主观交易就好了,否则拿什么东西去量化因子,基本面因子都算是广义上的技术指标。

量化交易者必须不能行为和认知产生割裂,很多人不明白,割裂了做不成量化,量化的过程其实就是:你本人价值观 ——> 选择策略方式 ——> 发掘因子 ——> 程序代码 进行拟合的过程,所以必须 想法和行为合一,就是很多人爱挂在嘴边的所谓的知行合一

其实他们的知行并不合一,因为成人的世界非黑即白的,所以我们应该明白几点:

策略反映价值观,什么人选择什么策略,是他们价值观的体现。

既然是价值观体现,那么就没有所谓的绝对高下之分,也没有什么绝对的有效无效之分,它们必然有适合的市场和适合的时间段,不要去随便用特警判官式的口吻居高临下的评判别人的策略不行。

总有初学者压根不知道自己是什么价值观,或者价值观都尚未成型,瞎胡抄别人的策略咋呼。这种行为是没用的,不是自己的认知赚来的钱,长久以往,他们的盈利最终会输回去。

认知体现了你的价值观,价值观会投射到你的量化交易策略上。没有自己认知的拿来主义的策略,是无法做演绎和迭代进化的。最终你会在连续的亏损迷茫和怀疑,在时间漫漫的推移中抄来的Alpha也就会钝化和失效。

程序员都应该看过《人月神话》,人力有时穷,个人无法做完全部的idea,你要设定一个计划,做自己的因子搜集,测试,优先级,能做的策略太多了,不可能全做。个人精力有限,比如我就放弃了基本面,用编制指数的金融专家帮我选股票基本面的方式圈定股票池。

别听任何大V跟你讲什么交易心态的鸡汤,最多讲一个月他就会转移话题到拉群——贵金属交易所开户的正路上面了。交易靠心态的话,迟早要还回去,因为人的心态是不稳定的,女性性格缺陷中有大姨妈周期,男性普遍的性格缺陷是男性易有阿斯(比女性高4倍),双向情感障碍和躁郁症。从医学统计上,有着各种各样心理问题的可以达到人群中总数的35%以上。而且性格缺陷几乎无解,心理医生,精神科都解决不了,无论是双相还是,吃药也只能维持不能根治。

一个人母胎性格说白了是天生的。如果要靠天吃饭的老天赏个好心态才能解决交易一致性问题,那交易员岂不是比天赋异禀的刘翔还稀少?那大家都只能喝西北风去了。

所以在做交易之前,先确定你的对交易的认知,钱从哪里,怎么赚到的钱,赚钱以后想干什么,把它们都写进程序里。而交易的一致性,靠的是程序,程序,程序;交易的确定性,来自于是回测统计和贝叶斯公式。

所以我可以在这里放肆的交底牌——我的量化策略来自于我的认知,也正是因为这个原因,我可以很大方的公开出来,因为不信的人就是不会信,他看不进去,这不属于他的认知,也就不用担心他会偷走我的策略,分享我的Alpha。

波浪理论

这只是我对量化投资的认知,你可以去寻找你的圣杯去。

波浪理论是证券技术分析的主要理论之一,由美国经济学家艾略特提出。一些交易员用以分析金融市场周期,预测市场趋势。拉尔夫·纳尔逊·艾略特,专业会计师,于1930年提出分析方法,认为市场价格的走势具有特定的形态。

艾略特波浪理论:
(https://zh.wikipedia.org/wiki/%E8%89%BE%E7%95%A5%E7%89%B9%E6%B3%A2%E6%B5%AA%E7%90%86%E8%AE%BA)

波浪理论更实践化和具象化的交易指导思想就是道氏理论和缠论。不是我刻意引流,但是只要稍微研究深入一点,你总会发觉缠论就在不远处向你招手,是回避不掉的。

教你炒股票1:不会赢钱的经济人,只是废人!
(http://blog.sina.com.cn/s/blog_486e105c01000461.html)

当然我对缠论持一种“酒肉穿肠过,佛主留心中”白目状态:我知道它但我不钻研它,也不妨碍我运用它。因为只要找到合适的程序代码,自己改好成适配自己的量化平台用的就行,原理我理解,所以实践中能知道这个程序代码是不是工作正确,这就够了。

任何钻研缠论的尝试很容易导致“辩经”心态,这种现象这在知乎缠论话题下的讨论中似乎极为常见。我认为这对我们推进量化交易学习进度是不利的,因为一个35岁程序员兼职做量化的时间并不算多到能拿来挥霍的程度,在某乎跟人讨论缠论“辩经”辨赢了,并不能赚到钱的。

我目前使用的缠论笔段分割代码:
(https://github.com/zengbin93/czsc/github.com)

ARIAM模型

证券市场是周期性重复的,也就是恒沙一样无数的贪婪和人性,左右了市场的波动行动,最终导致了历史总会一遍又一遍的重演。

时间序列中的预测模型是什么?
预测涉及使用其历史数据点预测变量的值,或者还可以涉及在给定另一个变量的值的变化的情况下预测一个变量的变化。预测方法主要分为定性预测和定量预测。时间序列预测属于定量预测的范畴,其中统计原理和概念应用于变量的给定历史数据以预测同一变量的未来值。使用的一些时间序列预测技术包括:

自回归模型(AR)
移动平均模型(MA)
季节回归模型
分布式滞后模型

如何通俗易懂地解释ARIMA模型:
(https://pic3.zhimg.com/v2-f2b41a923772474e80bb5955b33d9fd6_180x120.jpg)

这个知识点只需要了解就好了,因为根据实战应用,它明显没有后面的一次九项式灵光。它只是帮助我们验证一点:股票走势行情是周期性的,人性撰写的历史是一再重演的

周期分解算法

接上面的ARIAM模型,事实上我们只要稍加实践,就会发现ARIAM模型在股票的走势周期预测中拟合效果不好,为什么呢?它的分解级别不够,它只是进行了一次差分计算,事实上,股票在走势行情中大约包含了7~17个不同周期级别的分量信号。所以我们需要探索更多更有效的数学和算法途径。

信号与系统取巧的方法——EEMD经验模态分解

Mr.括号:这篇文章能让你明白经验模态分解(EMD)——基础理论篇:
(https://pic3.zhimg.com/v2-983c8b1d17943f33cb7a4fc6e5e3d942_180x120.jpg)

实践出真知,我拿沪深300指数作为范例,使用EEMD分解它的多次信号分量。

Python 代码如下,我使用CCI进行分解而不是收盘价是因为长期主升浪的股票在单边走势中,起始点和最近日期和价格差距超过2倍以上,级别差距过大,会影响到分解指标判断。

# python 实现对沪深300的 EEMD分解 解析出不同级别的自回归周期频率
import numpy as np
from PyEMD import EEMD, EMD, Visualisation
import pylab as plt

from GolemQ.fetch.kline import (
    get_kline_price,
    get_kline_price_min,
)
from GolemQ.fractal.v0 import (
    maxfactor_cross_v2_func,
)
from GolemQ.utils.parameter import (
    AKA, 
    INDICATOR_FIELD as FLD, 
    TREND_STATUS as ST,
    FEATURES as FTR,
)

if __name__ == "__main__":
    kline, display_name = get_kline_price_min('399300', frequency='60min',)
    features = maxfactor_cross_v2_func(kline.data)

    max_imf = 17
    S = features['CCI'].dropna().tail(480).values
    T = range(len(S))

    # EEMD计算
    eemd = EEMD()
    eemd.trials = 50
    eemd.noise_seed(12345)

    E_IMFs = eemd.eemd(S, T, max_imf)
    imfNo = E_IMFs.shape[0]
    tMin, tMax = np.min(T), np.max(T)

    # Plot results in a grid
    c = np.floor(np.sqrt(imfNo + 1))
    r = np.ceil((imfNo + 1) / c)

    plt.ioff()
    plt.subplot(r, c, 1)
    plt.plot(T, S, 'r')
    plt.xlim((tMin, tMax))
    plt.title("399300.XSHE:CCI(14)")

    for num in range(imfNo):
        plt.subplot(r, c, num + 2)
        plt.plot(T, E_IMFs[num], 'g')
        plt.xlim((tMin, tMax))
        plt.title("Imf " + str(num + 1))

    plt.show()

运行程序,实际上EEMD算法有个缺点:跟K-Means聚类和隐马尔科夫链HMM算法很像,就是它管分解,但是不管标注或者理解具体模态的含义。

模态的含义(代表主次,涨跌)必须程序员再次处理数据进行解读,在自动分解出来的结果中,我们还需要写更多的代码匹配出我们的“主级别”周期和当前周期。但是因为实践中并没有使用这个算法,我就不再列出曾经写过的主级别和当前周期适配代码了。

第二个缺点——跟小波分析,聚类分析一样,未来信息会反向传播,前面一篇文章中提到的时候已经有网友评论说小波分解和EEMD分解的这个缺陷有专有叫法叫“端点漂移”(因为我一切自己研究,所以叫法有时会自创不同)。时移窗口会发生抖动,但是不影响对波浪所处相位象限区间和趋势判断。但是这终究是不好的。所以EEMD经验模态分解我在量化交易中仅作为理论研究使用。EEMD算法再一次帮助我们验证一点:股票走势行情是周期性的,人性撰写的历史是一再重演的

最终我真正量化交易实践中运用的周期分解方法为

一次九项式拟合

本技巧的原始出处:
唐进民:多项式曲线拟合
(https://pic3.zhimg.com/v2-96702fac9fbdefb7d93aef386ee4d236_ipico.jpg)

这里使用了一个技巧就是滚动窗口计算。

直接上代码。

def strided_app(a, L, S):  
    '''
    Pandas rolling for numpy
    # Window len = L, Stride len/stepsize = S
    '''
    nrows = ((a.size - L) // S) + 1
    n = a.strides[0]
    return np.lib.stride_tricks.as_strided(a, shape=(nrows,L), strides=(S * n,n))

def rolling_poly9(s:np.ndarray, w:int=252) -> np.ndarray:
    '''
    一次九项式滚动分解拟合
    '''
    x_index = range(252)
    def last_poly9(sx):
        p = np.polynomial.Chebyshev.fit(x_index, sx, 9)
        return p(x_index)[-1]

    if (len(s) > w):
        x = strided_app(s, w, 1)
        return np.r_[np.full(w - 1, np.nan), 
                     np.array(list(map(last_poly9, x)))]
    else:
        x_index = range(len(s))
        p = np.polynomial.Chebyshev.fit(x_index, s, 9)
        y_fit_n = p(x_index)
        return y_fit_n

# 用法示例
features['POLYNOMIAL9'] = rolling_poly9(features['HMA10'].values, 252)

通过一次九项式拟合,策略代码自发性的寻找到周期规律——如果对象标的存在不符合周期性波动的规律(例如政策性很强的黄金股,纸黄金ETF),那么会在拟合中出现一种奇特的 ”与K线价格走势,HMA10相关性偏低的现象“。

通过核验特定指标的相关性,我就可以判断这个标的适合或者不适合我的量化策略进行交易。同样生效的算法还包括 最小递增序列的OLS线性拟合和回归树转折点算法,它们的组合,我称为:”咸鱼(波动性很差的股票)检测算法“。关于实现这种1秒钟判断一个,5分钟就可以从1700个超大股票池中判断“咸鱼”,“弱势”,“持有”,“做多”,“做空”的Python代码,我后面会写专文讨论。

就像这样

print(u'分析和展示计算结果...')
ret_codelist = featurs_printable_formatter(ret_codelist)
codelist_saltedfish, ret_codelist_saltedfish, ret_codelist = find_fratcal_saltfish(ret_codelist)
codelist_combo, ret_codelist_combo, ret_codelist = find_fratcal_bootstrap_combo(ret_codelist)
codelist_action, ret_codelist_action, ret_codelist_combo = find_action_long(ret_codelist_combo)
codelist_weak, ret_codelist_weak, ret_codelist = find_fratcal_weakshort(ret_codelist)
codelist_short, ret_codelist_short, ret_codelist_unknown = find_action_sellshort(ret_codelist)
#codelist_hyper_punch, ret_stocklist_hyper_punch, ret_codelist =
#find_action_hyper_punch(ret_codelist)
codelist_unknown = [index[1] for index, symbol in ret_codelist_unknown.iterrows()]

# 将计算的标的分成四类 —— 买入判断'buy',持有判断'long',做空判断'short',
# 'slatfish'是垃圾咸鱼票,既没有价格波动性也没有想象空间
if (eval_range in ['etf', 'csindex']):
    full_etf_list = perpar_symbol_range('etf')
    full_csindex_list = perpar_symbol_range('csindex')
    ret_codelist = ret_features_pd.loc[(each_day[-1], slice(None)), :].copy()
    symbol_list = ret_codelist.index.get_level_values(level=1).unique()
    symbol_list_grouped = [(symbol, 'etf') for symbol in list(set(symbol_list).interp(set(full_etf_list)))] + \
                            [(symbol, 'csindex') for symbol in list(set(symbol_list).interp(set(full_csindex_list)))]
    if (eval_range in ['etf']):
        symbol_list_grouped = [(symbol, 'etf') for symbol in symbol_list]
    elif (eval_range in ['csindex']):
        symbol_list_grouped = [(symbol, 'csindex') for symbol in symbol_list]
    symbol_list_grouped = list(set(symbol_list_grouped))
else:
    symbol_list_grouped = [(symbol, 'buy') for symbol in codelist_action] + \
                          [(symbol, 'long') for symbol in list(set(codelist_combo).difference(set(codelist_action)))] + \
                          [(symbol, 'weak') for symbol in codelist_weak] + \
                          [(symbol, 'short') for symbol in codelist_short] + \
                          [(symbol, 'saltedfish') for symbol in codelist_saltedfish] + \
                          [(symbol, 'unknown') for symbol in codelist_unknown]

经过它们快速分类。

后台回复关键词【入群

加入卖萌屋NLP/IR/Rec与求职讨论群

后台回复关键词【顶会

获取ACL、CIKM等各大顶会论文集!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值