真实波幅均值(ATR average true range)(难度:初级)

Table of Contents

什么是真实波幅均值?

真实波幅均值(ATR average true range)起初应用于股票市场分析,是取一定时间周期内的价格波动幅度的移动平均值,主要用于研判买卖时机,是显示市场变化率的反趋向指标,由威尔德(J. Welles Wilder)1978年于《New Concepts in Technical Trading Systems》一书中提出提出,目前已成为众多指标经常引用的技术量,被许多用户称为技术指标中的一匹真正的劲马。真实波幅均值(ATR)主要用于帮助用户合理分配资金、动态调整止损、动态调整仓位等

ATR指标使用方法

合理分配资金

不少投资者都会同时持有2个甚至更多的期货合约。如何在多个期货合约之间分配资金呢?均分法是大多数人选择的方法。手头有10万元资金,那么就两者各买5万元。如此算法固然简单,但却有一个重大问题——不同期货合约特性不同,有的很活跃波动很大,有的却往往波幅较小,若这两类期货合约用同样的资金购买,那么特性活跃的期货合约带来的亏损和盈利都会超过特性相对不活跃的。

ATR指标则可以解决这个问题,只要我们让所有资金的固定百分比与某个期货合约的1个ATR波动对应即可。以SHFE.au1912和DCE.i2001为例,假设我们有100万元资金,我们可以通过如下步骤让上述两个股票的1个ATR的波动等价于总资金1%的波动:

计算ATR:SHFE.au1912在2019/8/21日ATR为6.6元,相当于当日合约价的1.9%;而DCE.i2001,ATR为27.3元,相当于当日合约价的4.62%,显然后者比前者活跃。

计算总资产1%的1个ATR波动手数:10000÷(6.6*1000(SHFE.au1912合约乘数))=1.52,即我们应当买入1手的SHFE.au1912;与此同时,10000÷(27.3*100(DCE.i2001合约乘数))=3.66,即我们应当买入3手DCE.i2001。

如此,通过资金分配的不同,我们大体可以使这两个合约的正常波动对投资组合的影响大致相等。(策略源码在文章最后)

from tqsdk import TqApi
from tqsdk.ta import ATR

api = TqApi()
# 创建SHFE.au1912和DCE.i2001的日K线引用
klines1 = api.get_kline_serial("SHFE.au1912",86400)
klines2 = api.get_kline_serial("DCE.i2001",86400)
# 计算SHFE.au1912和DCE.i2001的ATR值
atr1 = ATR(klines1,14) 
atr2 = ATR(klines2,14)


# 预计输出为SHFE.au1912的ATR为: 6.617857142857141 DCE.i2001的ATR为: 52.642857142857146
print("SHFE.au1912的ATR为:",atr1.atr.iloc[-1],"DCE.i2001的ATR为:",atr2.atr.iloc[-1])
# 假设资产为100万,输出等于总资产1%的1个ATR波动的手数
print("SHFE.au1912的总资产1%的1个ATR波动为",10000/(atr1.atr.iloc[-1]*1000),"DCE.i2001的总资产1%的1个ATR波动为",10000/(atr2.atr.iloc[-1]*100))

api.close()

动态调整止损

众所周知,及时止损对交易者是有重大意义的,举例来说10%的亏损只需要11%的盈利即可弥补,20%的亏损,则需要 25%的盈利才可弥补。及时止损,对于长期获利,意义重大。选股大师欧奈尔则推荐投资者使用8%作为止损线为例,一旦亏损超过此数目,便割肉离场。然而利用固定比例作为止损,固然简单易算,但问题还是在于前面讲到的不到品种之间的特性区别。如果不同品种都选择8%作为止损线,显然不太合理。这时候,ATR就有用武之地了。

还是以SHFE.au1912为例,假如某个投资者以拥有该合约多头1手,则可以利用ATR计算加仓和止损价,假设一个ATR的波动为n,以2019/8/21的收盘价 352.5元作为基准。

加仓:设置加仓线为352.5+0.5n,即325.5+0.5×6.6=328.8元,一旦超过自动调整仓位加至多头2手。

止损:设置止损线为325.5-2n,即325.5-6.6*2=312.3,一旦跌破则自动空仓。

这样就算买入DCE.i2001使用相同系数,但是ATR会根据投资品种不同自动调整实际的百分比止损值,这样就比使用固定止损比例更具灵活性了。

# 判断是否持多单 
if position.pos_long > 0: 
    # 加仓策略: 如果是多仓且行情最新价在建仓的基础上涨了0.5n,就调整仓位为目标仓位多头2手 
    if quote.last_price >= order.trade_price + 0.5 *n : 
        print("目标仓位多头2手") 
        target_pos.set_target_volume(2) 
    # 止损策略: 如果是多仓且行情最新价在建仓的基础上下跌了2n,就卖出全部头寸止损 
    elif quote.last_price <= order.trade_price - 2 * n: 
        print("止损:卖出全部头寸") 
        target_pos.set_target_volume(0)

动态调整仓位

对于利用ATR来分配资金设定入市资金的投资者而言,ATR的另外一个效果就是可以动态调整仓位。就以前一例中100万元资金按照1%资金=1ATR波动共买入3手DCE.i2001例。假如买完上证DCE.i2001之后,此品种长期盘整,既无大涨也无大跌时,这时ATR就会进一步下跌,比如由27.3元下降至20元时,投资者便可重新计算仓位:

新仓位计算:10000÷(20*100(DCE.i2001合约乘数))=5

可补充仓位:5-3=2

如何计算ATR指标?

ATR的计算比较简单,首先我们要算出当前真实的波幅.这里不单单考虑当前的价格波动,同时也要考虑到前一个时间点收盘价和当前开盘价之间的价格缺口.而ATR则是真实波幅一段时间窗口(一般取14天)的简单移动平均。计算公式如下:

1.真实波幅(TR): TR = MAX(∣最高价-最低价∣,∣最高价-昨收∣,∣昨收-最低价∣)

2.真实波幅均值(ATR): ATR = TR的N日简单移动平均

在天勤中我们可以很方便的调用出以上两个数据

# 获取 SHFE.au1912 合约的平均真实波幅,导入TqApi和对应的技术指标函数ATR
from tqsdk import TqApi 
from tqsdk.ta import ATR

api = TqApi()
klines = api.get_kline_serial("SHFE.au1912", 24 * 60 * 60)
atr = ATR(klines, 14)
print(atr.tr)  # 真实波幅
print(atr.atr)  # 真实波幅均值
# 预计的输出是这样的:
[..., 143.0, 48.0, 80.0, ...]
[..., 95.20000000000005, 92.0571428571429, 95.21428571428575, ...]

将ATR技术指标运用于策略

策略实现环境:免费期货模拟、实盘的天勤量化程序软件

利用ATR技术指标函数可以进行指定合约的加仓和止损,以下为在持有多仓1手 SHFE.au1912情况下的具体加仓和止损代码:

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
__author__ = "Ringo"

from tqsdk import TqApi,TargetPosTask
from tqsdk.ta import ATR

# ART计算使用天数
ART_DAY_LENGTH = 20 
# 合约代码
SYMBOL = "SHFE.au1912" 

api = TqApi()
klines = api.get_kline_serial(SYMBOL,24*60*60,100)
target_pos = TargetPosTask(api, SYMBOL)
position = api.get_position(SYMBOL)
quote = api.get_quote(SYMBOL)
# 真实波幅均值(n值)
n = ATR(klines,ART_DAY_LENGTH)["atr"].iloc[-1] 
# 使用ATR技术指标加仓或止损前,账户下单多头1手
order = api.insert_order(SYMBOL,"BUY", "OPEN",1) 

while True:
    api.wait_update()
    # 判断多头1手委托单已经完成
    if order.status == "FINISHED" and order.volume_left == 0: 
        if api.is_changing(quote, "last_price"):
            print("最新价: ", quote.last_price)
            # 判断是否持多单
            if position.pos_long > 0:  
                # 加仓策略: 如果是多仓且行情最新价在建仓的基础上涨了0.5n,就调整仓位为目标仓位多头2手
                if quote.last_price >= order.trade_price + 0.5 *n :
                    print("目标仓位多头2手")
                    target_pos.set_target_volume(2)
                # 止损策略: 如果是多仓且行情最新价在建仓的基础上下跌了2n,就卖出全部头寸止损
                elif quote.last_price <= order.trade_price - 2 * n:
                    print("止损:卖出全部头寸")
                    target_pos.set_target_volume(0)

点击查看天勤量化软件

在一些成熟的交易系统,比如海龟交易系统,常使用ATR来确定头寸规模,进行头寸管理,很有成效。利用ATR与波动性成正比的关系,来设置交易的止损位。ATR越小,则止损距应该越短;ATR越大,则止损距就相应的拉长。这样,可以防止在大幅震荡的行情中,由于止损距过小而被提前震出场;或是在平稳的行情中,由于止损距过大,而无法应对突然的暴跌。