Last active
May 18, 2025 02:46
-
-
Save davidsaccavino/e5414d7280e2b9c6d0cc7234cf4eb0a4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//@version=5 | |
// Author: David Saccavino | |
// Last Update: November 25th, 2022 | |
// Saccavino Venture Capital, LLC - All Rights Reserved. | |
strategy("Stochastic/OBV-Weighted SuperTrend Strategy", overlay = true) | |
// backtesting boilerplate | |
startDate = timestamp("1950-01-01T00:00:00") | |
finishDate = timestamp("2023-01-01T00:00:00") | |
time_cond = time >= startDate and time <= finishDate | |
PL = strategy.opentrades.profit(strategy.opentrades - 1) | |
// * | |
// Start of: Initalize the Indicators | |
// | |
// Moving Average | |
smaWeightingToggle = input(false, "Enable short-term SMA weighting:") | |
shortSMALength = input(8, "Short SMA Length:") | |
shortSMA = ta.sma(close, shortSMALength) | |
// Average True Range | |
atrSrc = input(hl2, "ATR Source:") | |
atrMultiplier = input(3, "ATR Multiplier:") | |
atrPeriod = input(10, "ATR Period:") | |
atr = ta.sma(ta.tr, atrPeriod) | |
atrUp = atrSrc - (atrMultiplier * atr) | |
atrUpInit = nz(atrUp[1],atrUp) | |
atrUp := close[1] > atrUpInit ? math.max(atrUp,atrUpInit) : atrUp | |
atrDown = atrSrc + (atrMultiplier * atr) | |
atrDownInit = nz(atrDown[1], atrDown) | |
atrDown := close[1] < atrDownInit ? math.min(atrDown, atrDownInit) : atrDown | |
// SuperTrend | |
superTrend = 1 | |
superTrend := nz(superTrend[1], superTrend) | |
superTrend := superTrend == -1 and close > atrDownInit ? 1 : superTrend == 1 and close < atrUpInit ? -1 : superTrend | |
// Stochastic | |
stochSrc = input(close, "Stochastic Source:") | |
stochLen = input(14, "Stochastic Length:") | |
stochK = ta.stoch(stochSrc, high, low, stochLen) | |
stochD = ta.rma(stochK, 3) | |
// MACD | |
macdSrc = input(close, "MACD Source:") | |
[macdLine, signalLine, histLine] = ta.macd(macdSrc, 12, 26, 9) | |
// On-Balance-Volume | |
smma = 0.0 | |
obvSrc = input(close, "OBV Source:") | |
obvLen = input(8, "OBV Length:") | |
obv = ta.cum(math.sign(ta.change(obvSrc)) * volume) | |
obvMA = ta.sma(obv, obvLen) | |
smma := na(smma[1]) ? obvMA : (smma[1] * (obvLen - 1) + obv) / obvLen | |
// | |
// End of: Initalize the Indicators | |
// * | |
// * | |
// Start of: Logic gates for determining bullish or bearish sentiment | |
// | |
// OBV Bullish/Bearish logic gates | |
bullishOBV = ta.crossover(obv, smma) or obv > smma | |
bearishOBV = ta.crossunder(smma, obv) or obv < smma | |
// MACD Bullish/Bearish logic gates | |
bullishMACD = (ta.crossover(macdLine, signalLine) or (macdLine > signalLine + 0.25)) | |
bearishMACD = (ta.crossunder(macdLine, signalLine) or (macdLine < signalLine)) | |
// Stochastic Bullish/Bearish logic gates | |
bearishStochastic = (stochK < 60 and stochD > (stochK + 1.5)) or stochK < 40 | |
bullishStochastic = stochK > 60 and stochK > (stochD + 1.5) | |
// Aggregated Oscillator Bullish/Bearish logic gates | |
bullishOscillators = bullishOBV and bullishStochastic and bullishMACD and close > shortSMA | |
bearishOscillators = bearishOBV and bearishStochastic and bearishMACD | |
// Volume-Oscillator-weighted SuperTrend buy and sell signals | |
VOSTbuySignal = superTrend == 1 and superTrend[1] == -1 and bullishOscillators and (close[2] > shortSMA or smaWeightingToggle == true) | |
VOSTsellSignal = superTrend == -1 and superTrend[1] == 1 and bearishOscillators and (close[1] < shortSMA or smaWeightingToggle == true) | |
// Determine if currently in a "De-Risk Zone" | |
deRisk = (not VOSTsellSignal) and PL > 50 and (stochK < 55 or ((ta.crossunder(close[1], shortSMA) and close < shortSMA) and smaWeightingToggle == true)) | |
// | |
// End of: Logic gates for determining bullish or bearish sentiment | |
// * | |
// * | |
// Start of: Plot the Volume/Oscillator-weighted SuperTrend | |
// | |
plot(shortSMA, color = color.from_gradient((stochK + stochD) / 2, 0, 100, color.rgb(255, 0, 0), color.rgb(0, 200, 0))) | |
atrUpPlot = plot(superTrend == 1 ? atrUp : na, title="Up Trend", style=plot.style_linebr, linewidth=2, color=color.rgb(0, 255, 0, transp = 75)) | |
atrDownPlot = plot(superTrend == -1 ? atrDown : na, title="Down Trend", style=plot.style_linebr, linewidth=2, color=color.rgb(255, 0, 0, transp = 75)) | |
basePlot = plot(ohlc4, title="", style=plot.style_circles, linewidth=0) | |
plotshape(VOSTbuySignal ? atrUp : na, title="UpTrend Begins", location=location.absolute, style=shape.circle, size=size.tiny, color=color.rgb(0, 255, 0, transp = 75)) | |
plotshape(VOSTbuySignal ? atrUp : na, title="Buy", text="Buy", location=location.absolute, style=shape.labelup, size=size.tiny, color=color.rgb(0, 255, 0, transp = 75), textcolor=color.white) | |
plotshape(VOSTsellSignal ? atrDown : na, title="DownTrend Begins", location=location.absolute, style=shape.circle, size=size.tiny, color=color.rgb(255, 0, 0, transp = 75)) | |
plotshape(VOSTsellSignal ? atrDown : na, title="Sell", text="Sell", location=location.absolute, style=shape.labeldown, size=size.tiny, color=color.rgb(255, 0, 0, transp = 75), textcolor=color.white) | |
longFillColor = color.rgb(0, 255, 0, transp = 90) | |
shortFillColor = color.rgb(255, 0, 0, transp = 90) | |
fill(basePlot, atrUpPlot, title = "UpTrend Highligter", color = longFillColor) | |
fill(basePlot, atrDownPlot, title = "DownTrend Highligter", color = shortFillColor) | |
// Plot "De-Risk-Zones" | |
plotshape(deRisk ? atrDown : na, title="De-Risk Zone Notice", text="De-Risk Zone", location=location.absolute, style=shape.labeldown, size=size.tiny, color=color.rgb(255, 0, 0, transp = 75), textcolor=color.white) | |
// | |
// End of: Plot the Volume/Oscillator-weighted SuperTrend | |
// * | |
// Trading strategy logic gates for performance numbers in the Strategy Tester | |
if PL > 50 and stochK < 55 | |
strategy.close("Entry") | |
if VOSTbuySignal == true and time_cond | |
strategy.entry("Entry", strategy.long, 50000) | |
if VOSTsellSignal == true and time_cond | |
strategy.close("Entry") | |
strategy.exit("Exit", "Entry", profit = 10000000, loss = 75000) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment