
다중 지표 돌파 및 반전 거래 전략은 기술 분석 지표와 가격 행동을 결합한 양적 거래 방법이며, 시장의 두 가지 주요 거래 기회를 잡기 위해 고안되었습니다. 가격 반전 및 트렌드 돌파. 이 전략은 이동 평균, 상대적으로 약한 지수 (RSI), 평균 실제 범위 (ATR) 및 거래량 중화 평균 가격 (VWAP) 과 같은 여러 가지 기술 지표를 교묘하게 통합하고 있으며, 진입 신호의 신뢰성을 높이기 위해 오프 리치 돌파 (ORB) 메커니즘을 도입합니다. 이 전략은 두 개의 목표 스톱을 설계하고 있으며, 자동으로 스톱 손실을 평형 손실점으로 조정하는 위험 관리 장치가 있습니다.
이 전략의 핵심 원칙은 3가지 종류의 잠재적으로 유리한 거래 기회를 여러 지표에 의해 필터링하고 확인하는 것입니다.
반전 거래 신호:
트렌드 브레이크 신호:
오브 리브 (ORB) 신호:
전략은 ATR 지표를 사용하여 동적 스톱로스 위치를 계산하고, 특정 기간의 최저 가격/최고 가격과 ATR 값의 배수를 더하고 감소시켜 설정합니다. 진입 후, 전략은 두 가지 스톱 포지션을 설정합니다.
첫 번째 정지 목표가 달성되면, 전략은 자동으로 정지를 입시 가격으로 조정하고, 이미 얻은 이익을 효과적으로 보호한다.
다양한 입구 신호이 전략은 반전, 파격, 그리고 개장 간격의 세 가지 다른 입력 신호를 통합하여 여러 시장 환경에 적응할 수 있으며, 거래 기회를 효과적으로 증가시키면서도 높은 신호 품질을 유지할 수 있습니다.
좋은 위험 관리이 전략은 단계적 정지 메커니즘을 적용하여 수익의 일부를 확보하면서 잠재적으로 더 큰 수익을 유지할 수 있습니다. 첫 번째 정지 목표가 달성되면 자동으로 정지 손실이 이익 손실의 균형 지점으로 조정되어 “이익을 뛸 수 있도록” 동시에 자본을 보호합니다.
동적 스톱 손실 계산: ATR 지표를 사용하여 스톱 포지션을 계산하여 스톱 레벨이 시장의 변동적 동력에 따라 조정될 수 있도록, 현재의 시장 상황을 더 정확하게 반영하고, 너무 엄격하거나 너무 느슨한 스톱 설정을 피한다.
거래량 확인: 특히 ORB 신호에 거래량 확인 메커니즘을 도입하여, 거래량이 개장 기간 동안의 평균 거래량보다 특정 배수를 초과해야 한다고 요구하여, 낮은 품질의 돌파구를 효과적으로 필터링한다.
트렌드 필터: 200기 간단한 이동 평균 ((SMA200) 을 통해 장기적인 트렌드 방향을 판단하여 거래 방향이 주요 트렌드와 일치하도록 하여 거래 성공률을 높인다.
자금 관리 통합전략: 내장된 자금 관리 메커니즘, 각 거래에 사용되는 자금 비율을 제한하는 것 (본금의 기본 50%), 자금의 다양화 배치를 보장하고 단일 거래의 위험 을 낮추는 것.
해결 방법: 가격 행동 패턴 식별과 같은 미래 지향적 지표를 추가하거나, 시장 변화에 대한 민감성을 높이기 위해 더 긴 주기 이동 평균의 매개 변수를 줄이는 것을 고려하십시오.
해결 방법: 적절한 변수 최적화 방법을 사용하십시오. 예를 들어, 전진 검증, 몬테카로 시뮬레이션, 과잉 최적화를 피하십시오. 또는 고정된 변수를 사용하여 더 안정적인 규칙 설계에 집중하십시오.
해결책: 더 엄격한 신호 우선 순위 시스템을 구축하거나, 거래가 높은 확률에서만 실행되도록 추가 확인 메커니즘을 도입하십시오.
해결 방법: 옵션 헤지 전략을 사용하거나, 높은 변동성 시장 조건에서 스톱 라인지를 늘리거나, 심지어 일시적으로 포지션 크기를 줄이는 것을 고려하십시오.
해결 방법: 전체적인 위험 통제를 실시하고, 전체적인 포지션 규모를 제한하거나, 다른 자산 클래스 사이에 분산 거래하여 연관성 위험을 줄입니다.
최적화 이유: 기존의 고정 가중치 지표 조합은 시장의 다른 단계에 적응하기가 어렵고, 기계 학습은 역사적 데이터에서 최적의 지표 조합 패턴을 자동으로 학습할 수 있다.
최적화 이유: 시장의 감정은 단기 가격 움직임에 중요한 영향을 미치며, 이러한 지표를 통합하면 시장의 전환점을 사전에 포착하고, 진입 및 출구 시기를 최적화 할 수 있다.
최적화 이유: 고정된 리스크 수익률은 다른 시장 환경에서 충분히 유연하지 않을 수 있으며, 동적 조정은 높은 변동성 시장에서 더 먼 목표를 설정하고, 낮은 변동성 시장에서 더 보수적인 목표를 설정할 수 있다.
최적화 이유: 시장 활동은 하루의 다른 시간대에 뚜렷한 차이를 나타냅니다. 시간 필터는 전략이 가장 유리한 거래 시간에 집중하도록 도와줍니다.
최적화 이유: 위험은 시장의 변동성과 직결되어 있으며, 동적 포지션 관리는 더 일관된 위험 수준을 유지하여 장기적인 위험 조정 후 수익을 개선할 수 있다.
다중 지표 돌파 및 반전 거래 전략은 여러 가지 기술적 분석 방법을 결합한 통합적인 양자 거래 시스템으로, 반전, 트렌드 돌파 및 오픈 영역 돌파 신호를 통합하여, 완벽한 위험 관리 및 자금 관리 메커니즘과 결합하여, 다양한 시장 환경의 거래 기회를 잡기 위해 고안되었습니다. 이 전략의 핵심 장점은 신호 다원화, 위험 관리의 개선 및 파라미터의 사용자 정의성이 강하며, 특히 단기 거래에 적합합니다. 동시에, 전략은 지표 지연, 파라미터 민감성 및 신호 충돌 잠재적인 위험과 같은 위험에 직면하고 있으며, 기계 학습, 시장 감정 분석, 동적 정지 설정 등의 방향에 대한 추가 최적화가 필요합니다.
/*backtest
start: 2025-01-01 00:00:00
end: 2025-03-31 00:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=5
strategy("Reversal & Breakout Strategy with ORB", overlay=true, pyramiding=2, initial_capital=50000)
// --- Inputs ---
ema9Length = input.int(9, "9 EMA Length", minval=1)
ema20Length = input.int(20, "20 EMA Length", minval=1)
sma50Length = input.int(50, "50 SMA Length", minval=1)
sma200Length = input.int(200, "200 SMA Length", minval=1)
rsiLength = input.int(14, "RSI Length", minval=1)
rsiOverbought = input.int(70, "RSI Overbought", minval=0, maxval=100)
rsiOversold = input.int(30, "RSI Oversold", minval=0, maxval=100)
atrLength = input.int(14, "ATR Length", minval=1)
stopMulti = input.float(0.5, "Stop Loss ATR Multiplier", minval=0.1, step=0.1)
stopLookback = input.int(7, "Stop Loss Lookback", minval=1)
rr1 = input.float(0.5, "Risk:Reward Target 1", minval=0.1, step=0.1)
rr2 = input.float(1.1, "Risk:Reward Target 2", minval=0.1, step=0.1)
target1Percent = input.float(25, "Profit % Target 1", minval=0, maxval=100)
orbBars = input.int(15, "Opening Range Bars", minval=1, tooltip="Number of bars to define the opening range (e.g., 15 bars = 30 min on 2-min chart)")
volThreshold = input.float(1.5, "Volume Threshold Multiplier", minval=1.0, step=0.1, tooltip="Volume must be this multiple of the opening range average")
// --- Indicators ---
// Moving Averages
ema9 = ta.ema(close, ema9Length)
ema20 = ta.ema(close, ema20Length)
sma50 = ta.sma(close, sma50Length)
sma200 = ta.sma(close, sma200Length)
// VWAP
vwapValue = ta.vwap(close)
// RSI
rsi = ta.rsi(close, rsiLength)
// ATR
atr = ta.atr(atrLength)
// --- Opening Range Breakout ---
var float openingRangeHigh = na
var float openingRangeLow = na
var float openingRangeAvgVol = na
if bar_index < orbBars
openingRangeHigh := na
openingRangeLow := na
openingRangeAvgVol := na
else if bar_index == orbBars
openingRangeHigh := ta.highest(high, orbBars)
openingRangeLow := ta.lowest(low, orbBars)
openingRangeAvgVol := ta.sma(volume, orbBars)
orbLong = not na(openingRangeHigh) and ta.crossover(close, openingRangeHigh) and volume > openingRangeAvgVol * volThreshold
orbShort = not na(openingRangeLow) and ta.crossunder(close, openingRangeLow) and volume > openingRangeAvgVol * volThreshold
// --- Trend Detection ---
trendUp = close > sma200
trendDown = close < sma200
// --- Reversal Conditions ---
reversalLong = ta.crossover(close, sma50) and rsi < rsiOversold and close < vwapValue and trendUp
reversalShort = ta.crossunder(close, sma50) and rsi > rsiOverbought and close > vwapValue and trendDown
// --- Range Breakout Conditions ---
breakoutLong = ta.crossover(ema9, ema20) and close > vwapValue and trendUp
breakoutShort = ta.crossunder(ema9, ema20) and close < vwapValue and trendDown
// Combine conditions
longCondition = (reversalLong or breakoutLong or orbLong)
shortCondition = (reversalShort or breakoutShort or orbShort)
// --- Calculate Position Size ---
equityPerPosition = 25000.0 // $50,000 / 2 positions
positionSizeLong = math.floor(equityPerPosition / close)
positionSizeShort = math.floor(equityPerPosition / close)
// --- Stop Loss Calculation ---
longStop = ta.lowest(low, stopLookback) - (atr * stopMulti)
shortStop = ta.highest(high, stopLookback) + (atr * stopMulti)
// --- Variables to Store Trade Levels ---
var float tradeStop = na
var float tradeTarget1 = na
var float tradeTarget2 = na
var float initialPositionSize = na
var bool breakEvenSet = false // Track if stop has been moved to break-even
var float stopLevel = na // Dedicated variable for stop loss in exits
var float target1Level = na // Dedicated variable for first take profit
var float target2Level = na // Dedicated variable for second take profit
var float qtyTotal = na // Track total quantity
// --- Reset Levels Before New Trade ---
var bool newTrade = false
if longCondition or shortCondition
newTrade := true
else
newTrade := false
if strategy.position_size == 0 and newTrade
tradeStop := na
tradeTarget1 := na
tradeTarget2 := na
stopLevel := na
target1Level := na
target2Level := na
initialPositionSize := na
qtyTotal := na
breakEvenSet := false
// --- Strategy Entries ---
if longCondition and strategy.position_size == 0
strategy.entry("Long", strategy.long, qty=positionSizeLong * 2)
tradeStop := longStop
stopLevel := longStop
stopDistance = close - tradeStop
tradeTarget1 := close + (stopDistance * rr1)
tradeTarget2 := close + (stopDistance * rr2)
target1Level := tradeTarget1
target2Level := tradeTarget2
initialPositionSize := positionSizeLong * 2
qtyTotal := positionSizeLong * 2
breakEvenSet := false // Reset break-even flag
if shortCondition and strategy.position_size == 0
strategy.entry("Short", strategy.short, qty=positionSizeShort * 2)
tradeStop := shortStop
stopLevel := shortStop
stopDistance = tradeStop - close
tradeTarget1 := close - (stopDistance * rr1)
tradeTarget2 := close - (stopDistance * rr2)
target1Level := tradeTarget1
target2Level := tradeTarget2
initialPositionSize := positionSizeShort * 2
qtyTotal := positionSizeShort * 2
breakEvenSet := false // Reset break-even flag
// --- Trade Exits ---
if strategy.position_size > 0
qty_tp1 = qtyTotal * (target1Percent / 100)
qty_tp2 = qtyTotal * ((100 - target1Percent) / 100)
strategy.exit("Long Exit 1", "Long", qty=qty_tp1, stop=stopLevel, limit=target1Level)
strategy.exit("Long Exit 2", "Long", qty=qty_tp2, stop=stopLevel, limit=target2Level)
if strategy.position_size < 0
qty_tp1 = qtyTotal * (target1Percent / 100)
qty_tp2 = qtyTotal * ((100 - target1Percent) / 100)
strategy.exit("Short Exit 1", "Short", qty=qty_tp1, stop=stopLevel, limit=target1Level)
strategy.exit("Short Exit 2", "Short", qty=qty_tp2, stop=stopLevel, limit=target2Level)
// --- Move Stop to Break-even ---
if strategy.position_size != 0 and not na(initialPositionSize) and not breakEvenSet
if math.abs(strategy.position_size) < math.abs(initialPositionSize)
tradeStop := strategy.position_avg_price
stopLevel := strategy.position_avg_price
tradeTarget1 := na // Clear first target for plotting
breakEvenSet := true // Mark break-even as set
// --- Manual Close Fallback ---
if strategy.position_size > 0
if close >= target2Level or close <= stopLevel
strategy.close("Long", qty=qtyTotal, comment="Manual Close")
if strategy.position_size < 0
if close <= target2Level or close >= stopLevel
strategy.close("Short", qty=qtyTotal, comment="Manual Close")
// --- Reset Levels When No Position ---
if strategy.position_size == 0 and not newTrade
tradeStop := na
tradeTarget1 := na
tradeTarget2 := na
stopLevel := na
target1Level := na
target2Level := na
initialPositionSize := na
qtyTotal := na
breakEvenSet := false
// --- Plotting ---
plot(tradeStop, title="Stop Loss", color=color.red, linewidth=1, style=plot.style_linebr)
plot(tradeTarget1, title="Take Profit 1", color=color.green, linewidth=1, style=plot.style_linebr)
plot(tradeTarget2, title="Take Profit 2", color=color.blue, linewidth=1, style=plot.style_linebr)