趋势冲浪策略

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突破50线 + 价格站上EMA200 = 趋势来了,冲!

📊 技术指标组合拳,每一拳都很精准

RSI动量引擎 🚀
- 默认14周期RSI,突破50线才考虑入场 - 四种触发模式可选:从保守的”仅交叉”到激进的”任意突破” - 还有”优雅窗口”设计,给你30根K线的容错时间

双EMA过滤系统 📈
- EMA20确认短期动能,EMA200锁定主趋势 - 只有价格同时站上两条均线才开绿灯 - 这就像开车要同时踩油门和松刹车一样自然

⚡ 风控设计太贴心了!

一天一单原则 📅
划重点!每天最多只做一笔交易,避免频繁试错。这就像好的猎手不会一天打十只兔子,而是专注打那只最肥的。

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}}")
相关推荐