菜鸟de量化之路——(1)趋势跟踪策略

这是我第一篇博客,也是我的本科毕业课题--开发一个简易的量化系统,包括择时选股模块和回测模块。

所谓的量化系统,是指以数学模型代替人为判断,以程序交易替代人为操作,利用计算机的庞大的计算能力,制定能带来超额收益的交易策略。

由于之前没有开发相关系统的经验,我决定先从一个开源的量化系统开始学习,以python作为主要开发语言,同时学习python和量化知识。我选择阿布量化系统作为开发模板,学习配套书籍量化交易之路。Github地址:https://github.com/bbfamily/abu 这一系列笔记将从书本第七章量化系统入门开始,学习书上所有的例程。

趋势跟踪策略

趋势跟踪模型是大名鼎鼎的海归交易法则里面提到的一个经典量化模型,基本的策略是在一个上扬趋势刚刚开始的时候买入,在这个趋势即将结束之前退出系统。

首先我们选取苹果的历史两年股票数据作为数据来源:

from abupy import ABuSymbolPd
Apple_pd = ABuSymbolPd.make_kl_df('AAPL', n_folds=2)
Apple_pd.tail()

通过Apple_pd.tail()查看股票的数据结构和尾部数据如下图,可以看到包括close, high, low, p_change, open, pre_close,volume, date, date_week, key,atr21,atr14 等列 ,我们目前主要需要的是开盘价,最高价,最低价,收盘价,振幅的数据。

菜鸟de量化之路——(1)趋势跟踪策略

接下来使用seaborn库画出可视化的振幅变化图:

sns.set_context(rc={'figure.figzize':(14,7)})
sns.regplot(x=np.arange(0, Apple_pd.shape[0]),y=Apple_pd.close.values,marker='+')
plt.show()

菜鸟de量化之路——(1)趋势跟踪策略

下面使用abu内置的函数计算趋势角度方向:

start = 0
# 前1/4的数据
end = int(Apple_pd.shape[0] / 4)
# 将x也使用arange切割
x = np.arange(start, end)
# y根据start,end进行切片
y = Apple_pd.close.values[start:end]
sns.regplot(x=x, y=y, marker='+')
plt.show()
deg = ABuRegUtil.calc_regress_deg(y)
print('趋势角度:' + str(deg))

得到下面的结果,可以看出前四分之一的股价呈现明显的上升趋势,且趋势角度为8.98:

菜鸟de量化之路——(1)趋势跟踪策略

 

菜鸟de量化之路——(1)趋势跟踪策略

 

经过初步分析,对这一段的数据,可以使用趋势跟踪策略,下面编写一个简单的趋势跟踪策略模型,趋势跟踪模型的两个参数是买入信号和卖出信号的确定,当天的收盘价格超过N天的最高价格作为买入持有信号,收盘价格低于N天的最低价格作为卖出抛售信号。首先设置42天的最高价格和21天的最低价格作为阈值,设置两个不同的阈值主要是为了保证非均衡的胜负收益。

# 当天收盘价格超过N1天内最高价格作为买入信号 
N1 = 42
# 当天收盘价格超过N2天内最低价格作为卖出信号
N2 = 21
# 通过rolling_max方法计算最近N1个交易日的最高价
from abupy import pd_rolling_max,pd_expanding_max,pd_rolling_min, pd_expanding_min
Apple_pd['n1_high'] = pd_rolling_max(Apple_pd['high'], window=N1)
expan_max = pd_expanding_max(Apple_pd['close']) 
# fillna使用序列对应的expan_max
Apple_pd['n1_high'].fillna(value=expan_max, inplace=True)
Apple_pd['n2_low'] = pd_rolling_min(Apple_pd['low'], window=N2)
# expanding_min与expanding_max类似
expan_min = pd_expanding_min(Apple_pd['close'])
# fillna使用序列对应的eexpan_min
Apple_pd['n2_low'].fillna(value=expan_min, inplace=True)
# 当天收盘价格超过N天内的最高价或最低价, 超过最高价格作为买入信号买入股票持有 
buy_index = Apple_pd[Apple_pd['close'] > Apple_pd['n1_high'].shift(1)].index
Apple_pd.loc[buy_index, 'signal'] = 1

# 当天收盘价格超过N天内的最高价或最低价, 超过最低价格作为卖出信号
sell_index = Apple_pd[Apple_pd['close'] < Apple_pd['n2_low'].shift(1)].index
Apple_pd.loc[sell_index, 'signal'] = 0

Apple_pd[0:5]

得到扩展后的新的股票数据:

菜鸟de量化之路——(1)趋势跟踪策略

接下来将操作信号转化成持股状态,计算基准收益,计算使用趋势突破策略的收益之后可视化收益情况:

"""
    将信号操作序列移动一个单位,代表第二天再将操作信号执行,转换得到持股状态
    这里不shift(1)也可以,代表信号产生当天执行,但是由于收盘价格是在收盘后
    才确定的,计算突破使用了收盘价格,所以使用shift(1)更接近真实情况
"""
Apple_pd['keep'] = Apple_pd['signal'].shift(1)
Apple_pd['keep'].fillna(method='ffill', inplace=True)

# 计算基准收益
Apple_pd['benchmark_profit'] = np.log(
    Apple_pd['close'] / Apple_pd['close'].shift(1))

# 计算使用趋势突破策略的收益
Apple_pd['trend_profit'] = Apple_pd['keep'] * Apple_pd['benchmark_profit']

# 可视化收益的情况对比
Apple_pd[['benchmark_profit', 'trend_profit']].cumsum().plot(grid=True,
                                                          figsize=(
                                                          14, 7));

得到如下的结果:

菜鸟de量化之路——(1)趋势跟踪策略

 可以看出使用趋跟踪策略的盈利率略微高于benchmark值,但是还是处于负收益率期间,主要原因是测试数据整个阶段的股价处于下降阶段,仅仅一个趋势跟踪策略并不能违反市场盈利情况。

总结

一个单一的策略往往适用范围有限,考虑到股价在不同的阶段可能会处于不同的波动类型,如果能有更高级的策略模型用来判断股价的基本类型,从而对于不同的变化类型使用不同的子策略,可能会有不错的效果。Numpy, Pandas,Matplotlib, Seaborn是常用于Python量化系统的库,需要大量练习,重点掌握。