
Esta estratégia é como colocar um “detector de emoção” no mercado! Oh, ele percebe o “felicidade” do mercado através de um oscilador de equilíbrio bipolar, e emite um sinal de negociação quando o mercado está muito excitado (supercompra) ou muito frustrado (supervenda).
Imagine que a estratégia é como um super-sensível “metro de temperatura do mercado”. Primeiro, ela calcula o desvio do preço em relação à média de 25 ciclos, e depois faz o processamento padronizado (como trocar pessoas de diferentes alturas por proporções de alturas padrão).
O melhor desta estratégia é o seu mecanismo de compensação de sinal inverso - é tão inteligente quanto parar imediatamente quando você vê um sinal vermelho ao dirigir! Oh, quando o sinal oposto aparece, a estratégia se compensa imediatamente e não fica paralisada.
A estratégia é excelente, mas não é universal. Em mercados de forte tendência, os oscilantes podem ficar “perdidos”, como se fosse o uso de navegação urbana em uma auto-estrada. A configuração de limiares fixos pode ser desagradável em diferentes ambientes de mercado, exigindo que você ajuste com flexibilidade de acordo com a situação real.
/*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)