咱们有了策略向导,写策略就特别快了。
今天来复现的策略是一个经典的——大小盘趋势轮动策略。
沪深300代表的大盘与创业板代表的小盘之间,按动量来轮动。
直接信号轮动的效果:
过滤掉负的动量:
动量小于零的时候,平仓,收益率和最大回撤均得到改善。
再优化进场信号——在动量大于0.02的时候才进场,为负的时候离场:
年化进一步提升至19.7%,这样一个策略就完成了。
我们发布到服务器:
这些代码在本周五都会在星球更新:
本周一个任务主线是——重构Deap因子挖掘系统。
商品期货池:我们从国内期货市场筛选出历史流动性较好的41个品种具体如下表所示。
41个商品期货主连合约,我整理到咱们平台上了:
然后直接做单因子分析,用动量先看看:
单调性很好——但是是动量越大,收益越小。
看下分层收益:
IC上也得到印证——期货截面20日动量与收益率呈现负相关,因此我们只需要设计一个策略,买入动量最小的,卖空动量最大的即可:
回测区间:我们使用2016/1/1-2022/1/1作为样本内训练集,2022/1/2-2023/3/10作为样本外测试集,总回测区间为2016/1/1-2023/3/10。
算子函数集——也就是咱们的因子表达式引擎里提供的,这里才是因子挖掘的核心——因为无论是deap还是gplearn,框架本身你会使用就可以了。
这些函数的实现在这里:
代码都不复杂:
import numpy as np import pandas as pd from .expr_utils import calc_by_symbol, calc_by_date @calc_by_symbol def ts_delay(se: pd.Series, periods=5): # 滞后N天的序列 return se.shift(periods=periods) @calc_by_symbol def ts_delta(se: pd.Series, periods=20): # 当前序列与滞后N天之差 se_result = se - se.shift(periods=periods) return se_result @calc_by_symbol def ts_mean(se: pd.Series, d): return se.rolling(window=d).mean() @calc_by_symbol def ts_median(se: pd.Series, d): return se.rolling(window=d).median() @calc_by_symbol def ts_min(se: pd.Series, periods=5): return se.rolling(window=periods).min() @calc_by_symbol def ts_max(se: pd.Series, periods=5): return se.rolling(window=periods).max() @calc_by_symbol def ts_sum(se: pd.Series, N): ret = se.rolling(N).sum() return ret @calc_by_symbol def ts_argmin(se: pd.Series, periods=5): return se.rolling(periods, min_periods=2).apply(lambda x: x.argmin()) @calc_by_symbol def ts_argmax(se: pd.Series, periods=5): return se.rolling(periods, min_periods=2).apply(lambda x: x.argmax()) @calc_by_symbol def stddev(se, periods=5): return se.rolling(window=periods).std() @calc_by_symbol def ts_rank(se: pd.Series, periods=9): ret = se.rolling(window=periods).rank(pct=True) return ret @calc_by_symbol def shift(se: pd.Series, N): return se.shift(N) @calc_by_symbol def roc(se: pd.Series, N): return se / shift(se, N) - 1 @calc_by_symbol def ts_product(se: pd.Series, d): return se.rolling(window=d).apply(np.product) @calc_by_symbol def zscore(se: pd.Series, N): def _zscore(x): try: x.dropna(inplace=True) # print('sub', x) value = (x[-1] - x.mean()) / x.std() if value: return value except: return -1 # print(se) ret = se.rolling(window=N).apply(lambda x: _zscore(x)) return ret def decay_linear(series, window): """ 对输入的时间序列进行线性衰减。 :param series: 输入的时间序列。 :param window: 衰减的窗口大小。 :return: 衰减后的序列。 """ weights = np.arange(1, window + 1) decay = np.convolve(series, weights, 'valid') / np.sum(weights) return decay
绝大多数算子,无论是时序,还是截面,都可以通过封装numpy来完成,不过技术分析类的,还是只能通过Talib这样的技术指标库。
pandas_ta实现一个指标——不过pandas_ta似乎有bug,numpy版本不兼容:
import pandas_ta as ta @calc_by_symbol def ts_dema(X, d): ret = ta.dema(X, d) if ret is None: return pd.Series(None, index=X.index)
这些都准备好之后,因子挖掘就是使用框架的问题了,只是框架目前没有现成的、适用于因子挖掘的。
因此,我会为大家提供重写后的版本,本周是deap,下周也许会重写gplearn。
吾日三省吾身
“懂那么多道理,却过不好这一生“。
知道到做到,还有千山万水。
财富自由快车道,从需求出发,用户在抱怨什么。
比如大家急需要策略,要因子,想知道如何挖掘因子,这就是刚需。
有些用户想要实盘,自动化交易等等。
一个反馈系统非常关键。
把事情做精,把点打透,才能产生价值。
点子不重要,点子的执行才重要,直接解决问题。
发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/134177
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!