技术指标-ATR

2025/2/7 技术指标

ATRIndicator(Average True Range,平均真实波动幅度)是一个衡量市场波动性的技术指标,广泛用于确定止损、止盈位置以及仓位管理。以下是 ATRIndicator 的详细解释,并结合你的策略(15分钟K线 + 20MA上方做多)给出具体用法。


# 一、ATRIndicator 的核心逻辑

  1. 计算步骤

    • True Range (TR):计算单根K线的波动幅度,取以下三者中的最大值:
      • 当前最高价 - 当前最低价
      • 当前最高价 - 前一收盘价的绝对值
      • 当前最低价 - 前一收盘价的绝对值
    • ATR:对TR进行移动平均(默认周期14),得到平滑后的波动幅度。
  2. 核心作用

    • 衡量波动性:ATR值越大,市场波动越剧烈。
    • 动态调整止损/止盈:根据当前波动性调整止损和止盈位置,避免被短期波动洗出。

# 二、ATRIndicator 在你的策略中的具体用法

# 1. 动态止损(段永平“不亏钱”)

  • 规则
    开仓后,设置初始止损为开仓价下方 2 × ATR,随着价格上涨,逐步上移止损线(追踪止损)。

  • 代码实现

// 计算ATR(14周期)
ATRIndicator atr = new ATRIndicator(series, 14);

// 动态止损规则
Rule stopLossRule = new StopLossRule(closePrice, atr.multipliedBy(2), true); // 2倍ATR止损
1
2
3
4
5
  • 示例
    假设当前ATR为200美元,开仓价为30,000美元,则:
    • 初始止损 = 30,000 - (2 × 200) = 29,600
    • 价格上涨至31,000时,止损上移至31,000 - (2 × 200) = 30,600

# 2. 入场信号过滤(段永平“安全边际”)

  • 规则
    价格上穿20MA时,需满足价格低于20MA + 1倍ATR,确保入场点具备安全边际。

  • 代码实现

// 计算20MA和ATR
SMAIndicator sma20 = new SMAIndicator(closePrice, 20);
ATRIndicator atr = new ATRIndicator(series, 14);

// 买入规则:价格上穿20MA + 价格低于20MA的1倍ATR
Rule buyRule = new CrossedUpIndicatorRule(closePrice, sma20)
    .and(new UnderIndicatorRule(closePrice, sma20.plus(atr)));
1
2
3
4
5
6
7
  • 示例
    假设20MA为30,000,ATR为200,则:
    • 价格需低于30,000 + 200 = 30,200
    • 价格上穿30,000时入场

# 3. 动态止盈(段永平“长期持有”)

  • 规则
    价格每上涨1倍ATR,止盈线上移0.5倍ATR,确保在趋势中锁定利润。

  • 代码实现

// 动态止盈规则
Rule takeProfitRule = new TrailingStopLossRule(closePrice, atr.multipliedBy(0.5), true); // 0.5倍ATR止盈
1
2
  • 示例
    假设开仓价为30,000,ATR为200,则:
    • 价格上涨至30,200时,止盈线上移至30,200 - (0.5 × 200) = 30,100
    • 价格上涨至30,400时,止盈线上移至30,400 - (0.5 × 200) = 30,300

# 4. 仓位管理(段永平“聚焦本质”)

  • 规则
    根据ATR值动态调整仓位,波动性越大,仓位越小。

  • 代码实现

// 计算仓位比例(ATR越大,仓位越小)
Num positionSize = series.numOf(100).dividedBy(atr); // 假设100为基准仓位
1
2
  • 示例
    假设ATR为200,则仓位 = 100 / 200 = 0.5(即50%仓位)
    若ATR为100,则仓位 = 100 / 100 = 1(即100%仓位)

# 三、完整策略代码示例

// 创建价格序列
BaseBarSeries series = ...; // 加载K线数据

// 计算指标
ClosePriceIndicator closePrice = new ClosePriceIndicator(series);
SMAIndicator sma20 = new SMAIndicator(closePrice, 20);
ATRIndicator atr = new ATRIndicator(series, 14);

// 买入规则:价格上穿20MA + 价格低于20MA的1倍ATR
Rule buyRule = new CrossedUpIndicatorRule(closePrice, sma20)
    .and(new UnderIndicatorRule(closePrice, sma20.plus(atr)));

// 止损规则:2倍ATR动态止损
Rule stopLossRule = new StopLossRule(closePrice, atr.multipliedBy(2), true);

// 止盈规则:0.5倍ATR动态止盈
Rule takeProfitRule = new TrailingStopLossRule(closePrice, atr.multipliedBy(0.5), true);

// 构建策略
Strategy strategy = new BaseStrategy(buyRule, stopLossRule.or(takeProfitRule));

// 运行回测
TradingRecord tradingRecord = new BaseTradingRecord();
for (int i = series.getBeginIndex(); i <= series.getEndIndex(); i++) {
    if (strategy.shouldEnter(i)) {
        // 计算仓位比例
        Num positionSize = series.numOf(100).dividedBy(atr.getValue(i));
        tradingRecord.enter(i, series.getBar(i).getClosePrice(), positionSize);
    } else if (strategy.shouldExit(i)) {
        tradingRecord.exit(i, series.getBar(i).getClosePrice(), positionSize);
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

# 四、实战注意事项

  1. ATR周期选择

    • 默认14周期适用于大多数场景,可根据币种特性调整(如高波动币种可缩短至10)。
  2. 止损/止盈倍数优化

    • 通过历史回测确定最佳倍数(如1.5倍ATR止损,0.3倍ATR止盈)。
  3. 结合更高周期确认趋势

    • 使用4小时或日线图确认趋势方向,避免逆势交易。

通过将 ATRIndicator 融入你的策略,可以实现更科学的动态止损、止盈和仓位管理,从而在币圈合约交易中更好地控制风险、捕捉趋势。


# 2. 当前波动率显著高于历史平均水平

# 定义

  • 波动率:价格的变化幅度,通常用标准差或ATR(平均真实波动幅度)来衡量。
  • 历史波动率:过去N根K线的波动率均值。
  • 显著高于:当前波动率超过历史波动率的某个阈值(例如50%)。

# 量化方法

  1. 计算过去N根K线的波动率(以标准差为例):

    • 计算每根K线的收益率: [ \text{Return}i = \frac{\text{Close}i - \text{Close}{i-1}}{\text{Close}{i-1}} ]
    • 计算收益率的标准差: [ \text{HistoricalVolatility} = \sqrt{\frac{\sum_{i=1}^{N} (\text{Return}_i - \text{AvgReturn})^2}{N}} ]
      • ( \text{AvgReturn} ):过去N根K线的平均收益率。
  2. 计算当前波动率:

    • 当前波动率可以用最近M根K线(例如M=5)的收益率标准差来衡量。
  3. 判断是否显著高于:

    • 如果当前波动率 > 历史波动率 × 1.5(即当前波动率比历史波动率高50%),则认为波动率显著高于。

# 代码示例(Java)

public boolean isVolatilitySignificantlyHigh(double[] closes, double[] recentCloses) {
    int N = closes.length;
    double[] returns = new double[N - 1];
    for (int i = 1; i < N; i++) {
        returns[i - 1] = (closes[i] - closes[i - 1]) / closes[i - 1];
    }
    double avgReturn = Arrays.stream(returns).average().orElse(0);
    double historicalVolatility = Math.sqrt(Arrays.stream(returns)
            .map(r -> Math.pow(r - avgReturn, 2))
            .average()
            .orElse(0));

    int M = recentCloses.length;
    double[] recentReturns = new double[M - 1];
    for (int i = 1; i < M; i++) {
        recentReturns[i - 1] = (recentCloses[i] - recentCloses[i - 1]) / recentCloses[i - 1];
    }
    double currentVolatility = Math.sqrt(Arrays.stream(recentReturns)
            .map(r -> Math.pow(r - Arrays.stream(recentReturns).average().orElse(0), 2))
            .average()
            .orElse(0));

    return currentVolatility > historicalVolatility * 1.5; // 阈值设为1.5(50%)
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# 3. 参数选择与优化

  • 波动率阈值:1.5(50%)是一个常用值,但可以根据历史数据回测找到最优值。
  • 周期长度
    • 波动率:N=20(历史波动率),M=5(当前波动率)。

Last Updated: 2025/2/14 18:00:25