트렌드 서핑 전략

RSI EMA ATR VOLUME
생성 날짜: 2025-10-09 11:21:13 마지막으로 수정됨: 2025-10-09 11:21:13
복사: 0 클릭수: 267
avatar of ianzeng123 ianzeng123
2
집중하다
319
수행원

트렌드 서핑 전략 트렌드 서핑 전략

♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️ ♂️

이 전략은 매우 민감한 “트렌드 레이더”와 같습니다. 그것은 맹목적으로 추격하는 전략이 아니라 완벽한 파도가 나올 때까지 기다리는 인내심있는 서퍼와 같습니다.

RSI 동력 엔진 🚀

  • 기본 14주기 RSI, 50선을 돌파하면 입장이 고려됩니다.
  • 4가지의 트리거 모드를 선택할 수 있습니다. 보수적인 “단순히 교차”에서 급진적인 “任意突破”까지
  • 30K 가닥의 오차 시간을 주는 “아름다운 창” 디자인도 있습니다.

이중 EMA 필터링 시스템 📈

  • EMA20는 단기 동력을 확인하고, EMA200는 주 트렌드를 고정합니다.
  • 가격만 동시 2개의 평행선 위에 서면 녹색등을 켜면 됩니다
  • 그것은 마치 운전하는 동안 동시에 가솔린과 브레이크를 누르는 것과 같습니다.

바람 조절이 너무 세심하게 설계되었습니다!

일일일 원칙 📅
우선순위를 정하라! 하루에 한 번만 거래하고, 반복되는 시도와 실수를 피하라. 이것은 훌륭한 사냥꾼이 하루에 10마리의 토끼를 잡는 대신 가장 뚱뚱한 토끼를 잡는 것에 집중하는 것과 같다.

ATR 동적 상쇄 🛡️

  • 1.5배의 ATR 설정 스톱로스, 시장의 변동에 따라 자동으로 조정
  • 2배의 리스크와 수익을 가져오며, 손실보다 더 빨리 수익을 올립니다.
  • 선택적 스톱 트래킹으로 큰 트렌드에서 승리할 수 있습니다.

이 전략은 누구에게 가장 적합할까요?

가장 좋은 사용 시나리오

  • 유행성 강한 품종 (주식 지수, 주류 화폐, 대시장 주식)
  • 일선 또는 4 시간 레벨에서 가장 잘 작동합니다.
  • 인내심을 가진 중선 거래자에게 적합합니다.

주의사항

  • 위축 시장의 경우, 위축 시장에서 돈을 벌 수 있다고 기대하지 마십시오.
  • 기초적인 분석이 필요하고, 기술적인 분석은 만능이 아닙니다.
  • 가장 적합한 매개 변수를 찾기 위해 시뮬레이션 디스크 테스트를 권장합니다.

이 전략의 핵심은 “바람이 올 때까지 기다려야 한다”는 것입니다. 매일 완벽한 거래 기회가 생기는 것은 아니지만, 한번 생겨나면 성공률은 매우 높습니다!

전략 소스 코드
/*backtest
start: 2025-07-01 00:00:00
end: 2025-10-08 00:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT","balance":500000}]
*/

//@version=6
strategy("FirstStrike Long 200 Daily Trend Rider [KedArc Quant]",
     overlay=true,
     initial_capital=100000,
     default_qty_type=strategy.percent_of_equity,
     default_qty_value=10,
     commission_type=strategy.commission.percent,
     commission_value=0.01,
     pyramiding=0,
     calc_on_every_tick=false,
     process_orders_on_close=true)

//@author [KedArc Quant]
//@created on 02-Sep-2025

// ========= Inputs =========
groupRSI   = "RSI / Trigger"
rsiLen     = input.int(14, "RSI Length", minval=2, tooltip="Period for RSI calculation.", group=groupRSI)
rsiTrigger = input.int(50, "Trigger Level (RSI >= this)", minval=1, maxval=99, tooltip="RSI must cross/sustain above this for entry.", group=groupRSI)
triggerMode = input.string("Any bar >= trigger", "Trigger mode", options=["Cross only", "Cross+Grace", "Cross+Grace+Sustain", "Any bar >= trigger"], tooltip="Modes for RSI trigger: 'Cross only' for precise, 'Any bar' for opportunistic.", group=groupRSI)
graceBars   = input.int(30, "Grace window (bars) after cross", minval=0, maxval=500, tooltip="Bars after RSI cross where entry is still allowed if RSI >= trigger.", group=groupRSI)
sustainBars = input.int(3, "Sustain bars (RSI >= trigger)", minval=1, maxval=100, tooltip="Consecutive bars RSI must stay >= trigger for sustain mode.", group=groupRSI)
requireDip  = input.bool(false, "Require RSI dip below Rearm before any entry?", tooltip="If true, needs RSI < Rearm level post-reset before entry.", group=groupRSI)
rsiRearm    = input.int(45, "Rearm level (if requireDip=true)", minval=1, maxval=99, tooltip="RSI level below which a dip 'rearms' eligibility.", group=groupRSI)

groupEMA   = "Trend / Filters"
emaFastLen = input.int(20, "EMA (fast) confirmation", minval=1, tooltip="Short EMA for price action filter (close > EMA).", group=groupEMA)
emaTrend   = input.int(200, "EMA (trend filter)", minval=50, tooltip="Long EMA for overall trend (close > EMA200).", group=groupEMA)

groupTime  = "Optional Hour Window"
useSession = input.bool(false, "Restrict by Session?", tooltip="Use TradingView session string for precise market hours.", group=groupTime)
sessionStr = input("0930-1600", "Session (e.g., 0930-1600 for NYSE)", tooltip="Session format: HHMM-HHMM in exchange timezone.", group=groupTime)
useTime    = input.bool(false, "Restrict by Hour Range?", tooltip="Fallback to simple hour range if session not used.", group=groupTime)
startHour  = input.int(9,  "Start Hour", minval=0, maxval=23, group=groupTime)
endHour    = input.int(15, "End Hour",   minval=0, maxval=23, group=groupTime)

groupVol = "Volume Filter"
useVol = input.bool(false, "Require Volume > SMA?", tooltip="Filter entries to high-volume bars only.", group=groupVol)
volLen = input.int(20, "Volume SMA Length", minval=1, tooltip="SMA period for volume average.", group=groupVol)

groupRisk  = "Risk / Exits"
atrLen   = input.int(14, "ATR Length", minval=1, tooltip="Period for ATR volatility calculation.", group=groupRisk)
atrMult  = input.float(1.5, "ATR Stop Multiplier", step=0.1, tooltip="Multiplier for initial stop-loss distance.", group=groupRisk)
riskRR   = input.float(2.0, "Take-Profit R Multiple", step=0.1, tooltip="Risk-reward ratio for fixed TP.", group=groupRisk)
useTrail = input.bool(false, "Use Trailing Stop?", tooltip="Activate trailing stop after entry for trend capture.", group=groupRisk)
trailMult = input.float(2.0, "Trailing ATR Multiplier", step=0.1, tooltip="ATR multiplier for trailing stop distance.", group=groupRisk)

// ========= Calculations =========
hr      = hour(time)
inSession = useSession ? time(timeframe.period, sessionStr) != 0 : true
inHours = useSession ? inSession : (useTime ? (hr >= startHour and hr <= endHour) : true)

emaFast = ta.ema(close, emaFastLen)
ema200  = ta.ema(close, emaTrend)
rsi     = ta.rsi(close, rsiLen)
atr     = ta.atr(atrLen)
volSMA = ta.sma(volume, volLen)

// Trend filters (long-only)
trendOK = close > ema200
priceOK = close > emaFast
volOK = useVol ? volume > volSMA : true

// ----- One-trade-per-day gate -----
newDay = ta.change(time("D"))
var bool tookTradeToday = false
if newDay != 0
    tookTradeToday := false

// ----- Rearm (optional pullback requirement) -----
var bool rearmed = not requireDip
if requireDip and rsi < rsiRearm
    rearmed := true
if newDay != 0
    rearmed := not requireDip  // Reset to false if required, else true

// ----- Trigger logic variants -----
crossNow       = ta.crossover(rsi, rsiTrigger)
var int lastCrossBarIndex = na
if newDay != 0
    lastCrossBarIndex := na
if crossNow
    lastCrossBarIndex := bar_index

withinGrace = graceBars > 0 and not na(lastCrossBarIndex) and (bar_index - lastCrossBarIndex) <= graceBars and rsi >= rsiTrigger

// Sustain: RSI has been >= trigger for sustainBars consecutive bars
sinceBelow  = ta.barssince(rsi < rsiTrigger)
sustainOK   = not na(sinceBelow) and sinceBelow >= sustainBars

anyBarOK    = rsi >= rsiTrigger

bool triggerOK = switch triggerMode
    "Cross only"              => crossNow
    "Cross+Grace"             => (crossNow or withinGrace)
    "Cross+Grace+Sustain"     => ((crossNow or withinGrace) and sustainOK)  // AND for post-cross sustain
    "Any bar >= trigger"      => anyBarOK

// Final entry condition (one long per day)
longCond = inHours and trendOK and priceOK and rearmed and triggerOK and volOK and not tookTradeToday and strategy.position_size == 0

// ========= Orders =========
if longCond
    strategy.entry("Long", strategy.long)
    tookTradeToday := true
    rearmed := false
    label.new(bar_index, low, "LONG\nRSI:" + str.tostring(rsi, "#.#"), color=color.green, style=label.style_label_up, size=size.small)

if strategy.position_size > 0
    avg       = strategy.position_avg_price
    stopPrice = avg - atrMult * atr
    riskPS    = avg - stopPrice
    limitPx   = avg + riskRR * riskPS
    strategy.exit("TP/SL", from_entry="Long", stop=stopPrice, limit=limitPx)
    
    if useTrail
        trailStop = close - trailMult * atr  // Simple close-based trail
        strategy.exit("Trail", from_entry="Long", trail_price=trailStop, trail_offset=0)

// ========= Visuals (minimal) =========
plot(ema200, "EMA 200 (Trend)", color=color.new(color.blue, 0), linewidth=2)
plot(emaFast, "EMA Fast", color=color.new(color.orange, 0))
plot(strategy.position_size != 0 ? strategy.position_avg_price : na, "Entry Px", color=color.new(color.green, 0), style=plot.style_linebr)
bgcolor(longCond ? color.new(color.green, 90) : na, title="Entry Signal")

alertcondition(longCond, title="FirstStrike Long Entry", message="Long entry triggered at {{close}}")