| //@version=6 | |
| strategy( | |
| title = "RSI System v3", | |
| shorttitle = "RSI System", | |
| overlay = true, | |
| initial_capital = 5000, | |
| margin_long = 1, | |
| margin_short = 1, | |
| slippage = 3, | |
| commission_type = strategy.commission.cash_per_order, | |
| commission_value = 0.04) | |
| // ═══════════════════════════════════════════════════════════════════ | |
| // ═══════════════════════════════════════════════════════════════════ | |
| // INPUTS | |
| // ═══════════════════════════════════════════════════════════════════ | |
| tradeDirection = input.string("Both", "Trade Direction", options=["Both", "Long Only", "Short Only"], group="General Settings") | |
| // RSI | |
| rsiLen = input.int (14, "RSI Length", minval=1, group="RSI Settings") | |
| buyThreshold = input.float(60, "Buy Threshold (≥)", step=0.5, group="RSI Settings") | |
| sellThreshold = input.float(30, "Sell Threshold (≤)", step=0.5, group="RSI Settings") | |
| // MA | |
| maSlowLen = input.int (110, "MA Slow Length", minval=2, group="MA Settings") | |
| maFastLen = input.int (20, "MA Fast Length", minval=1, group="MA Settings") | |
| maDistThresh = input.float(6.0, "MA Max Distance (thay thế crossover)", step=0.5, minval=0, group="MA Settings", | |
| tooltip="Nếu maFast đã ở trên/dưới maSlow với khoảng cách < threshold thì vẫn xét vào lệnh (không cần cắt lại)") | |
| // Risk & Exit | |
| atrLen = input.int (14, "ATR Length", minval=1, group="Risk & Exit") | |
| atrMult = input.float(2.5, "ATR Multiplier (SL)", step=0.1, minval=0.1, group="Risk & Exit") | |
| rrRatio = input.float(6.0, "Take Profit (R:R)", step=0.5, minval=0.5, group="Risk & Exit", | |
| tooltip="TP = entry ± SL_dist × R:R. Mặc định 6R") | |
| useTrailSL = input.bool (true, "Trailing SL (ATR động)", group="Risk & Exit", | |
| tooltip="Bật: SL tự trailing theo ATR mỗi bar. Tắt: SL cố định tại mức đặt ban đầu") | |
| riskPct = input.float(0.5, "Risk mỗi lệnh (% vốn)", step=0.1, minval=0.1, maxval=100, group="Risk & Exit", | |
| tooltip="Qty tự tính: mất tối đa riskPct% equity khi chạm SL") | |
| // ═══════════════════════════════════════════════════════════════════ | |
| // INDICATORS | |
| // ═══════════════════════════════════════════════════════════════════ | |
| rsi_indi = ta.rsi(close, rsiLen) | |
| maSlow = ta.sma(rsi_indi, maSlowLen) | |
| maFast = ta.sma(rsi_indi, maFastLen) | |
| atr = ta.atr(atrLen) | |
| ema100 = ta.ema(close, 100) | |
| // Crosses (top-level — tránh lỗi history) | |
| crossUp = ta.crossover (maFast, maSlow) | |
| crossDown = ta.crossunder(maFast, maSlow) | |
| // ═══════════════════════════════════════════════════════════════════ | |
| // ENTRY CONDITIONS | |
| // ═══════════════════════════════════════════════════════════════════ | |
| maDist = maFast - maSlow // dương = fast trên slow | |
| // MA signal: crossover HOẶC fast đã trên slow với khoảng cách < threshold | |
| maSignalUp = crossUp or (maDist > 0 and maDist < maDistThresh) | |
| maSignalDown = crossDown or (maDist < 0 and math.abs(maDist) < maDistThresh) | |
| buyEntry = rsi_indi >= buyThreshold and maSignalUp and close > ema100 and (tradeDirection == "Both" or tradeDirection == "Long Only") | |
| sellEntry = rsi_indi <= sellThreshold and maSignalDown and close < ema100 and (tradeDirection == "Both" or tradeDirection == "Short Only") | |
| // ═══════════════════════════════════════════════════════════════════ | |
| // POSITION STATE | |
| // ═══════════════════════════════════════════════════════════════════ | |
| noPosition = strategy.position_size == 0 | |
| isLong = strategy.position_size > 0 | |
| isShort = strategy.position_size < 0 | |
| // ═══════════════════════════════════════════════════════════════════ | |
| // TRAILING SL + TP STATE | |
| // ═══════════════════════════════════════════════════════════════════ | |
| var float trailSL = na | |
| var float tpLevel = na | |
| var float entryPrice = na | |
| var int entryBar = na | |
| // Reset khi hết lệnh | |
| if noPosition | |
| trailSL := na | |
| tpLevel := na | |
| entryPrice := na | |
| entryBar := na | |
| // Helper: tính qty | |
| calcQty(slDist) => | |
| math.max(strategy.equity * riskPct / 100 / slDist, 0.0001) | |
| // ─── Entry Buy ──────────────────────────────────────────────────── | |
| if buyEntry and noPosition | |
| slDist = atr * atrMult | |
| entryPrice := close | |
| entryBar := bar_index | |
| trailSL := close - slDist | |
| tpLevel := close + slDist * rrRatio | |
| alertMsgBuy = "Buy Entry: " + str.tostring(close, "#.#####") + " | SL: " + str.tostring(trailSL, "#.#####") + " | TP: " + str.tostring(tpLevel, "#.#####") | |
| strategy.entry("Buy", strategy.long, qty=calcQty(slDist), alert_message=alertMsgBuy) | |
| // ─── Entry Sell ─────────────────────────────────────────────────── | |
| if sellEntry and noPosition | |
| slDist = atr * atrMult | |
| entryPrice := close | |
| entryBar := bar_index | |
| trailSL := close + slDist | |
| tpLevel := close - slDist * rrRatio | |
| alertMsgSell = "Sell Entry: " + str.tostring(close, "#.#####") + " | SL: " + str.tostring(trailSL, "#.#####") + " | TP: " + str.tostring(tpLevel, "#.#####") | |
| strategy.entry("Sell", strategy.short, qty=calcQty(slDist), alert_message=alertMsgSell) | |
| // ─── Cập nhật trailing SL mỗi bar ────────────────────────── | |
| if useTrailSL | |
| if isLong | |
| trailSL := math.max(trailSL, close - atr * atrMult) | |
| if isShort | |
| trailSL := math.min(trailSL, close + atr * atrMult) | |
| // ═══════════════════════════════════════════════════════════════════ | |
| // EXIT LOGIC — điều kiện nào đến trước thì thoát | |
| // ═══════════════════════════════════════════════════════════════════ | |
| exitSL_Long = isLong and close < trailSL | |
| exitSL_Short = isShort and close > trailSL | |
| exitTP_Long = isLong and high >= tpLevel | |
| exitTP_Short = isShort and low <= tpLevel | |
| exitMA_Long = isLong and crossDown and not exitSL_Long and not exitTP_Long | |
| exitMA_Short = isShort and crossUp and not exitSL_Short and not exitTP_Short | |
| if exitSL_Long or exitTP_Long | |
| strategy.close("Buy") | |
| if exitMA_Long | |
| alertMsgMALong = "MA Cross Exit Buy | Entry: " + str.tostring(entryPrice, "#.#####") + " | SL: " + str.tostring(trailSL, "#.#####") + " | TP: " + str.tostring(tpLevel, "#.#####") | |
| strategy.close("Buy", alert_message=alertMsgMALong) | |
| if exitSL_Short or exitTP_Short | |
| strategy.close("Sell") | |
| if exitMA_Short | |
| alertMsgMAShort = "MA Cross Exit Sell | Entry: " + str.tostring(entryPrice, "#.#####") + " | SL: " + str.tostring(trailSL, "#.#####") + " | TP: " + str.tostring(tpLevel, "#.#####") | |
| strategy.close("Sell", alert_message=alertMsgMAShort) | |
| // ═══════════════════════════════════════════════════════════════════ | |
| // VISUALS | |
| // ═══════════════════════════════════════════════════════════════════ | |
| plot(ema100, "EMA 100", color=color.white, linewidth=2) | |
| // Trailing SL line | |
| pClose = plot(close, "Close", display=display.none) | |
| pTrailSL = plot(isLong or isShort ? trailSL : na, | |
| "Trailing SL", color=color.new(color.red, 0), linewidth=2, style=plot.style_linebr) | |
| fill(pClose, pTrailSL, | |
| color = isLong or isShort ? color.new(color.red, 85) : na, title="SL Zone") | |
| // Exit markers | |
| plotshape(exitSL_Long or exitSL_Short, | |
| "Exit: SL", shape.xcross, location.abovebar, | |
| color.new(color.red, 0), size=size.small, text="SL", textcolor=color.red) | |
| plotshape(exitTP_Long or exitTP_Short, | |
| "Exit: TP", shape.triangleup, location.abovebar, | |
| color.new(color.lime, 0), size=size.small, text="TP", textcolor=color.lime) | |
| plotshape(exitMA_Long or exitMA_Short, | |
| "Exit: MA", shape.xcross, location.abovebar, | |
| color.new(color.orange, 0), size=size.small, text="MA", textcolor=color.orange) |
Xet Storage Details
- Size:
- 9.98 kB
- Xet hash:
- 900d9f504497ceef48b36a50ef82053e6c5ea8fbaa782a47d0c63958299798cd
·
Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.