技术指标-ATR
FCAT 2025/2/7 技术指标
ATRIndicator
(Average True Range,平均真实波动幅度)是一个衡量市场波动性的技术指标,广泛用于确定止损、止盈位置以及仓位管理。以下是 ATRIndicator
的详细解释,并结合你的策略(15分钟K线 + 20MA上方做多)给出具体用法。
# 一、ATRIndicator 的核心逻辑
计算步骤:
- True Range (TR):计算单根K线的波动幅度,取以下三者中的最大值:
- 当前最高价 - 当前最低价
- 当前最高价 - 前一收盘价的绝对值
- 当前最低价 - 前一收盘价的绝对值
- ATR:对TR进行移动平均(默认周期14),得到平滑后的波动幅度。
- True Range (TR):计算单根K线的波动幅度,取以下三者中的最大值:
核心作用:
- 衡量波动性: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
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
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
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
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
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
# 四、实战注意事项
ATR周期选择:
- 默认14周期适用于大多数场景,可根据币种特性调整(如高波动币种可缩短至10)。
止损/止盈倍数优化:
- 通过历史回测确定最佳倍数(如1.5倍ATR止损,0.3倍ATR止盈)。
结合更高周期确认趋势:
- 使用4小时或日线图确认趋势方向,避免逆势交易。
通过将 ATRIndicator
融入你的策略,可以实现更科学的动态止损、止盈和仓位管理,从而在币圈合约交易中更好地控制风险、捕捉趋势。
# 2. 当前波动率显著高于历史平均水平
# 定义
- 波动率:价格的变化幅度,通常用标准差或ATR(平均真实波动幅度)来衡量。
- 历史波动率:过去N根K线的波动率均值。
- 显著高于:当前波动率超过历史波动率的某个阈值(例如50%)。
# 量化方法
计算过去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线的平均收益率。
计算当前波动率:
- 当前波动率可以用最近M根K线(例如M=5)的收益率标准差来衡量。
判断是否显著高于:
- 如果当前波动率 > 历史波动率 × 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
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(当前波动率)。