Two-Pole Smoothing Oscillator Strategy

SMA stdev EMA CROSSOVER CROSSUNDER
Created on: 2025-10-17 15:20:53 Modified on: 2025-10-17 15:20:53
Copy: 0 Number of hits: 262
avatar of ianzeng123 ianzeng123
2
Follow
323
Followers

 Two-Pole Smoothing Oscillator Strategy  Two-Pole Smoothing Oscillator Strategy

🎯 What’s This Amazing Strategy?

You know what? This strategy is like installing an “emotion detector” for the market! 📡 It uses a two-pole smoothing oscillator to sense the market’s “moods” - when the market gets too excited (overbought) or too depressed (oversold), it sends out trading signals. Key point! This isn’t your ordinary oscillator, but a premium version with “double beauty filter” processing that effectively filters out market noise, helping you see the real trend direction.

💡 How It Works - The Big Reveal

Imagine this strategy as a super-sensitive “market thermometer” 🌡️. First, it calculates how much prices deviate from the 25-period moving average, then standardizes this (like converting people of different heights to standard height ratios). Next comes the crucial “double smoothing” process, like applying two beauty filters to a photo consecutively, making signals clearer and more reliable. When the oscillator breaks through set thresholds, the strategy strikes decisively!

⚡ This Strategy’s Superpowers

Pitfall guide incoming! The most powerful feature is its “reverse signal exit” mechanism - as smart as hitting the brakes immediately when seeing a red light while driving! 🚦 When opposite signals appear, the strategy closes positions immediately without stubbornly holding on. Plus there’s 5-period fixed stop-loss protection, like adding an “airbag” to your capital. Most thoughtfully, it comes with complete trading statistics, keeping you informed of strategy performance at all times!

🚨 Risk Warnings Are Essential

Key point! While this strategy is excellent, it’s not omnipotent. In strong trending markets, the oscillator might get “lost,” like using city navigation on a highway - not quite suitable. Fixed threshold settings might not adapt well to different market environments, requiring flexible adjustments based on actual conditions. Remember, any strategy needs good risk management - don’t put all your eggs in one basket!

Strategy source code
/*backtest
start: 2025-01-01 00:00:00
end: 2025-10-15 08:00:00
period: 1h
basePeriod: 1h
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT","balance":500000}]
*/

//@version=6
strategy("Two-Pole Threshold Entries + Opposite-Signal & Stop Exits + Stats",
     overlay=true,
     max_labels_count=500)

// === Inputs ===
length       = input.int(20,    minval=1,    title="Filter Length")
buyTrig      = input.float(-0.8,             title="Buy Threshold (osc ↑)")
sellTrig     = input.float( 0.8,             title="Sell Threshold (osc ↓)")
stopLossPts  = input.int(10,    minval=1,    title="Stop Loss (pts)")

// === Two-Pole Oscillator ===
sma25 = ta.sma(close, 25)
dev   = (close - sma25) - ta.sma(close - sma25, 25)
norm  = dev / ta.stdev(close - sma25, 25)
alpha = 2.0 / (length + 1)

var float s1 = na
var float s2 = na
s1 := na(s1) ? norm : (1 - alpha) * s1 + alpha * norm
s2 := na(s2) ? s1   : (1 - alpha) * s2 + alpha * s1

osc     = s2
prevOsc = osc[4]

// === Trigger Cross Signals ===
isLongSig  = ta.crossover(osc, buyTrig)  and barstate.isconfirmed
isShortSig = ta.crossunder(osc, sellTrig) and barstate.isconfirmed

// === State & Stats Vars ===
var int   tradeDir    = 0      //  1=long, -1=short, 0=flat
var float entryPrice = na
var int   entryBar   = na

var int   buyTotal    = 0
var int   buyFailed   = 0
var float sumMoveB    = 0.0
var int   cntMoveB    = 0
var float sumPLptsB   = 0.0

var int   sellTotal   = 0
var int   sellFailed  = 0
var float sumMoveS    = 0.0
var int   cntMoveS    = 0
var float sumPLptsS   = 0.0

// === Exit Marker Flags ===
var bool longStopHit  = false
var bool shortStopHit = false
var bool longSigExit  = false
var bool shortSigExit = false

longStopHit  := false
shortStopHit := false
longSigExit  := false
shortSigExit := false

// === 1) Opposite-Signal Exit ===
if tradeDir == 1 and isShortSig
    float ptsL = close - entryPrice
    sumMoveB  += ptsL
    sumPLptsB += ptsL
    cntMoveB  += 1
    strategy.close("Long")
    longSigExit := true
    tradeDir    := 0

if tradeDir == -1 and isLongSig
    float ptsS = entryPrice - close
    sumMoveS  += ptsS
    sumPLptsS += ptsS
    cntMoveS  += 1
    strategy.close("Short")
    shortSigExit := true
    tradeDir     := 0

// === 2) 5-Bar, Bar-Close 10-pt Stop Exit ===
inWindow       = (tradeDir != 0) and (bar_index <= entryBar + 5)
longStopPrice  = entryPrice - stopLossPts
shortStopPrice = entryPrice + stopLossPts

if tradeDir == 1 and inWindow and close <= longStopPrice
    buyFailed   += 1
    sumPLptsB   -= stopLossPts
    strategy.close("Long")
    longStopHit := true
    tradeDir    := 0

if tradeDir == -1 and inWindow and close >= shortStopPrice
    sellFailed   += 1
    sumPLptsS    -= stopLossPts
    strategy.close("Short")
    shortStopHit := true
    tradeDir     := 0

// === 3) New Entries (only when flat) ===
if tradeDir == 0 and isLongSig
    buyTotal   += 1
    entryPrice := close
    entryBar   := bar_index
    strategy.entry("Long", strategy.long)
    tradeDir   := 1

if tradeDir == 0 and isShortSig
    sellTotal  += 1
    entryPrice := close
    entryBar   := bar_index
    strategy.entry("Short", strategy.short)
    tradeDir   := -1

// === Stats Computation ===
float avgMoveB    = cntMoveB  > 0 ? sumMoveB  / cntMoveB  : na
float successPctB = buyTotal   > 0 ? (buyTotal - buyFailed) / buyTotal  * 100 : na
float pnlUSD_B    = sumPLptsB * 50.0

float avgMoveS    = cntMoveS  > 0 ? sumMoveS  / cntMoveS  : na
float successPctS = sellTotal  > 0 ? (sellTotal - sellFailed) / sellTotal * 100 : na
float pnlUSD_S    = sumPLptsS * 50.0

string tf = timeframe.period



// === On-Chart Markers ===
plotshape(isLongSig,  title="Long Entry",      style=shape.triangleup,   location=location.belowbar, color=color.green,  size=size.tiny)
plotshape(isShortSig, title="Short Entry",     style=shape.triangledown, location=location.abovebar, color=color.red,    size=size.tiny)
plotshape(longSigExit,  title="Exit on Sell Sig", style=shape.xcross, location=location.abovebar, color=color.orange, size=size.tiny)
plotshape(shortSigExit, title="Exit on Buy Sig",  style=shape.xcross, location=location.belowbar, color=color.orange, size=size.tiny)
plotshape(longStopHit,  title="Stop Exit Long",  style=shape.xcross, location=location.abovebar, color=color.purple, size=size.tiny)
plotshape(shortStopHit, title="Stop Exit Short", style=shape.xcross, location=location.belowbar, color=color.purple, size=size.tiny)