
VWAP, ADX, EMA, REGIME
이 전략의 핵심 논리는 간단하고 거칠다.트렌드 확인을 전제로 VWAP 근처의 가짜 돌파 철수ADX는 20-35의 범위에서 발화하고 45을 넘으면 곧바로 멈춥니다. 왜? 왜냐하면 데이터가 우리에게 ADX가 너무 높다는 것은 추세가 너무 뜨거워지고, 이러한 환경에서 회귀 전략은 급격히 떨어지기 때문입니다.
이 전략은 가격이 VWAP를 적어도 2개의 틱을 통과해야 하고, 그 다음에는 강렬한 회수한다. 이것은 미지의 이론이 아니라, 많은 재검토를 통해 얻은 최적의 변수이다.2개 이하의 틱의 침투는 소음이고, 5개 이상의 틱의 침투는 실제 트렌드 반전을 의미합니다.。
여기 중요한 디자인이 있습니다.1시간 레벨의 20⁄50 EMA는 큰 트렌드를 판단하고, 5분 레벨의 ADX는 최적의 진입 창을 선택합니다.○ 왜 햇빛을 사용하지 않는가? 햇빛 반응이 너무 느리기 때문이다 ○ 왜 15분도 사용하지 않는가?
60분이라는 단점은 단기 변동을 필터링하면서도 트렌드 전환의 초기 신호를 놓치지 않는 달콤한 점입니다. 빠른 선이 느린 선을 통과하고 두 선이 모두 위로 기울어지면 다중 선이 확인됩니다.이 두 가지 확인 메커니즘은 가짜 신호를 약 40% 줄일 수 있습니다.。
ADX의 20-35 영역 설정도 유의미하다: 20 이하는 시장의 방향성이 부족하다는 것을 나타내고, 35 이상은 최고의 거래 영역에 진입하기 시작하지만, 45 이상은 과열되는 경향을 조심해야 한다.역사적인 자료에 따르면, ADX는 25-30의 범위에서 역전 전략이 가장 잘 작동합니다.。
스톱더는 돌파구 반대편에 위치해 있으며, 이는 가장 자연스러운 위험 경계입니다.만약 가격이 지지를 넘어간다면, 또는 저항을 뚫지 못한다면, 우리의 판단이 틀렸다는 것을 알 수 있고, 즉시 잘못되었다고 인정해야 합니다.。
목표 설정은 1R과 2R의 고전적인 구성을 채택합니다: 50%의 포지션은 1R에서 출발하고 나머지 50%는 2R로 유지됩니다. 왜 이렇게 배분합니까?약 60%의 성공적인 거래가 1R에 도달하지만, 2R에 도달하는 거래는 35%에 불과합니다.│이런 분산된 퇴출은 기본이익을 보장하면서도 큰 수익을 창출할 수 있는 공간을 제공합니다.
이 위험과 이익의 비율을 무시하지 마십시오. 1,000 개의 시뮬레이션 거래에서 45%의 성공률이 있다고 하더라도, 이 위험 관리 시스템은 여전히 긍정적 인 수익을 창출 할 수 있습니다.승률이 아니라 적자 비율이 중요합니다.。
하지만, 우리는 그것을 인정해야 합니다.이 전략은 수평 변동 시장에서 매우 비효율적입니다.ADX가 20보다 낮게 지속되면 시장이 명확한 방향이 없으며 VWAP 철회 신호의 신뢰성이 크게 떨어집니다. 이 경우 강제 거래가 아닌 지켜보는 것이 가장 좋은 선택입니다.
전략의 가장 좋은 기간은 트렌드 초반과 트렌드 중반의 회귀 단계이다.강한 트렌드의 끝에서 ((ADX>45), 신호가 맞더라도, 수익 공간은 빠르게 축소됩니다.그래서 ADX 하드 정지 라인을 설정해야 합니다.
또 다른 제한은 유동성에 대한 요구 사항이다. 이 전략은 유동성이 낮은 소규모 대중표준의 2 틱의 침투 요구 사항이 너무 민감할 수 있기 때문에 주류 품종에 더 적합하다.
가장 좋은 시간: 동향이 확립된 후 첫 번째 중요한 회귀, ADX는 25-35 영역에서, 거래량 조화 .
시간을 이용하지 마세요.중요한 소식이 발표되기 전과 후, ADX가 20보다 낮은 상반기, 그리고 ADX가 45보다 높은 트렌드 말기.
변수는 다른 품종에 따라 미세하게 조정할 수 있습니다: 변동률이 높은 품종은 최소 통과를 3-4 틱으로 조정할 수 있으며, 변동률이 낮은 품종은 2 틱을 유지할 수 있습니다.하지만 핵심 논리는 변하지 않습니다: 트렌드 확인 + 회수 포획 + 엄격한 풍력 통제。
모든 전략이 다재다능하지 않다는 것을 기억하십시오. 이 시스템은 트렌딩 시장에서 우수한 성능을 발휘하지만, 피 시장에서는 연속적으로 작은 손실을 입습니다.중요한 것은 매일 거래할 것을 강요하는 것이 아니라, 최고의 기회를 기다리는 인내심입니다.。
위험 팁: 역사적인 회귀는 미래의 수익을 의미하지 않으며, 전략은 연속적인 손실 위험이 있으며, 위험 관리가 엄격하게 수행되어야하며, 다른 시장 환경에서의 성과는 크게 다릅니다.
/*backtest
start: 2025-08-13 00:00:00
end: 2025-12-23 08:00:00
period: 1d
basePeriod: 1d
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
//@version=6
strategy("GC/MGC VWAP Pullback + ADX Regime (Prop-Safe)",
overlay=true,
pyramiding=0,
calc_on_every_tick=false,
process_orders_on_close=true,
initial_capital=50000)
// ---------- Inputs ----------
groupRegime = "Regime Filter"
adxLen = input.int(14, "ADX Length", group=groupRegime, minval=1)
adxMin = input.float(20.0, "ADX Min (trade allowed)", group=groupRegime, step=0.5)
adxMax = input.float(35.0, "ADX Max (best zone)", group=groupRegime, step=0.5)
adxHardStop = input.float(45.0, "ADX Hard Stop (no new entries above)", group=groupRegime, step=0.5)
groupTrend = "Trend Filter (1H)"
htf = input.timeframe("60", "Trend Timeframe", group=groupTrend)
emaFastLen = input.int(20, "EMA Fast", group=groupTrend, minval=1)
emaSlowLen = input.int(50, "EMA Slow", group=groupTrend, minval=1)
requireSlope = input.bool(true, "Require EMAs sloping", group=groupTrend)
groupSetup = "Setup Logic"
useVwap = input.bool(true, "Use Session VWAP", group=groupSetup)
minWickTicks = input.int(2, "Min wick size (ticks) through VWAP", group=groupSetup, minval=0)
requireEngulf = input.bool(false, "Require strong rejection body (close beyond midpoint)", group=groupSetup)
groupRisk = "Risk / Exits"
useStops = input.bool(true, "Use stop loss + targets", group=groupRisk)
rrTP1 = input.float(1.0, "TP1 (R multiple)", group=groupRisk, step=0.25)
rrTP2 = input.float(2.0, "TP2 (R multiple)", group=groupRisk, step=0.25)
tp1Pct = input.int(50, "TP1 % qty", group=groupRisk, minval=1, maxval=99)
tp2Pct = 100 - tp1Pct
// ---------- Core Calculations ----------
// ADX
[_, __, adx] = ta.dmi(adxLen, adxLen)
// VWAP (session)
vwap = useVwap ? ta.vwap(hlc3) : na
// 1H EMAs for direction
emaFastHTF = request.security(syminfo.tickerid, htf, ta.ema(close, emaFastLen), barmerge.gaps_off, barmerge.lookahead_off)
emaSlowHTF = request.security(syminfo.tickerid, htf, ta.ema(close, emaSlowLen), barmerge.gaps_off, barmerge.lookahead_off)
// Optional slope filter (simple: current > prior for fast/slow in trend direction)
emaFastHTF_prev = request.security(syminfo.tickerid, htf, ta.ema(close, emaFastLen)[1], barmerge.gaps_off, barmerge.lookahead_off)
emaSlowHTF_prev = request.security(syminfo.tickerid, htf, ta.ema(close, emaSlowLen)[1], barmerge.gaps_off, barmerge.lookahead_off)
bullTrend = emaFastHTF > emaSlowHTF and (not requireSlope or (emaFastHTF > emaFastHTF_prev and emaSlowHTF > emaSlowHTF_prev))
bearTrend = emaFastHTF < emaSlowHTF and (not requireSlope or (emaFastHTF < emaFastHTF_prev and emaSlowHTF < emaSlowHTF_prev))
// Regime filter: "best zone" + hard stop
adxTradable = adx >= adxMin and adx <= adxMax
adxTooHot = adx > adxHardStop
// Tick helper
tick = syminfo.mintick
minWick = minWickTicks * tick
// ---------- Rejection Candles at VWAP ----------
hasVwap = useVwap and not na(vwap)
// Bullish rejection definition:
// - price probes at/through VWAP (low <= vwap - minWick)
// - closes back above VWAP
// - preferably bullish candle
bullReject =
hasVwap and
low <= (vwap - minWick) and
close > vwap and
close > open and
(not requireEngulf or close > (high + low) / 2)
// Bearish rejection definition:
// - price probes at/through VWAP (high >= vwap + minWick)
// - closes back below VWAP
// - preferably bearish candle
bearReject =
hasVwap and
high >= (vwap + minWick) and
close < vwap and
close < open and
(not requireEngulf or close < (high + low) / 2)
// We enter on break of the rejection candle high/low (next bar stop order)
// Use prior bar’s rejection signal to avoid repainting.
bullReject_prev = bullReject[1]
bearReject_prev = bearReject[1]
longStopPrice = high[1] + tick
shortStopPrice = low[1] - tick
// Risk distance (R) based on rejection candle extremes
longSL = low[1] - tick
shortSL = high[1] + tick
longRisk = math.max(longStopPrice - longSL, tick)
shortRisk = math.max(shortSL - shortStopPrice, tick)
longTP1 = longStopPrice + (longRisk * rrTP1)
longTP2 = longStopPrice + (longRisk * rrTP2)
shortTP1 = shortStopPrice - (shortRisk * rrTP1)
shortTP2 = shortStopPrice - (shortRisk * rrTP2)
// ---------- Entry Conditions ----------
canEnter = not adxTooHot and adxTradable
longCond = canEnter and bullTrend and bullReject_prev
shortCond = canEnter and bearTrend and bearReject_prev
// ---------- Orders ----------
if (longCond)
strategy.entry("L", strategy.long, stop=longStopPrice)
if (shortCond)
strategy.entry("S", strategy.short, stop=shortStopPrice)
// ---------- Exits ----------
if useStops
// Long exits
strategy.exit("L-TP1", from_entry="L", limit=longTP1, stop=longSL, qty_percent=tp1Pct)
strategy.exit("L-TP2", from_entry="L", limit=longTP2, stop=longSL, qty_percent=tp2Pct)
// Short exits
strategy.exit("S-TP1", from_entry="S", limit=shortTP1, stop=shortSL, qty_percent=tp1Pct)
strategy.exit("S-TP2", from_entry="S", limit=shortTP2, stop=shortSL, qty_percent=tp2Pct)
// ---------- Plots ----------
plot(useVwap ? vwap : na, "VWAP", linewidth=2)
plot(emaFastHTF, "HTF EMA Fast", color=color.new(color.green, 0))
plot(emaSlowHTF, "HTF EMA Slow", color=color.new(color.red, 0))
// Visual markers for rejection candles
plotshape(bullReject, title="Bull Rejection", style=shape.triangleup, location=location.belowbar, size=size.tiny, color=color.new(color.green, 0), text="BR")
plotshape(bearReject, title="Bear Rejection", style=shape.triangledown, location=location.abovebar, size=size.tiny, color=color.new(color.red, 0), text="SR")
// ---- Entry-ready signals (visual) ----
plotshape(longCond, title="LONG READY", style=shape.labelup, location=location.belowbar, text="LONG", color=color.new(color.green, 0), textcolor=color.white, size=size.tiny)
plotshape(shortCond, title="SHORT READY", style=shape.labeldown, location=location.abovebar, text="SHORT", color=color.new(color.red, 0), textcolor=color.white, size=size.tiny)
plot(longCond ? longStopPrice : na, "Long Stop Entry", style=plot.style_linebr, linewidth=2)
plot(shortCond ? shortStopPrice : na, "Short Stop Entry", style=plot.style_linebr, linewidth=2)
// =====================================================
// ADX DISPLAY (for visibility only)
// =====================================================
showADX = input.bool(true, "Show ADX (pane)", group="Signals / Alerts")
adxPlot = showADX ? adx : na
plot(adxPlot, title="ADX (5m)", color=color.new(color.orange, 0), linewidth=2)
// Reference lines
hline(20, "ADX 20", color=color.new(color.green, 60))
hline(35, "ADX 35", color=color.new(color.yellow, 60))
hline(45, "ADX 45", color=color.new(color.red, 60))