一、问题简述
在此作业中,我们致力于开发一个股票交易模型,它的主要流程为:
- 对股票的价格和交易数据进行适当的标记,并打上买卖动作的标签。
- 插入具体的特征,用以更好解释标签。
- 采用合适的方法训练模型。
- 使用机器学习的输出对当前为止的价格数据做出买入、卖出、不做动作的预测。
- 最后反馈模型的利润率、最大回撤、夏普指数、交易次数等详细信息。
二、特征选取
1. 布林线
布林线指标(Bollinger Bands),主要利用统计原理,求出股价的移动平均值、标准差及其信赖区间,从而确定股价的波动范围及未来走势,利用波带显示股价的安全高低价位。
布林线指标属于路径指标,股价波动在上限和下限的区间之内,这条带状区的宽窄,随着股价波动幅度的大小而变化,股价涨跌幅度加大时,带状区变宽,涨跌幅度狭小盘整时,带状区则变窄。
布林线Python上可由以下代码实现:
1 | import talib as ta |
其中的UP、MD、DN分别表示上、中、下轨线。
2. CCI
CCI(Commodity Channel Index)指标又叫顺势指标,是一种专门测量股价或外汇是否已超出常态分布范围的指标。
CCI指标属于超买超卖类指标中较为特殊的一种,波动在正无穷大和负无穷大之间,但又不需要以0为中轴线。因此CCI不会出现指标钝化现象,有利于投资者更好地研判行情,特别是那些短期内暴涨暴跌的非常态行情。这对于我们在股票市场上追涨杀跌、短期获得较高收益率由较大的帮助。
布林线Python上可由以下代码实现:
1 | import talib as ta |
3. 其他特征:MTM、涨停与复权
股票的动量指标MTM当主要通过前价格和一段时间前的价格,或对比开盘价与收盘价的高低,来判断股票价格走势的强弱和方向。MTM指标可以用来发现股票价格趋势的转折点,也可以用来确认价格趋势的持续性。当MTM指标从上升转为下降时,可能意味着股票价格即将出现下跌趋势;当MTM指标从下降转为上升时,可能意味着股票价格即将出现上涨趋势。
股票涨停是指为了减少股市交易的投机行为,规定每个股票每个交易日的涨跌幅度,达到上涨上限幅度的就叫涨停。中国股市每个交易日涨跌限幅为**10%**。股票看到有涨停势头时尽快买入,增长势头减弱时卖出,可以快速增加手里持有的现金量。
股票复权是指当股价因送股、配股等原因而发生下跌时,股价瞬间变为原来的二分之一或者三分之一等,但该股票实际价值并没有发生变化。我们的测试数据没有直接看出股票是否发生复权的指标,但是复权的发生不会影响股票原有的走势。对于股票复权,Adj Close可以作为间接的判断依据之一。
三、标签插入
1. 布林线
布林线的绘制可以帮助我们判断股票的走势,从而确定买卖情况:
- BOLL指标中的上、中、下轨线所形成的价格通道的移动范围是不确定的,在正常情况下,市场价格应始终处于价格通道内运行。如果市场价格脱离价格通道运行,则意味着行情处于极端的状态下;
- 当布林线的上、中、下轨线同时向上运行时,表明市场强势特征非常明显,短期内将继续上涨,应坚决持股做多。反之则表明市场的弱势特征非常明显,短期内将继续下跌,投资者应坚决做空;
- 当布林线的上轨线向下运行,中轨线和下轨线向上运行时,表明市场处于整理态势之中。如果市场是处于长期上升趋势时,则表明市场是上涨途中的强势整理;如果市场是处于长期下跌趋势时,则表明市场是下跌途中的弱势整理。
同时,对于布林线自身的研判也有一定的标准:
- 当股价穿越上轨线(动态上限压力线,静态最上压力线BOLB1)时,为卖点信号;
- 当股价穿越下轨线(动态下限支撑线,静态最下支撑线BOLB4)时,为买点信号;
- 当股价由下向上穿越中界线(静态从BOLB4穿越BOLB3)时,为加码信号;
- 当股价由上向下穿越中界线(静态由BOLB1穿越BOLB2)时,为卖出信号。
基于以上标准我们确定了买卖标志的BOLL定量模型:
1 | df['BOLL_last'] = df['BOLL'].shift(1) |
其中的正向信号表示买入,负向信号表示卖出,而值的多少(通常为0.5或者1.0)表示了买入信号的强烈与否。例如1.0的指标表示建议将所有现金梭哈股市;-0.5的指标则是建议卖出一半的股票转为流动资本。后续的信号系统与此一致。
2. CCI
CCI指标在+100线(也叫天线)~ -100线(也叫地线)的常态区间里运行时,参考意义不大,可以用布林线等其它技术指标进行研判。(这也意味着我们确定权重时的先后顺序)
但CCI指标穿过两条标准线(+100线和-100线)时,意味着我们需要进行适当的买卖操作了:
- 当CCI自常态行情由下往上突破+100天线时为短线追涨抢进时机;
- 而当CCI由上往下跌破-100地线时为痛打落水狗的卖空杀跌时机;
- CCI由下往上突破-100地线为空头回补短线的买进时机;
- CCI从+100天线由上往下跌破天线,可以卖出止赢。
此外,CCI指标还有其他可以作为买卖标准的判断方式,但由于专业性过强、有一定主观判断的因素、缺乏合适的定性标准,因此我们未予采纳。
基于以上标准我们确定了买卖标志的CCI定量模型:
1 | df['CCI_last'] = df['CCI'].shift(1) |
3. 其他指标
MTM、涨停、复权等定性指标对于股票买卖策略的计算有着重要作用,但在机器学习的过程中表现欠佳,且该信号往往快速强烈,可以直接算出或用Pyalgotrade计算得出,因此不需要再进行机器学习的标签标记和模拟训练。
四、机器学习
1. 模型构建
对于特征提取和标签插入,尽管我们计算了各项指标,但是我们最终得到的还是取值从-1到+1的“推荐买卖量”。其中全买为+1,全卖为-1。为了加权计算得出买卖股票的量,我们加入了“推荐股票持有量”来进行计算。具体的计算步骤为:
- 计算各指标的推荐买卖程度;
- 计算各指标推荐您现在持有股票的量;
- 根据权重和优先级计算加权平均推荐股票持有量;
- 计算推荐您买卖的量(一阶差分)。
而从“推荐买卖量”到“推荐持有量”在交易策略中以函数Sig2sig(self, dataframe, column_name, new_column_name)
实现。
在特征提取和标签插入的过程中,我们按照MTM->涨停复权->BOLL->CCI的先后顺序(优先级)来处理股票的各项指标。具体计算方法在模型文件MyModel.ipynb(代码块14)与交易文件MyStrategy.py(函数onBars(self, bars)
)中都有所体现。
2. 模型优化
与样例文件不同,我们的模型本质上属于多分类问题,在测试极度随机树、逻辑回归、K近邻等分类模型之后,我们最终选择了支持向量机(SVM)进行分类和预测。多类分类器采用间接法,二分类器选择one-versus-one(ovo),核函数选择径向基函数(radial basis function)。Python代码如下:
1 | from sklearn import svm |
我们将训练完的模型保存在了文件“mystock.pkl”中。由于模型是多分类且包含较多主客观杂糅的因素,我们模型的accuracy为72%。具体分类评价报告为:
1 | precision recall f1-score support |
此外,对于真实股票交易中可能出现的诸多状况,我们也在具体实现的过程中进行了模拟和优化:
- 交易过量问题。在模拟交易的过程中,可能由于自身持有资金的量过大或股价过低,而同时机器学习模型又强烈推荐购入股票(例如连续涨停)。此时的预期交易量可能大于股票的每日交易量,Pyalgotrade会产生以下报错:为了避免以上情况的产生,最佳的策略就是减少交易量。简化起见,我们对此提出了动态交易策略。亦即当手中资金较多时,对推荐的交易量乘一个交易乘数,来控制交易量,保证买入和卖出股票的量都在可控的区间内。同时我们还会将交易量与过去10天的指数平均交易量进行对比,动态改变交易策略,防止出现超量交易或“Invalid quantity”等报错。
1
201X-XX-XX 00:00:00 broker.backtesting [DEBUG] Not enough volume to fill stockXX market order [XX] for XXXX share/s
- 负交易量问题。Pyalgotrade允许股票的做空与现金的贷款,因此在买卖的过程中偶尔会有“负现金”和“负股数”的出现(这种问题也通常是由上述的交易过量导致失控而产生)。但买入股票(enterLong函数)和卖出股票(enterShort函数)均不允许负交易量,因此在发生这种特殊情况时,我们将不按照预测结果,而是直接买入稍多余手中做空股票的数量(或卖出约等于手中贷款的股票)保证二者都在正区间。
尽管精确度并不是极其准确,但在最终交易标志signal_FINAL的正负号的预测上,准确率可以达到100%,因此对于预测股票的买卖操作可以起到较强的指导和推荐作用。同时,其他对于交易模型的优化也保证了交易的可靠性。
五、测试结果
对于真实的股票数据,模型取得了较好的测试结果。对于用作测试集的股票都取得了较好的效果。
利润率(%) | 夏普指数 | 最大回撤(%) | 交易次数 | |
---|---|---|---|---|
stock11 | 152.3 | 0.73 | 0.1334 | 232 |
stock12 | 131.74 | 0.63 | 0.0892 | 209 |
stock13 | 124.96 | 0.5 | 0.1674 | 223 |
stock14 | 169.05 | 0.7 | 0.1512 | 227 |
stock15 | 172.63 | 0.6 | 0.1554 | 212 |
stock16 | 122.93 | 0.55 | 0.1547 | 233 |
stock17 | 74.49 | 0.23 | 0.1374 | 229 |
stock18 | 166.75 | 0.78 | 0.0993 | 227 |
stock19 | 107.23 | 0.41 | 0.1651 | 242 |
stock20 | 198.21 | 1.05 | 0.0946 | 266 |
各支股票收益率情况如表1。可以看出,12年间,股票收益普遍位于100%至200%之间,使用年金模型折算年化收益率约为6%~10%,在无组合资产投资方面属于较为先进的水平。
六、总结
基于Pyalgotrade平台和talib库,我们实现了一个股票交易模型,它主要运用布林线、CCI等指标,结合动量、涨停、复权等股票专业知识,进行主观客观综合分析,采用支持向量机进行预测推荐的交易量,并进行投资规划,可以实现约为6%~10%的年化收益率。与中长期持股的股票交易策略不同,本交易模型主要采用了“快买快卖”“买了就卖”的短线交易策略,主要的收益来源是短期持股,因此也有较高的交易次数。