欢迎大家订阅《教你用 Python 进阶量化交易》专栏!为了能够提供给大家更轻松的学习过程,笔者在专栏内容之外已陆续推出一些手记来辅助同学们学习本专栏内容,目前推出的扩展篇链接如下:
第一篇《管理概率==理性交易》
第二篇《线性回归拟合股价沉浮》
第三篇《最大回撤评价策略风险》
第四篇《寻找最优化策略参数》
第五篇《标记A股市场涨跌周期》
第七篇《装饰器计算代码时间》
第八篇《矢量化计算KDJ指标》
第九篇《移植量化交易小工具》
第十篇《统计学预测随机漫步》
第十一篇《TA-Lib库扩展介绍》
第十二篇《股票分笔数据跨周期处理》
第十三篇《TA-Lib库量价指标分析》
在专栏的19小节《股票交易策略开发:趋势突破择时策略》介绍了海龟法则中唐奇安通道突破策略。
在专栏的21小节《股票交易策略开发:ATR止盈止损风险策略》介绍了基于ATR指标的风险管理策略。
在海龟交易法则中,ATR指标是资金管理的核心,风险管理策略的判断某种程度上也是对于资金的保护。
在资金管理中,根据ATR值实现动态仓位的计算,可以与当前市场的波动率相关联。本次场外片主要介绍下如何结合专栏第19小节和21小节的内容,实现基于ATR指标的动态资金管理模块。
ATR指标的计算比较简单,分为以下两部分:
- TR=∣最高价-最低价∣和∣最高价-昨收∣和∣昨收-最低价∣的最大值= max(∣High-Low∣,∣High-Close∣,∣Close-Low∣)
- ATR=TR的N日简单移动平均
ATR指标的实现可直接使用talib库的ATR() 接口,如下所示:
ATR14 = talib.ATR(df_stock.High, df_stock.Low, df_stock.Close, timeperiod=14)
ATR21 = talib.ATR(df_stock.High, df_stock.Low, df_stock.Close, timeperiod=21)
我们先绘制出浙大网新2018年1月1日至2019年10月18日的行情走势图,如下所示:
然后我们绘制出浙大网新2018年1月1日至2019年10月18日的14日和21日的ATR指标,如下图所示:
接下来在21小节《股票交易策略开发:ATR止盈止损风险策略》中加入ATR资金管理模块。资金管理模块由以下三部分组成:
- 头寸规模
- 止损价位(专栏已介绍)
- 加减仓规模
专栏中已经实现了止盈止损实现方法,参数和类函数如下所示:
{'stop_loss_n': 0.8, 'stop_win_n': 2, 'class': FactorSellAtrStop}
那么让我们来扩展介绍下头寸规模和加减仓规模的实现。
(1)计算头寸规模
《海龟交易法则》建议第一笔仓位的一个ATR波动与总资金1%波动相对应。即:买入股票数量 * ATR = 资金 * 1%
比如手上有10万元资金,那么10万资金的1%波动就是1000元。股票A的21日ATR为0.201元,1000元÷0.201元=4975.12股,取整则是4900股。也就是说,头寸规模应该是买入4900股。
我们对比下全仓买入和ATR头寸规模买入的资金收益,分别在初始化函数中设立两个账户:
def __init__(self, kl_pd, buy_factors, sell_factors):
"""
:param cap: 初始资金
:param kl_pd: 择时时间段交易数据
:param buy_factors: 买入因子序列,序列中的对象为dict,每一个dict针对一个具体因子
:param sell_factors: 卖出因子序列,序列中的对象为dict,每一个dict针对一个具体因子
"""
# 回测阶段kl
self.kl_pd = kl_pd
# 初始化买入因子列表
self.init_buy_factors(buy_factors)
# 初始化卖出因子列表
self.init_sell_factors(sell_factors)
self.buy_price = 0 # 买入价格
self.cash_hold_a = 100000 # 账户A 初始资金
self.cash_hold_b = 100000 # 账户B 初始资金
self.posit_num_a = 0 # 账户A 持股数目
self.posit_num_b = 0 # 账户B 持股数目
self.profit_curve_a = [] # 账户A 资产曲线
self.profit_curve_b = [] # 账户B 资产曲线
plt.figure(figsize=(18, 8), dpi=80, facecolor="white")
买入部分代码更改如下所示:
self.posit_num_a = int(self.cash_hold_a / self.buy_price)
self.posit_num_b = int(self.cash_hold_b * 0.1 / today.atr21) # 计算买入的股票数量
self.cash_hold_a = 0
self.cash_hold_b = self.cash_hold_b - self.posit_num_b * self.buy_price # 计算买入后剩余的资金
卖出部分代码更改如下所示:
self.cash_hold_a = int(self.posit_num_a * today.Close)
self.posit_num_a = 0
self.cash_hold_b = self.cash_hold_b + int(self.posit_num_b * today.Close) # 计算卖出后总共的资金
self.posit_num_b = 0
对比回测效果如下图所示:
其中全仓买入最后的收益为111750,ATR头寸规模买入最后的收益为145537。可见同样的收益率,但是不同的仓位管理策略,最终的资金获利是不同的。当然此处仅仅是以一个例程展示下对比的结果而已。
(2)动态调整仓位
当我们以一个ATR波动与总资金1%波动相对应的策略买入了4900股。假如买完之后股票A长期盘整,既无大涨也无大跌,此时ATR会进一步下跌,比如由0.201元下降至0.120元时,投资者便可重新计算仓位。依旧按照1%资金=1ATR波动计算,则可持有8300股,此前已经买入4900股,则投资者还可加仓3400股。
有人会觉得万一股价向下,那不是亏损更多嘛?有经验的投资者都明白,长期盘整往往是大方向出现的前兆。如果股价向下,由于投资者按照ATR设定止损,所以亏损的资金总额依然不变。但是若方向朝上,则后面加仓的部分便可以为投资者带来额外的收益。实际操作中记住需要增加手续费和加动态调整仓位的阈值,比如波动在1000股以上才选择加减仓。
实现代码如下所示:
posit_num_wave = int(self.total_cash * 0.1 / today.atr21) # 计算买入的股票数量
if(posit_num_wave >= self.posit_num_b): # 波动后加仓
self.cash_hold_b = self.cash_hold_b - (posit_num_wave - self.posit_num_b) * self.buy_price # 计算买入后剩余的资金
self.posit_num_b = posit_num_wave
else: # 波动后减仓
self.cash_hold_b = self.cash_hold_b + (self.posit_num_b - posit_num_wave) * self.buy_price # 计算买入后剩余的资金
self.posit_num_b = posit_num_wave
关于完整代码可以加入专栏交流群获取。更多的量化交易内容欢迎大家订阅专栏阅读!!
·····························
欢迎大家订阅《教你用 Python 进阶量化交易》专栏!