MacdMaStrategy.java是一个专为ETH合约设计的MACD+MA复合交易策略实现类,结合了移动平均线(MA)的趋势判断能力和MACD指标的动量分析能力,通过RSI和波动率指标进行风险控制和信号过滤。
类中初始化了以下技术指标:
// MACD指标:用于判断价格动量和趋势变化
private final MACD macd = new MACD();
// 30日移动平均线:ETH波动较大,使用更短的周期捕捉趋势变化
private final MovingAverage ma30 = new MovingAverage(30);
// 100日移动平均线:ETH作为高波动资产,长期趋势判断使用更短周期
private final MovingAverage ma100 = new MovingAverage(100);
// RSI指标(10周期):ETH波动快,使用更短周期提高响应速度
private final RSI rsi = new RSI(10);
// 波动率指标(15周期):ETH波动频繁,使用更短周期捕捉市场变化
private final Volatility volatility = new Volatility(15);
// 最新价格:用于策略判断
private BigDecimal lastPrice;
// 当前市场趋势:牛市/熊市
private TrendDirection trend;
定义了两个内部枚举类型用于状态表示:
enum PositionStatus { FLAT, LONG, SHORT } // 持仓状态:空仓/多头/空头
enum TrendDirection { BULLISH, BEARISH } // 趋势方向:牛市/熊市
public void execute(List<BigDecimal> prices) {
// 验证输入数据完整性:策略需要至少200个价格数据点
if (prices.size() < 200) {
throw new IllegalArgumentException("至少需要200个价格数据点才能运行该策略");
}
updateIndicators(prices); // 更新所有技术指标
getTrend(); // 确定当前市场趋势
}
private void updateIndicators(List<BigDecimal> prices) {
// 先计算波动率指标,因为MACD需要用它来动态调整周期
volatility.calculate(prices);
// 计算MACD指标并传入波动率参数,实现动态周期调整
macd.calculate(prices, volatility.getValue());
// 计算移动平均线指标
ma30.calculate(prices); // 计算30日移动平均线
ma100.calculate(prices); // 计算100日移动平均线
// 计算RSI指标
rsi.calculate(prices);
// 更新最新价格
lastPrice = prices.get(prices.size()-1);
}
public TrendDirection getTrend() {
return determineTrend();
}
private TrendDirection determineTrend() {
BigDecimal currentMa100 = ma100.getMa(); // 获取当前100日移动平均线
// 根据最新价格与100日MA的关系判断趋势:价格高于100日MA为牛市,否则为熊市
return lastPrice.compareTo(currentMa100) > 0 ?
TrendDirection.BULLISH : TrendDirection.BEARISH;
}
public TradeRequestParam getOrderParamOpen(TradeRequestParam tradeRequestParam) {
return checkEntrySignal(tradeRequestParam);
}
private TradeRequestParam checkEntrySignal(TradeRequestParam tradeRequestParam) {
String poSide = null;
BigDecimal currentMa30 = ma30.getMa();
BigDecimal currentDif = macd.getDif();
BigDecimal currentDea = macd.getDea();
BigDecimal macdBar = macd.getMacdBar();
BigDecimal currentRsi = rsi.getRsi();
BigDecimal currentVolatility = volatility.getValue();
if (trend == TrendDirection.BULLISH) {
// 牛市入场条件:MACD多头信号、MACD柱状图为正、价格在30日MA之上、RSI合理、波动率适中
boolean macdBull = currentDif.compareTo(currentDea) > 0;
boolean macdBarPositive = macdBar.compareTo(BigDecimal.ZERO) > 0;
BigDecimal priceMaDiff = lastPrice.subtract(currentMa30);
boolean priceAboveMAWithStrength = priceMaDiff.compareTo(currentMa30.multiply(new BigDecimal("0.005"))) > 0;
boolean rsiInRange = currentRsi.compareTo(new BigDecimal(40)) > 0 && currentRsi.compareTo(new BigDecimal(65)) < 0;
boolean volatilityModerate = currentVolatility.compareTo(new BigDecimal("0.005")) > 0 &&
currentVolatility.compareTo(new BigDecimal("0.05")) < 0;
if (macdBull && macdBarPositive && priceAboveMAWithStrength && rsiInRange && volatilityModerate) {
poSide = CoinEnums.POSSIDE_LONG.getCode();
}
} else if (trend == TrendDirection.BEARISH) {
// 熊市入场条件:MACD空头信号、MACD柱状图为负、价格在30日MA之下、RSI合理、波动率适中
boolean macdBear = currentDif.compareTo(currentDea) < 0;
boolean macdBarNegative = macdBar.compareTo(BigDecimal.ZERO) < 0;
BigDecimal priceMaDiff = currentMa30.subtract(lastPrice);
boolean priceBelowMAWithStrength = priceMaDiff.compareTo(currentMa30.multiply(new BigDecimal("0.005"))) > 0;
boolean rsiInRange = currentRsi.compareTo(new BigDecimal(35)) > 0 && currentRsi.compareTo(new BigDecimal(60)) < 0;
boolean volatilityModerate = currentVolatility.compareTo(new BigDecimal("0.005")) > 0 &&
currentVolatility.compareTo(new BigDecimal("0.05")) < 0;
if (macdBear && macdBarNegative && priceBelowMAWithStrength && rsiInRange && volatilityModerate) {
poSide = CoinEnums.POSSIDE_SHORT.getCode();
}
}
tradeRequestParam.setPosSide(poSide);
return tradeRequestParam;
}
public TradeRequestParam getOrderParamClose(TradeRequestParam tradeRequestParam) {
return checkExitSignal(tradeRequestParam);
}
private TradeRequestParam checkExitSignal(TradeRequestParam tradeRequestParam) {
BigDecimal currentMa30 = ma30.getMa();
BigDecimal currentDif = macd.getDif();
BigDecimal currentDea = macd.getDea();
String posSide = tradeRequestParam.getPosSide();
if (posSide == CoinEnums.POSSIDE_LONG.getCode()) {
// 多头持仓离场条件:MACD转为空头信号且价格跌破30日MA
boolean macdExit = currentDif.compareTo(currentDea) < 0;
boolean priceExit = lastPrice.compareTo(currentMa30) < 0;
if (macdExit && priceExit) {
tradeRequestParam.setSide(CoinEnums.SIDE_SELL.getCode());
}
} else if (posSide == CoinEnums.POSSIDE_SHORT.getCode()) {
// 空头持仓离场条件:MACD转为多头信号且价格突破30日MA
boolean macdExit = currentDif.compareTo(currentDea) > 0;
boolean priceExit = lastPrice.compareTo(currentMa30) > 0;
if (macdExit && priceExit) {
tradeRequestParam.setSide(CoinEnums.SIDE_BUY.getCode());
}
}
return tradeRequestParam;
}
public boolean getSkip() {
return shouldSkipTrade();
}
private boolean shouldSkipTrade() {
// 波动率过滤:当波动率小于1%时,市场活跃度不足,跳过交易
if (volatility.getValue().compareTo(new BigDecimal("0.01")) < 0) {
return true;
}
// RSI极端值过滤:
// 1. 牛市中RSI>65表示超买,避免追高
// 2. 熊市中RSI<35表示超卖,避免追空
if (trend == TrendDirection.BULLISH && rsi.getRsi().compareTo(new BigDecimal(65)) > 0) {
return true;
}
if (trend == TrendDirection.BEARISH && rsi.getRsi().compareTo(new BigDecimal(35)) < 0) {
return true;
}
return false;
}
MacdMaStrategy.java实现了一个完整的MACD+MA复合交易策略,专为ETH合约设计。该策略通过结合多种技术指标,实现了趋势判断、入场时机选择和风险控制的功能。策略执行流程清晰,从指标更新到趋势判断,再到交易信号生成和过滤,形成了一个完整的交易决策系统。
该策略的核心优势在于动态参数调整和多重指标验证,能够较好地适应ETH高波动的市场特性,同时通过严格的过滤机制降低交易风险。