Pine Script技术问询:为何止损单在入场止损触发时即刻生效?
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:
- Swapped
loss/profitforstop/limit: This aligns with your intended logic of using absolute price levels for stop loss and take profit. - Fixed
etf_dsecurity call: Now correctly pulls entry timeframe data instead of middle timeframe data. - Updated plot labels: Removed duplicate labels to make the indicator easier to interpret.
- Improved cancellation logic: Checks if the entry order is active before evaluating the stop condition, avoiding
navalue errors.
This should resolve the immediate stop loss trigger issue and clean up other minor inconsistencies in your code.
内容的提问来源于stack exchange,提问作者Barry Weinberg

