You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Pine Script技术问询:为何止损单在入场止损触发时即刻生效?

MTF Stoch RSI Strategy: Fixing Immediate Stop Loss Trigger Issue

Hey there, let's break down why your stop loss is firing the second your entry stop fills—this is a super common Pine Script gotcha, and I can spot exactly where things went off track.

Root Cause: Misusing strategy.exit Parameters

The biggest issue is how you're using loss and profit in your strategy.exit calls. Those parameters expect a distance from the entry price (in ticks, points, or currency), not absolute price levels.

When you pass something like loss=LongLowStop, you're telling the strategy to exit if the position loses LongLowStop points. Since LongLowStop is a price (like 1.07500 for EUR/USD), that's an enormous "loss threshold"—so as soon as your entry fills, the strategy thinks the loss condition is already met and triggers the exit immediately.

Fix 1: Use stop and limit for Absolute Prices

Instead of loss and profit, use the stop parameter for your stop loss price, and limit for your take profit price. These parameters accept absolute price values, which is exactly what you calculated with LongLowStop and LongProfit.

Fix 2: Correct the etf_d Security Call

I also noticed a typo in your etf_d assignment—you were using mtf_security instead of etf_security. This would pull the wrong timeframe data for your entry signal, which could cause unexpected triggers or false signals.

Fix 3: Refine Order Cancellation Logic

Your original cancellation logic checked low < LongLowStop when no position was open, but since LongLowStop is only set when goLong is true, this would evaluate to na most of the time. I updated it to only check if the entry order is actually active first.

Modified Working Code

Here's the corrected version of your strategy with all these fixes applied:

// MTF Stochastic RSI Strategy by
// © drbarry92064859
//@version=4
strategy("Stochastic RSI Bands Strategy", "StochRSI Band Strategy", overlay = false, initial_capital = 1000, default_qty_value = 100, default_qty_type = strategy.percent_of_equity)
prevRep = true

// Timeframe settings
etf = input("15", "Entry Timeframe", input.resolution, options=["1","5","15","60"])
mtf = input("240", "Middle Timeframe", input.resolution, options= ["60","240","D"])
htf = input("D", "Higher Timeframe", input.resolution, options=["240","D","W","M"])

//Which Timeframes to use Settings
showetf = input(false, "Show Entry Timeframe", input.bool)
showmtf = input(true, "Show Middle Timeframe", input.bool)
showhtf = input(true, "Show Higher Timeframe", input.bool)

//StochRSI Settings
etf_lengthRSI = input(13, "Entry TimeFrame RSI Length", options=[8, 13, 21, 34])
mtf_lengthRSI = input(13, "Middle TimeFrame RSI Length", options=[8, 13, 21, 34])
htf_lengthRSI = input(13, "Higher TimeFrame RSI Length", options=[8, 13, 21, 34])

htf_srsi_settings(htf_lengthRSI) =>
    htf_lengthStoch = htf_lengthRSI==8 ? 5 : htf_lengthRSI==13 ? 8 : htf_lengthRSI==21 ? 13 : 21
    htf_smoothK = htf_lengthRSI==8 ? 3 : htf_lengthRSI==13 ? 5 : htf_lengthRSI==21 ? 8 : 13
    htf_smoothD = htf_lengthRSI==8 ? 3 : htf_lengthRSI==13 ? 5 : htf_lengthRSI==21 ? 8 : 13
    [htf_lengthStoch, htf_smoothK, htf_smoothD]

mtf_srsi_settings(mtf_lengthRSI) =>
    mtf_lengthStoch = mtf_lengthRSI==8 ? 5 : mtf_lengthRSI==13 ? 8 : mtf_lengthRSI==21 ? 13 : 21
    mtf_smoothK = mtf_lengthRSI==8 ? 3 : mtf_lengthRSI==13 ? 5 : mtf_lengthRSI==21 ? 8 : 13
    mtf_smoothD = mtf_lengthRSI==8 ? 3 : mtf_lengthRSI==13 ? 5 : mtf_lengthRSI==21 ? 8 : 13
    [mtf_lengthStoch, mtf_smoothK, mtf_smoothD]

etf_srsi_settings(etf_lengthRSI) =>
    etf_lengthStoch = etf_lengthRSI==8 ? 5 : etf_lengthRSI==13 ? 8 : etf_lengthRSI==21 ? 13 : 21
    etf_smoothK = etf_lengthRSI==8 ? 3 : etf_lengthRSI==13 ? 5 : etf_lengthRSI==21 ? 8 : 13
    etf_smoothD = etf_lengthRSI==8 ? 3 : etf_lengthRSI==13 ? 5 : etf_lengthRSI==21 ? 8 : 13
    [etf_lengthStoch, etf_smoothK, etf_smoothD]

overbought = input(75, minval=1)
oversold = input(25, minval=1)

//StochRSI Calculation
[htf_lengthStoch, htf_smoothK, htf_smoothD] = htf_srsi_settings(htf_lengthRSI)
[mtf_lengthStoch, mtf_smoothK, mtf_smoothD] = mtf_srsi_settings(mtf_lengthRSI)
[etf_lengthStoch, etf_smoothK, etf_smoothD] = etf_srsi_settings(etf_lengthRSI)

src = input(close, title="RSI Source")

etf_rsi1 = rsi(src, etf_lengthRSI)
htf_rsi1 = rsi(src, htf_lengthRSI)
mtf_rsi1 = rsi(src, mtf_lengthRSI)

etf_k_sma = sma(stoch(etf_rsi1, etf_rsi1, etf_rsi1, etf_lengthStoch), etf_smoothK)
etf_d_sma = sma(etf_k_sma, etf_smoothD)

htf_k_sma = sma(stoch(htf_rsi1, htf_rsi1, htf_rsi1, htf_lengthStoch), htf_smoothK)
htf_d_sma = sma(htf_k_sma, htf_smoothD)

mtf_k_sma = sma(stoch(mtf_rsi1,mtf_rsi1, mtf_rsi1, mtf_lengthStoch), mtf_smoothK)
mtf_d_sma = sma(mtf_k_sma, mtf_smoothD)

// Function to securely and simply call `security()` so that it never repaints and never looks ahead.
htf_security(_sym, _res, _src, _rep) => security(_sym, _res, _src[not _rep and barstate.isrealtime ? 1 : 0])[_rep or barstate.isrealtime ? 0 : 1]
mtf_security(_sym, _res, _src, _rep) => security(_sym, _res, _src[not _rep and barstate.isrealtime ? 1 : 0])[_rep or barstate.isrealtime ? 0 : 1]
etf_security(_sym, _res, _src, _rep) => security(_sym, _res, _src[not _rep and barstate.isrealtime ? 1 : 0])[_rep or barstate.isrealtime ? 0 : 1]

// Get all timeframe srsi data
htf_k = htf_security(syminfo.tickerid, htf, htf_k_sma, not prevRep)
htf_d = htf_security(syminfo.tickerid, htf, htf_d_sma, not prevRep)
mtf_k = mtf_security(syminfo.tickerid, mtf, mtf_k_sma, not prevRep)
mtf_d = mtf_security(syminfo.tickerid, mtf, mtf_d_sma, not prevRep)
etf_k = etf_security(syminfo.tickerid, etf, etf_k_sma, not prevRep)
etf_d = etf_security(syminfo.tickerid, etf, etf_d_sma, not prevRep) // Fixed typo here

//Plot SRSI
plot(htf_k,"HTF Fast SRSI", color.blue, linewidth=4)
plot(htf_d,"HTF Slow SRSI", color.red, linewidth=4)
plot(mtf_k,"MTF Fast SRSI", color.blue, linewidth=2) // Fixed duplicate label
plot(mtf_d,"MTF Slow SRSI", color.red, linewidth=2) // Fixed duplicate label
plot(etf_k,"ETF Fast SRSI", color.blue, linewidth=1) // Fixed duplicate label
plot(etf_d,"ETF Slow SRSI", color.red, linewidth=1) // Fixed duplicate label

hline(overbought, color=color.black, linestyle=hline.style_dashed)
hline(oversold, color=color.black, linestyle=hline.style_dashed)

//StochRSI Positions
htfBull = htf_k > htf_d
htfBear = htf_k < htf_d
mtfBull = mtf_k > mtf_d
mtfBear = mtf_k < mtf_d

etfBullCO = etf_k[1] < etf_d[1] and etf_k > etf_d and etf_k[1] <= oversold and etf_d[1] <= oversold
etfBearCO = etf_d[1] < etf_k[1] and etf_d > etf_k and etf_k[1] >= overbought and etf_d[1] >= overbought

htfOB = htf_k >= overbought and htf_d >= overbought
htfOS = htf_k <= oversold and htf_d <= oversold
mtfOB = mtf_k >= overbought and mtf_d >= overbought
mtfOS = mtf_k <= oversold and mtf_d <= oversold

//StochRsi Bands
htf_srsiLong = (htfBull and not htfOB) or (htfBear and htfOS)
htf_srsiShort = (htfBear and not htfOS) or (htfBull and htfOB)
mtf_srsiLong = (mtfBull and not mtfOB) or (mtfBear and mtfOS)
mtf_srsiShort = (mtfBear and not mtfOS) or (mtfBull and mtfOB)

//Strategy Orders
//Long Entry
float LongHighEntry = na
float LongLowStop = na
float LongProfit = na

goLong = etfBullCO and htf_srsiLong and strategy.position_size == 0

if goLong
    LongHighEntry := high[1] + syminfo.mintick * 50
    LongLowStop := low[1] - syminfo.mintick * 100
    LongProfit := (LongHighEntry - LongLowStop) + LongHighEntry
    strategy.entry("Open Long", strategy.long, stop=LongHighEntry)
    // Use stop and limit instead of loss and profit for absolute prices
    strategy.exit("Long Exit", "Open Long", stop=LongLowStop, limit=LongProfit )

plot(LongHighEntry, "LongEntry", color.blue, 3, plot.style_linebr)
plot(LongLowStop, "LongStopLoss", color.red, 3, plot.style_linebr)
plot(LongProfit, "LongProfit", color.green, 3, plot.style_linebr)

//Long Cancel Trade if Hits StopLoss or Enters Red Zone before Entry
strategy.cancel("Open Long", when = strategy.order.size("Open Long") > 0 and low < LongLowStop )

//Short Entry
float ShortLowEntry = na
float ShortHighStop = na
float ShortProfit = na

goShort = etfBearCO and htf_srsiShort and strategy.position_size == 0

if goShort
    ShortLowEntry := low[1] - syminfo.mintick * 50
    ShortHighStop := high[1] + syminfo.mintick * 100
    ShortProfit := (ShortLowEntry - ShortHighStop) + ShortLowEntry
    strategy.entry("Open Short", strategy.short, stop=ShortLowEntry)
    // Use stop and limit instead of loss and profit for absolute prices
    strategy.exit("Short Exit", "Open Short", stop=ShortHighStop, limit=ShortProfit)

plot(ShortLowEntry, "ShortEntry", color.blue, 3, plot.style_linebr)
plot(ShortHighStop, "ShortStopLoss", color.red, 3, plot.style_linebr)
plot(ShortProfit, "ShortProfit", color.green, 3, plot.style_linebr)

strategy.cancel("Open Short", when = strategy.order.size("Open Short") > 0 and high > ShortHighStop )

Key Changes Made:

  1. Swapped loss/profit for stop/limit: This aligns with your intended logic of using absolute price levels for stop loss and take profit.
  2. Fixed etf_d security call: Now correctly pulls entry timeframe data instead of middle timeframe data.
  3. Updated plot labels: Removed duplicate labels to make the indicator easier to interpret.
  4. Improved cancellation logic: Checks if the entry order is active before evaluating the stop condition, avoiding na value errors.

This should resolve the immediate stop loss trigger issue and clean up other minor inconsistencies in your code.

内容的提问来源于stack exchange,提问作者Barry Weinberg

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.28 20:04:04