Guest User

Community Buy/Sell Reddit SuperScript

a guest
Apr 26th, 2026
302
1
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 56.82 KB | Source Code | 1 0
  1. // Long Description:
  2. // Buy/Sell SuperScript [reddit] is a unified master indicator that allows traders to monitor
  3. // reversal exhaustion (tops/bottoms), high-frequency continuation entries, and overnight gap
  4. // probabilities simultaneously. Every module is highly customizable and routed through a globally
  5. // unified trend-filtering engine (VIDYA Trend Engine) that supports both trend-aligned and
  6. // counter-trend (contra) filtering using normalized momentum slope thresholds
  7. // (Flat, Weak, Moderate, Strong). Additionally, all signals can be gated by a multi-timeframe
  8. // consensus. The script includes UI tables for TimeFrame consensus and a real-time
  9. // SPY/ES/SPX price conversion.
  10. //
  11. // TLDR Description: Unified master script combining Top, Bottom, HF, and Gap signals.
  12. // - top_finder & bottom_finder: Exhaustion reversals (weak/moderate/strong/momentum)
  13. // - hf_signals: High-frequency buy/sell continuation patterns
  14. // - overnight_gap: Statistical gap up/down probability and consensus tracking
  15. // - Global VIDYA Engine: Advanced trend-aligned & contra-trend slope filtering (Z-score normalized)
  16. // - Multi-TF consensus filtering capabilities for all underlying strategies
  17. // - On-chart tables for SPY/ES/SPX correlation math and Timeframe statuses
  18. // ─────────────────────────────────────────────────────────────────────────────
  19.  
  20. //@version=6
  21. indicator("Buy/Sell SuperScript [reddit]", overlay=true, max_labels_count=500, max_lines_count=500, max_boxes_count=500)
  22.  
  23. // === Input groups ===
  24. grpModules = "Modules"
  25. grpDisplaySignal = "Signal Display Settings"
  26. grpTopSignal = "top_finder - Signal"
  27. grpTopRegime = "top_finder - Regime Filters"
  28. grpTopTrend = "top_finder - Trend Filters"
  29. grpBottomSignal = "bottom_finder - Signal"
  30. grpBottomConfirm = "bottom_finder - Confirmation"
  31. grpBottomMomentum = "bottom_finder - Momentum"
  32. grpBottomTrend = "bottom_finder - Trend Filters"
  33. grpHfSignalsSignal = "hf_signals - Signal"
  34. grpHfSignalsNormalize = "hf_signals - Normalization"
  35. grpHfSignalsRegime = "hf_signals - Regime Filters"
  36. grpHfSignalsVolumeSqz = "hf_signals - Volume & Squeeze"
  37. grpDeltaVolumeCandles = "Delta Volume Candles"
  38. grpHfSignalsTrend = "hf_signals - Trend Filters"
  39. grpGap = "overnight_gap - Signal"
  40. grpGapTrend = "overnight_gap - Trend Filters"
  41. grpAlerts = "Alerts"
  42. grpColors = "Colors"
  43. grpVIDYA = "VIDYA Trend Engine"
  44. grpVIDYAAligned = "VIDYA Trend-Aligned Filters"
  45. grpVIDYAContra = "VIDYA Counter-Trend (Contra) Filters"
  46. grpTimeframes = "Timeframes"
  47. grpConverter = "SPY/ES/SPX Converter"
  48.  
  49. // Webhook Configuration
  50. webhookKey = input.string("MY_SECRET_KEY", title="Secret Key", group=grpAlerts)
  51. alertExpiry = input.int(5, title="Alert Expiry (Minutes)", minval=1, group=grpAlerts)
  52.  
  53. // === Global toggles ===
  54. useTop = input.bool(true, title="Enable top_finder Signals", group=grpModules)
  55. useBot = input.bool(true, title="Enable bottom_finder Signals", group=grpModules)
  56. useHfSignals = input.bool(true, title="Enable hf_signals (High Frequency) Signals", group=grpModules)
  57. useOvernightGap = input.bool(true, title="Enable Overnight Gap signals", group=grpModules)
  58.  
  59. showConverter = input.bool(true, title="Show SPY / ES / SPX Converter Table", group=grpConverter)
  60. convPositionStr = input.string("Bottom Right", title="Table Position", options=["Top Right", "Bottom Right", "Bottom Left", "Top Left"], group=grpConverter)
  61.  
  62. // === Signal Display Settings ===
  63. showTopStrong = input.bool(true, title="Show Top strong sell labels", group=grpDisplaySignal)
  64. showTopModerate = input.bool(true, title="Show Top moderate sell labels", group=grpDisplaySignal)
  65. showBottomWeak = input.bool(true, title="Show Bottom weak buy labels", group=grpDisplaySignal)
  66. showBottomModerate = input.bool(true, title="Show Bottom moderate buy labels", group=grpDisplaySignal)
  67. showBottomStrong = input.bool(true, title="Show Bottom strong buy labels", group=grpDisplaySignal)
  68. showMomentumBuy = input.bool(true, title="Show Momentum buy labels", group=grpDisplaySignal)
  69. showHfBuy = input.bool(true, title="Show hf_signals buy labels", group=grpDisplaySignal)
  70. showHfSell = input.bool(true, title="Show hf_signals sell labels", group=grpDisplaySignal)
  71. showOvernightGapBuy = input.bool(true, title="Show Overnight Gap buy labels", group=grpDisplaySignal)
  72. showOvernightGapSell = input.bool(true, title="Show Overnight Gap sell labels", group=grpDisplaySignal)
  73.  
  74. // --------------------------------------------------
  75. // overnight_gap settings
  76. // --------------------------------------------------
  77. gapProbThreshold = input.int(75, title="High Prob Threshold (%)", minval=50, maxval=100, group=grpGap)
  78. gapConsensusReq = input.int(3, title="Required Momentum Consensus (1-4)", minval=1, maxval=4, group=grpGap)
  79. gapAnchorBars = input.int(3, title="Momentum Lookback Bars", minval=1, maxval=20, group=grpGap)
  80.  
  81. gapFilterByTF = input.bool(false, title="Filter by Selected Timeframes", group=grpGapTrend)
  82. gapFilterByVIDYA = input.bool(false, title="Filter by VIDYA trend", group=grpGapTrend)
  83. gapFilterLogic = input.string("Normal", title="Trend Filter Logic", options=["Normal", "Contrarian"], group=grpGapTrend, tooltip="Normal: Buy = Bullish Trend, Sell = Bearish Trend.\nContrarian: Buy = Bearish Trend, Sell = Bullish Trend.")
  84.  
  85. overnightGapAlertsEnabled = input.bool(true, title="Enable Overnight Gap alerts", group=grpAlerts)
  86.  
  87. // --------------------------------------------------
  88. // top_finder settings
  89. // --------------------------------------------------
  90. topLen = input.int(150, title="Top length", group=grpTopSignal)
  91. topStrongAlertsEnabled = input.bool(true, title="Enable top strong sell alerts", group=grpAlerts)
  92. topModerateAlertsEnabled = input.bool(true, title="Enable top moderate sell alerts", group=grpAlerts)
  93.  
  94. useTopCooldown = input.bool(true, title="Use cooldown", group=grpTopSignal)
  95. strongTopCooldownBars = input.int(5, title="Strong cooldown bars", minval=1, group=grpTopSignal)
  96. moderateTopCooldownBars = input.int(8, title="Moderate cooldown bars", minval=1, group=grpTopSignal)
  97.  
  98. // Top regime filters
  99. useTopADX = input.bool(false, title="Use ADX filter", group=grpTopRegime)
  100. adxTopLen = input.int(16, title="ADX DI length", minval=5, group=grpTopRegime)
  101. adxTopSmooth = input.int(30, title="ADX smoothing", minval=5, group=grpTopRegime)
  102. adxTopMin = input.float(18.0, title="ADX min", step=0.5, group=grpTopRegime)
  103.  
  104. useTopSlope = input.bool(false, title="Use slope filter", group=grpTopRegime)
  105. topSlopeLen = input.int(10, title="Slope lookback", minval=1, group=grpTopRegime)
  106. topMaLen = input.int(50, title="Slope MA length", minval=1, group=grpTopRegime)
  107. topAtrLen = input.int(14, title="ATR length", minval=1, group=grpTopRegime)
  108. slopeMinMultTop = input.float(0.20, title="Slope min multiplier", step=0.05, minval=0.0, group=grpTopRegime)
  109.  
  110. useTopRSI = input.bool(true, title="Use RSI filter", group=grpTopRegime)
  111. topRSILen = input.int(6, title="RSI length", minval=1, group=grpTopRegime)
  112. topRSIThresh = input.int(70, title="RSI threshold", minval=50, maxval=100, group=grpTopRegime)
  113.  
  114. topFilterByTF = input.bool(false, title="Filter sells by selected timeframes", group=grpTopTrend)
  115. topFilterByVIDYA = input.bool(false, title="Filter sells by VIDYA trend", group=grpTopTrend)
  116. topFilterLogic = input.string("Normal", title="Trend Filter Logic", options=["Normal", "Contrarian"], group=grpTopTrend, tooltip="Normal: Sells require Bearish trend.\nContrarian: Sells require Bullish trend.")
  117.  
  118. // --------------------------------------------------
  119. // bottom_finder settings
  120. // --------------------------------------------------
  121. wvfPD = input.int(22, title="WVF Percentile LCD (pd)", group=grpBottomSignal)
  122. wvfBBL = input.int(20, title="WVF Bollinger band length", group=grpBottomSignal)
  123. wvfMult = input.float(2.0, minval=1.0, maxval=5.0, title="WVF Bollinger multiplier", group=grpBottomSignal)
  124. wvfLB = input.int(50, title="WVF lookback percentiles", group=grpBottomSignal)
  125. ph = input.float(0.85, title="WVF highest percentile coefficient", group=grpBottomSignal)
  126. pl = input.float(1.01, title="WVF lowest percentile coefficient", group=grpBottomSignal)
  127.  
  128. weakThresh = input.float(0.98, title="WVF weak buy upper ratio threshold", minval=0, step=0.01, group=grpBottomSignal)
  129. moderateThresh = input.float(1.5, title="WVF moderate buy upper ratio threshold", minval=0, step=0.01, group=grpBottomSignal)
  130.  
  131. bottomFirstOnly = input.bool(true, title="Indicate only first confirmed bar", group=grpBottomConfirm)
  132.  
  133. botFilterByTF = input.bool(false, title="Filter buys by selected timeframes", group=grpBottomTrend)
  134. botFilterByVIDYA = input.bool(false, title="Filter buys by VIDYA trend", group=grpBottomTrend)
  135. botFilterLogic = input.string("Normal", title="Trend Filter Logic", options=["Normal", "Contrarian"], group=grpBottomTrend, tooltip="Normal: Buys require Bullish trend.\nContrarian: Buys require Bearish trend.")
  136.  
  137. // The hf_signals family had separate bar-level cooldown, but here we rely on this for bottom sequential confirmation
  138. bottomWeakBars = input.int(6, title="Weak consecutive for confirm", minval=1, maxval=20, group=grpBottomConfirm)
  139. bottomModerateBars = input.int(4, title="Moderate consecutive for confirm", minval=1, maxval=20, group=grpBottomConfirm)
  140. bottomStrongBars = input.int(2, title="Strong consecutive for confirm", minval=1, maxval=20, group=grpBottomConfirm)
  141. weakAlertsEnabled = input.bool(true, title="Enable bottom weak buy alerts", group=grpAlerts)
  142. moderateAlertsEnabled = input.bool(true, title="Enable bottom moderate buy alerts", group=grpAlerts)
  143. strongAlertsEnabled = input.bool(true, title="Enable bottom strong buy alerts", group=grpAlerts)
  144. momentumAlertsEnabled = input.bool(true, title="Enable bottom momentum buy alerts", group=grpAlerts)
  145.  
  146. // --------------------------------------------------
  147. // hf_signals settings
  148. // --------------------------------------------------
  149. hfSignalsSmaLen = input.int(9, title="SMA length", group=grpHfSignalsSignal)
  150. thresholdMode = input.string("Absolute", title="Threshold mode", options=["Absolute", "Percent", "ATR"], group=grpHfSignalsSignal)
  151. inchAbove = input.float(4.0, title="Threshold above SMA", group=grpHfSignalsSignal)
  152. inchBelow = input.float(4.0, title="Threshold below SMA", group=grpHfSignalsSignal)
  153. atrLen = input.int(4, title="ATR length", group=grpHfSignalsSignal)
  154.  
  155. useCooldown = input.bool(true, title="Enable cooldown filters", group=grpHfSignalsSignal)
  156. maxBars = input.int(2, title="Max bars for pullback & resume", minval=1, group=grpHfSignalsSignal)
  157. minBarsBetween = input.int(7, title="Min bars between signals", minval=0, group=grpHfSignalsSignal)
  158.  
  159. hfSignalsAutoNorm = input.bool(true, title="Universal auto-normalize", group=grpHfSignalsNormalize)
  160. normMode = input.string("ATR", title="Normalizer", options=["ATR", "Z-Score"], group=grpHfSignalsNormalize)
  161. normLookback = input.int(100, title="Z-score lookback", minval=20, group=grpHfSignalsNormalize)
  162. breakMult = input.float(0.60, title="Breakout multiple", minval=0.05, step=0.05, group=grpHfSignalsNormalize)
  163. bandMult = input.float(0.40, title="Pullback band multiple", minval=0.0, step=0.05, group=grpHfSignalsNormalize)
  164. roundToTick = input.bool(true, title="Round thresholds to mintick", group=grpHfSignalsNormalize)
  165. useNormFloor = input.bool(true, title="Apply minimum normalizer floor", group=grpHfSignalsNormalize)
  166. minNormTicks = input.int(20, title="Min normalizer (ticks)", minval=1, group=grpHfSignalsNormalize)
  167.  
  168. useReclaimExtreme = input.bool(false, title="Require reclaim of breakout extreme", group=grpHfSignalsRegime)
  169. useADXFilter = input.bool(true, title="Filter ADX must be trending", group=grpHfSignalsRegime)
  170.  
  171. diLen = input.int(16, title="DMI length", minval=5, group=grpHfSignalsRegime)
  172. adxSmoothing = input.int(30, title="ADX smoothing", minval=5, group=grpHfSignalsRegime)
  173. adxMin = input.float(15.0, title="ADX minimum", step=0.5, group=grpHfSignalsRegime)
  174. useHfSignalsSlopeFilter = input.bool(false, title="Slope filter", group=grpHfSignalsRegime)
  175. hfSignalsSlopeLen = input.int(10, title="Slope lookback", minval=1, group=grpHfSignalsRegime)
  176. hfSignalsSlopeMinMult = input.float(0.90, title="Min slope in norm units", step=0.05, minval=0.0, group=grpHfSignalsRegime)
  177. enforceAlternation = input.bool(true, title="Enforce alternating signals", group=grpHfSignalsRegime)
  178. hfBuyAlertsEnabled = input.bool(true, title="Enable HF buy alerts", group=grpAlerts)
  179. hfSellAlertsEnabled = input.bool(true, title="Enable HF sell alerts", group=grpAlerts)
  180.  
  181. // Volume/squeeze filters (hf_signals)
  182. useVolFilter = input.bool(false, title="Volume confirmation", group=grpHfSignalsVolumeSqz)
  183. volLen = input.int(15, title="Volume SMA lookback", group=grpHfSignalsVolumeSqz)
  184. volMult = input.float(0.8, title="Volume multiplier", step=0.1, group=grpHfSignalsVolumeSqz)
  185. useDeltaVolumeLowerTF = input.bool(true, title="Use lower timeframe delta volume", group=grpHfSignalsVolumeSqz)
  186. deltaVolumeTF = input.timeframe("1", title="Delta Volume Lower TF", group=grpHfSignalsVolumeSqz)
  187. showDeltaVolumeCandles = input.bool(true, title="Show Delta Volume Candles", group=grpDeltaVolumeCandles)
  188. deltaVolumeDisplayOption = input.string("full bar", title="Delta Candle Display", options=["half bar", "full bar"], group=grpDeltaVolumeCandles)
  189. deltaVolUpColor = input.color(#089981, title="Delta Up color", group=grpDeltaVolumeCandles)
  190. deltaVolUpNegColor = input.color(#f23645, title="Delta Up - color", group=grpDeltaVolumeCandles)
  191. deltaVolDownColor = input.color(#f23645, title="Delta Down color", group=grpDeltaVolumeCandles)
  192. deltaVolDownPosColor = input.color(#089981, title="Delta Down + color", group=grpDeltaVolumeCandles)
  193.  
  194. useSqzFilter = input.bool(true, title="Squeeze filter", group=grpHfSignalsVolumeSqz)
  195. sqzLen = input.int(100, title="Squeeze lookback", group=grpHfSignalsVolumeSqz)
  196.  
  197. hfFilterByTF = input.bool(false, title="Filter by selected timeframes", group=grpHfSignalsTrend)
  198. hfFilterByVIDYA = input.bool(true, title="Filter by VIDYA trend", group=grpHfSignalsTrend)
  199. hfFilterLogic = input.string("Normal", title="Trend Filter Logic", options=["Normal", "Contrarian"], group=grpHfSignalsTrend, tooltip="Normal: Buy = Bullish Trend, Sell = Bearish Trend.\nContrarian: Buy = Bearish Trend, Sell = Bullish Trend.")
  200.  
  201. // Colour options
  202. topStrongLabelColor = input.color(color.new(color.red, 0), title="Top strong label color", group=grpColors)
  203. topStrongTextColor = input.color(color.white, title="Top strong text color", group=grpColors)
  204. topModerateLabelColor = input.color(color.new(color.yellow, 0), title="Top moderate label color", group=grpColors)
  205. topModerateTextColor = input.color(color.black, title="Top moderate text color", group=grpColors)
  206. bottomWeakLabelColor = input.color(color.new(color.red, 0), title="Bottom weak label color", group=grpColors)
  207. bottomWeakTextColor = input.color(color.black, title="Bottom weak text color", group=grpColors)
  208. bottomModerateLabelColor = input.color(color.new(color.yellow, 0), title="Bottom moderate label color", group=grpColors)
  209. bottomModerateTextColor = input.color(color.black, title="Bottom moderate text color", group=grpColors)
  210. bottomStrongLabelColor = input.color(color.new(color.green, 0), title="Bottom strong label color", group=grpColors)
  211. bottomStrongTextColor = input.color(color.black, title="Bottom strong text color", group=grpColors)
  212. momentumLabelColor = input.color(color.new(color.purple, 0), title="Momentum buy label color", group=grpColors)
  213. momentumTextColor = input.color(color.white, title="Momentum buy text color", group=grpColors)
  214. hfSignalsBuyLabelColor = input.color(color.new(color.gray, 0), title="hf_signals buy color", group=grpColors)
  215. hfSignalsSellLabelColor = input.color(color.new(color.gray, 0), title="hf_signals sell color", group=grpColors)
  216. hfSignalsBuyTextColor = input.color(color.green, title="hf_signals buy text color", group=grpColors)
  217. hfSignalsSellTextColor = input.color(color.red, title="hf_signals sell text color", group=grpColors)
  218. hfSignalsBullBarColor = input.color(color.new(color.lime, 0), title="hf_signals bullish bar color", group=grpColors)
  219. hfSignalsBearBarColor = input.color(color.new(color.red, 0), title="hf_signals bearish bar color", group=grpColors)
  220.  
  221. // VIDYA trend settings
  222. sourceVIDYA = close
  223. vidya_length = input.int(10, title='VIDYA Length', minval=1, group=grpVIDYA)
  224. vidya_momentum = input.int(20, title='VIDYA Momentum', minval=1, group=grpVIDYA)
  225. band_distance = input.float(2, 'Distance factor for upper/lower bands', step=0.1, group=grpVIDYA)
  226. up_trend_color = input.color(#17dfad, '+', group=grpVIDYA, inline='c')
  227. down_trend_color = input.color(#dd326b, '-', group=grpVIDYA, inline='c')
  228. shadow = input.bool(true, 'Shadow', group=grpVIDYA, inline='c')
  229. showVIDYA = input.bool(true, 'Show VIDYA overlay', group=grpVIDYA)
  230. showVIDYA_SlopeHistogram = input.bool(false, 'Show VIDYA slope histogram (separate pane)', group=grpVIDYA)
  231.  
  232. vidya_flat_cutoff = input.float(0.3, title='VIDYA Flat/Weak cutoff', step=0.05, minval=0.0, group=grpVIDYA)
  233. vidya_weak_cutoff = input.float(1.0, title='VIDYA Weak/Moderate cutoff', step=0.05, minval=0.0, group=grpVIDYA)
  234. vidya_moderate_cutoff = input.float(1.5, title='VIDYA Moderate/Strong cutoff', step=0.05, minval=0.0, group=grpVIDYA)
  235.  
  236. allowAlignedFlat = input.bool(true, title="Allow Flat Slope", group=grpVIDYAAligned)
  237. allowAlignedWeak = input.bool(true, title="Allow Weak Slope", group=grpVIDYAAligned)
  238. allowAlignedModerate = input.bool(true, title="Allow Moderate Slope", group=grpVIDYAAligned)
  239. allowAlignedStrong = input.bool(false, title="Allow Strong Slope", group=grpVIDYAAligned)
  240.  
  241. allowContraFlat = input.bool(true, title="Allow Flat Slope", group=grpVIDYAContra)
  242. allowContraWeak = input.bool(false, title="Allow Weak Slope", group=grpVIDYAContra)
  243. allowContraModerate = input.bool(false, title="Allow Moderate Slope", group=grpVIDYAContra)
  244. allowContraStrong = input.bool(false, title="Allow Strong Slope", group=grpVIDYAContra)
  245.  
  246. var float vidya_up_trend_volume = 0.0
  247. var float vidya_down_trend_volume = 0.0
  248. var label vidya_delta_volume_label = na
  249. var label vidya_trend_star_label = na
  250.  
  251. t1 = input.timeframe('5', 'Time frame 1', group=grpTimeframes)
  252. active_t1 = input.bool(true, 'Monitor Time frame 1', group=grpTimeframes)
  253. t2 = input.timeframe('15', 'Time frame 2', group=grpTimeframes)
  254. active_t2 = input.bool(true, 'Monitor Time frame 2', group=grpTimeframes)
  255. t3 = input.timeframe('60', 'Time frame 3', group=grpTimeframes)
  256. active_t3 = input.bool(true, 'Monitor Time frame 3', group=grpTimeframes)
  257. t4 = input.timeframe('240', 'Time frame 4', group=grpTimeframes)
  258. active_t4 = input.bool(true, 'Monitor Time frame 4', group=grpTimeframes)
  259. t5 = input.timeframe('1D', 'Time frame 5', group=grpTimeframes)
  260. active_t5 = input.bool(true, 'Monitor Time frame 5', group=grpTimeframes)
  261. showTfTable = input.bool(true, title="Show TimeFrame Consensus Table", group=grpTimeframes)
  262. tfPositionStr = input.string("Top Right", title="Table Position", options=["Top Right", "Bottom Right", "Bottom Left", "Top Left"], group=grpTimeframes)
  263.  
  264. string tfTablePosStr = tfPositionStr == "Bottom Right" ? position.bottom_right : tfPositionStr == "Top Right" ? position.top_right : tfPositionStr == "Bottom Left" ? position.bottom_left : position.top_left
  265. var table statusTable = table.new(tfTablePosStr, 2, 6, border_width=1, frame_color=color.new(color.gray, 80), border_color=color.new(color.gray, 80), bgcolor=color.new(color.black, 90))
  266.  
  267. round_mintick(x) =>
  268. roundToTick and not na(x) ? math.round(x / syminfo.mintick) * syminfo.mintick : x
  269.  
  270. // === VIDYA helper functions ===
  271. vidya_calc(src, vidya_length, vidya_momentum) =>
  272. float momentum = ta.change(src)
  273. float sum_pos_momentum = math.sum(momentum >= 0 ? momentum : 0.0, vidya_momentum)
  274. float sum_neg_momentum = math.sum(momentum >= 0 ? 0.0 : -momentum, vidya_momentum)
  275. float abs_cmo = math.abs(100 * (sum_pos_momentum - sum_neg_momentum) / (sum_pos_momentum + sum_neg_momentum))
  276. float alpha = 2 / (vidya_length + 1)
  277. var float vidya_value = 0.0
  278. vidya_value := alpha * abs_cmo / 100 * src + (1 - alpha * abs_cmo / 100) * nz(vidya_value[1])
  279. ta.sma(vidya_value, 15)
  280.  
  281. f_vidya_trend(src) =>
  282. float vidya_value = vidya_calc(src, vidya_length, vidya_momentum)
  283. float vidya_atr = ta.atr(200)
  284. float upper_band = vidya_value + vidya_atr * band_distance
  285. float lower_band = vidya_value - vidya_atr * band_distance
  286. var int vidya_state = 0
  287. if ta.crossover(src, upper_band)
  288. vidya_state := 1
  289. if ta.crossunder(src, lower_band)
  290. vidya_state := -1
  291. vidya_state
  292.  
  293. // === top_finder logic ===
  294. top_lowest = ta.lowest(topLen)
  295. top_highest = ta.highest(topLen)
  296. rocTop = ta.roc(close, 8)
  297. rocTop := rocTop / ta.stdev(ta.roc(close, 8), 200)
  298.  
  299. top_strong = useTop and high < top_highest and high[1] == top_highest[1] and rocTop[2] > 2 and top_lowest == top_lowest[5] and barstate.isconfirmed
  300. top_moderate = useTop and high < top_highest and high[1] == top_highest[1] and not top_strong and barstate.isconfirmed
  301.  
  302. // Top regime filter computations
  303. [_, _, adxValTop] = ta.dmi(adxTopLen, adxTopSmooth)
  304.  
  305. maTop = ta.sma(close, topMaLen)
  306. atrTop = ta.atr(topAtrLen)
  307. slopeAbsTop = math.abs(maTop - maTop[topSlopeLen])
  308.  
  309. topTrendOK = not useTopADX or adxValTop >= adxTopMin
  310.  
  311. topSlopeOK = not useTopSlope or slopeAbsTop >= slopeMinMultTop * (atrTop)
  312.  
  313. topRSI = ta.rsi(close, topRSILen)
  314. topRSIOK = not useTopRSI or topRSI >= topRSIThresh
  315.  
  316. topRegimeOK = topTrendOK and topSlopeOK and topRSIOK
  317.  
  318. strongTopPrevBars = ta.barssince(top_strong[1])
  319. moderateTopPrevBars = ta.barssince(top_moderate[1])
  320. strongTopConfirmed = top_strong and topRegimeOK and (not useTopCooldown or na(strongTopPrevBars) or strongTopPrevBars >= strongTopCooldownBars)
  321. moderateTopConfirmed = top_moderate and topRegimeOK and (not useTopCooldown or na(moderateTopPrevBars) or moderateTopPrevBars >= moderateTopCooldownBars)
  322.  
  323. // === bottom_finder logic ===
  324. wvf = ((ta.highest(close, wvfPD)-low)/ta.highest(close, wvfPD))*100
  325. sDev = wvfMult * ta.stdev(wvf, wvfBBL)
  326. midLine = ta.sma(wvf, wvfBBL)
  327. upperBand = midLine + sDev
  328.  
  329. rangeHigh = ta.highest(wvf, wvfLB) * ph
  330.  
  331. signal = 0
  332. if wvf >= upperBand or wvf >= rangeHigh
  333. signal := wvf < weakThresh ? 1 : wvf < moderateThresh ? 2 : 3
  334.  
  335. var int weakConsec = 0
  336. var int moderateConsec = 0
  337. var int strongConsec = 0
  338.  
  339. if signal == 1
  340. weakConsec := nz(weakConsec[1],0)+1
  341. moderateConsec := 0
  342. strongConsec := 0
  343. else if signal == 2
  344. moderateConsec := nz(moderateConsec[1],0)+1
  345. weakConsec := 0
  346. strongConsec := 0
  347. else if signal == 3
  348. strongConsec := nz(strongConsec[1],0)+1
  349. weakConsec := 0
  350. moderateConsec := 0
  351. else
  352. weakConsec := 0
  353. moderateConsec := 0
  354. strongConsec := 0
  355.  
  356. weakConfirmed = weakConsec >= bottomWeakBars
  357. moderateConfirmed = moderateConsec >= bottomModerateBars
  358. strongConfirmed= strongConsec >= bottomStrongBars
  359.  
  360. weakFirst = weakConfirmed and weakConsec == bottomWeakBars
  361. moderateFirst = moderateConfirmed and moderateConsec == bottomModerateBars
  362. strongFirst = strongConfirmed and strongConsec == bottomStrongBars
  363.  
  364. bottomConfirmed = weakConfirmed or moderateConfirmed or strongConfirmed
  365. bottomWasConfirmed = barstate.isfirst ? false : bottomConfirmed[1]
  366. bottomSignal = bottomFirstOnly ? (bottomConfirmed and not bottomWasConfirmed) : bottomConfirmed
  367. bottomWeakSignal = bottomFirstOnly ? weakFirst : weakConfirmed
  368. bottomModerateSignal = bottomFirstOnly ? moderateFirst : moderateConfirmed
  369. bottomStrongSignal = bottomFirstOnly ? strongFirst : strongConfirmed
  370. bottomSignalVisible = (showBottomWeak and bottomWeakSignal) or (showBottomModerate and bottomModerateSignal) or (showBottomStrong and bottomStrongSignal)
  371.  
  372. momentumLowest = ta.lowest(150)
  373. momentumRoc = ta.roc(close, 8)
  374. momentumRoc := momentumRoc / ta.stdev(ta.roc(close, 8), 200)
  375. momentumBuyBase = low[1] == momentumLowest[1] and low > momentumLowest and low[2] == momentumLowest[2] and momentumRoc[2] < -2 and barstate.isconfirmed
  376. momentumBuySignal = showMomentumBuy and momentumBuyBase
  377.  
  378. bottomLongColor = bottomStrongLabelColor
  379. bottomTextColor = bottomStrongTextColor
  380. if bottomFirstOnly
  381. if weakFirst
  382. bottomLongColor := bottomWeakLabelColor
  383. bottomTextColor := bottomWeakTextColor
  384. else if moderateFirst
  385. bottomLongColor := bottomModerateLabelColor
  386. bottomTextColor := bottomModerateTextColor
  387. else if strongFirst
  388. bottomLongColor := bottomStrongLabelColor
  389. bottomTextColor := bottomStrongTextColor
  390. else
  391. if weakConfirmed
  392. bottomLongColor := bottomWeakLabelColor
  393. bottomTextColor := bottomWeakTextColor
  394. else if moderateConfirmed
  395. bottomLongColor := bottomModerateLabelColor
  396. bottomTextColor := bottomModerateTextColor
  397. else if strongConfirmed
  398. bottomLongColor := bottomStrongLabelColor
  399. bottomTextColor := bottomStrongTextColor
  400.  
  401. // === hf_signals logic ===
  402. smaHfSignals = ta.sma(close, hfSignalsSmaLen)
  403. atrHfSignals = ta.atr(atrLen)
  404.  
  405. normUnit0 = normMode == "ATR" ? atrHfSignals : math.max(ta.stdev(close - smaHfSignals, normLookback), syminfo.mintick*2)
  406. normUnit = useNormFloor ? math.max(normUnit0, minNormTicks*syminfo.mintick) : normUnit0
  407.  
  408. effThrAboveB = hfSignalsAutoNorm ? breakMult * normUnit : (thresholdMode=="Absolute"?inchAbove:(thresholdMode=="Percent"?smaHfSignals*inchAbove/100:atrHfSignals*inchAbove))
  409. effThrBelowB = hfSignalsAutoNorm ? breakMult * normUnit : (thresholdMode=="Absolute"?inchBelow:(thresholdMode=="Percent"?smaHfSignals*inchBelow/100:atrHfSignals*inchBelow))
  410. effPbBandB = hfSignalsAutoNorm ? bandMult * normUnit : 0.25
  411.  
  412. effThrAboveB := round_mintick(effThrAboveB)
  413. effThrBelowB := round_mintick(effThrBelowB)
  414. effPbBandB := round_mintick(effPbBandB)
  415.  
  416. // --- Dynamic Volume Logic for SPX because SPX has no volume---
  417. // Check if the current ticker is SPX (handles various exchange prefixes)
  418. isSPX = (syminfo.ticker == "SPX" or syminfo.root == "SPX")
  419.  
  420. // Fetch SPY volume as a proxy ONLY if we are on SPX
  421. spyVolProxy = request.security("AMEX:SPY", timeframe.period, volume, gaps=barmerge.gaps_off)
  422.  
  423. // Determine which volume to use: SPY volume for SPX charts, or native volume for everything else
  424. effectiveVol = isSPX ? spyVolProxy : volume
  425.  
  426. deltaVolumeTicker = isSPX ? "AMEX:SPY" : syminfo.tickerid
  427. deltaVolTFsec = timeframe.in_seconds(deltaVolumeTF)
  428. chartTFsec = timeframe.in_seconds(timeframe.period)
  429. lowerTFAllowed = useDeltaVolumeLowerTF and deltaVolTFsec > 0 and deltaVolTFsec < chartTFsec
  430.  
  431. float bullVol = na
  432. float bearVol = na
  433. if lowerTFAllowed
  434. [bV, sV, nV, tV, aCl] = request.security_lower_tf(deltaVolumeTicker, deltaVolumeTF, [close > open ? volume : 0, close < open ? volume : 0, close == open ? volume : 0, volume, close])
  435. bullVol := nz(bV.sum(), 0)
  436. bearVol := nz(sV.sum(), 0)
  437. else
  438. bullVol := close > open ? effectiveVol : 0
  439. bearVol := close < open ? effectiveVol : 0
  440.  
  441. // --- HF Signals Volume Filter ---
  442. [_, _, adxValue] = ta.dmi(diLen, adxSmoothing)
  443. avgVolB = ta.sma(effectiveVol, volLen)
  444.  
  445. // The filter now uses 'effectiveVol' (SPY for SPX, Native for others)
  446. volOK = not useVolFilter or effectiveVol > (avgVolB * volMult)
  447.  
  448. basisB = ta.sma(close, sqzLen)
  449. devB = 2*ta.stdev(close, sqzLen)
  450. upperBB = basisB + devB
  451. lowerBB = basisB - devB
  452. atrSqz = ta.atr(sqzLen)
  453. upperKC = basisB + 1.5*atrSqz
  454. lowerKC = basisB - 1.5*atrSqz
  455. isSqueezed = lowerBB > lowerKC and upperBB < upperKC
  456. squeezeOK = not useSqzFilter or not isSqueezed
  457.  
  458. hfSignalsSlopeMA = ta.sma(close, hfSignalsSlopeLen)
  459. hfSignalsSlopeAbs = math.abs(hfSignalsSlopeMA - hfSignalsSlopeMA[hfSignalsSlopeLen])
  460. hfSignalsSlopeOK = not useHfSignalsSlopeFilter or hfSignalsSlopeAbs >= hfSignalsSlopeMinMult * normUnit
  461.  
  462. var int lastSignal = 0
  463. var int hfSignalsBarTrendState = 0
  464. var bool inBuy=false, pulledBuy=false, firedB=false
  465. var int startB = na
  466. var int lastBuyBar = na
  467. var float hiB=na
  468. var bool inSell=false, pulledSell=false, firedS=false
  469. var int startS = na
  470. var int lastSellBar = na
  471. var float loS=na
  472.  
  473. if close < smaHfSignals
  474. inBuy := false
  475. pulledBuy := false
  476. firedB := false
  477.  
  478. if not inBuy and (not useADXFilter or adxValue >= adxMin) and close > smaHfSignals + effThrAboveB
  479. inBuy := true
  480. pulledBuy := false
  481. firedB := false
  482. startB := bar_index
  483. hiB := high
  484.  
  485. if inBuy
  486. hiB := math.max(hiB, high)
  487. if useCooldown and bar_index - startB > maxBars
  488. inBuy := false
  489.  
  490. buyPulled = inBuy and not pulledBuy and low <= smaHfSignals + effPbBandB and close > smaHfSignals
  491. if buyPulled
  492. pulledBuy := true
  493.  
  494. buySignalRawB = inBuy and pulledBuy and not firedB and close > smaHfSignals and close > open and (not useReclaimExtreme or close > hiB[1]) and (not useCooldown or bar_index - startB <= maxBars) and (na(lastBuyBar) or not useCooldown or bar_index - lastBuyBar >= minBarsBetween)
  495.  
  496. buySignalB = buySignalRawB and (not enforceAlternation or lastSignal <= 0) and barstate.isconfirmed and volOK and squeezeOK and hfSignalsSlopeOK
  497. if buySignalB
  498. firedB := true
  499. lastBuyBar := bar_index
  500. lastSignal := 1
  501. hfSignalsBarTrendState := 1
  502.  
  503. if close > smaHfSignals
  504. inSell := false
  505. pulledSell := false
  506. firedS := false
  507.  
  508. if not inSell and (not useADXFilter or adxValue >= adxMin) and close < smaHfSignals - effThrBelowB
  509. inSell := true
  510. pulledSell := false
  511. firedS := false
  512. startS := bar_index
  513. loS := low
  514.  
  515. if inSell
  516. loS := math.min(loS, low)
  517. if useCooldown and bar_index - startS > maxBars
  518. inSell := false
  519.  
  520. sellPulled = inSell and not pulledSell and high >= smaHfSignals - effPbBandB and close < smaHfSignals
  521. if sellPulled
  522. pulledSell := true
  523.  
  524. sellSignalRawB = inSell and pulledSell and not firedS and close < smaHfSignals and close < open and (not useReclaimExtreme or close < loS[1]) and (not useCooldown or bar_index - startS <= maxBars) and (na(lastSellBar) or not useCooldown or bar_index - lastSellBar >= minBarsBetween)
  525.  
  526. sellSignalB = sellSignalRawB and (not enforceAlternation or lastSignal >= 0) and barstate.isconfirmed and volOK and squeezeOK and hfSignalsSlopeOK
  527. if sellSignalB
  528. firedS := true
  529. lastSellBar := bar_index
  530. lastSignal := -1
  531. hfSignalsBarTrendState := -1
  532.  
  533. // === Plotting ===
  534.  
  535. // VIDYA overlay styling replacing chart bar styling
  536. float vidya_value = vidya_calc(sourceVIDYA, vidya_length, vidya_momentum)
  537. float vidya_atr = ta.atr(200)
  538. float upper_band = vidya_value + vidya_atr * band_distance
  539. float lower_band = vidya_value - vidya_atr * band_distance
  540. var bool is_vidya_up = false
  541. if ta.crossover(sourceVIDYA, upper_band)
  542. is_vidya_up := true
  543. if ta.crossunder(sourceVIDYA, lower_band)
  544. is_vidya_up := false
  545.  
  546. float smoothed_value = na
  547. if is_vidya_up
  548. smoothed_value := lower_band
  549. else
  550. smoothed_value := upper_band
  551. if ta.change(is_vidya_up)
  552. smoothed_value := na
  553. vidya_up_trend_volume := 0.0
  554. vidya_down_trend_volume := 0.0
  555.  
  556. float delta_vol = bullVol - bearVol
  557. float delta_val = (bullVol + bearVol) != 0 ? delta_vol / (bullVol + bearVol) * 100 : 0
  558. string delta_volume = str.tostring(delta_val, format.percent)
  559. string delta_volume_abs = str.tostring(delta_vol, format.volume)
  560.  
  561. float delta_vol_sum = bullVol + bearVol
  562. float delta_norm = effectiveVol != 0 ? delta_vol / effectiveVol : 0
  563. float delta_aNorm = math.abs(delta_norm)
  564. bool delta_pos = delta_norm >= 0
  565.  
  566. float delta_abs_price = math.abs(open - close)
  567. float delta_price_min = math.min(open, close)
  568. float delta_price_max = math.max(open, close)
  569. float delta_price_avg = (open + close) / 2
  570.  
  571. float delta_base = deltaVolumeDisplayOption == "half bar" ? delta_price_avg : delta_pos ? delta_price_min : delta_price_max
  572. float delta_value = deltaVolumeDisplayOption == "half bar" ? delta_price_avg + delta_norm * delta_abs_price / 2 : delta_pos ? delta_price_min + delta_aNorm * delta_abs_price : delta_price_max - delta_aNorm * delta_abs_price
  573.  
  574. color delta_css = close > open ? deltaVolUpColor : close < open ? deltaVolDownColor : chart.fg_color
  575. color delta_cssD = color.new(delta_norm > 0 ? close > open ? deltaVolUpColor : deltaVolDownPosColor : close < open ? deltaVolDownColor : deltaVolUpNegColor, 50)
  576.  
  577. barcolor(showDeltaVolumeCandles ? color.new(color.white, 100) : na, title="Hide Native Candles")
  578.  
  579. plotcandle(delta_base, delta_base, delta_value, delta_value, title="Delta Volume Body", color=delta_cssD, wickcolor=na, bordercolor=na, display= showDeltaVolumeCandles ? display.all - display.status_line : display.none)
  580. plotcandle(open, high, low, close, title="Delta Volume Candle", color=na, wickcolor=delta_css, bordercolor=delta_css, display= showDeltaVolumeCandles ? display.all - display.status_line : display.none)
  581. plot(bullVol, title="Delta Bull Vol", display= showDeltaVolumeCandles ? display.data_window : display.none)
  582. plot(bearVol, title="Delta Bear Vol", display= showDeltaVolumeCandles ? display.data_window : display.none)
  583. plot(delta_vol, title="Delta Volume", display= showDeltaVolumeCandles ? display.data_window : display.none)
  584.  
  585. bool trend_cross_up = not is_vidya_up[1] and is_vidya_up
  586. bool trend_cross_down = not is_vidya_up and is_vidya_up[1]
  587.  
  588. color vidya_trend_color = is_vidya_up ? up_trend_color : down_trend_color
  589. p1 = plot(showVIDYA ? smoothed_value : na, title="VIDYA Trend", color=vidya_trend_color, linewidth=2, style=plot.style_linebr)
  590. p2 = plot(showVIDYA ? hl2 : na, title="VIDYA Reference", display=display.none)
  591. fill(p1, p2, smoothed_value, hl2, color.new(vidya_trend_color, shadow ? 80 : 100), color.new(vidya_trend_color, 100))
  592.  
  593. plotshape(trend_cross_up[1] ? smoothed_value[0] : na, title="Trend Up", style=shape.labelup, location=location.absolute, color=color.new(up_trend_color, 50), text="▲", textcolor=chart.fg_color)
  594. plotshape(trend_cross_down[1] ? smoothed_value[0] : na, title="Trend Down", style=shape.labeldown, location=location.absolute, color=color.new(down_trend_color, 50), text="▼", textcolor=chart.fg_color)
  595.  
  596. if barstate.islast and not na(smoothed_value)
  597. if showDeltaVolumeCandles
  598. if not na(vidya_delta_volume_label)
  599. label.delete(vidya_delta_volume_label)
  600. vidya_delta_volume_label := label.new(bar_index, smoothed_value, 'Buy: ' + str.tostring(bullVol, format.volume) + '\nSell: ' + str.tostring(bearVol, format.volume) + '\nDelta Vol: ' + delta_volume_abs + '\nDelta %: ' + delta_volume, color=color.new(vidya_trend_color, 90), style=is_vidya_up ? label.style_label_upper_left : label.style_label_lower_left, textcolor=chart.fg_color, size=size.small)
  601. if not na(vidya_trend_star_label)
  602. label.delete(vidya_trend_star_label)
  603. vidya_trend_star_label := label.new(bar_index, smoothed_value, text='✪', color=#00000003, textcolor=vidya_trend_color, style=label.style_label_center, size=size.large)
  604. else
  605. if not na(vidya_delta_volume_label)
  606. label.delete(vidya_delta_volume_label)
  607. vidya_delta_volume_label := na
  608. if not na(vidya_trend_star_label)
  609. label.delete(vidya_trend_star_label)
  610. vidya_trend_star_label := na
  611.  
  612. s1 = request.security(syminfo.tickerid, t1, f_vidya_trend(sourceVIDYA)[1], lookahead=barmerge.lookahead_on)
  613. s2 = request.security(syminfo.tickerid, t2, f_vidya_trend(sourceVIDYA)[1], lookahead=barmerge.lookahead_on)
  614. s3 = request.security(syminfo.tickerid, t3, f_vidya_trend(sourceVIDYA)[1], lookahead=barmerge.lookahead_on)
  615. s4 = request.security(syminfo.tickerid, t4, f_vidya_trend(sourceVIDYA)[1], lookahead=barmerge.lookahead_on)
  616. s5 = request.security(syminfo.tickerid, t5, f_vidya_trend(sourceVIDYA)[1], lookahead=barmerge.lookahead_on)
  617.  
  618. bool tf_buy_ok = (not active_t1 or s1 == 1) and (not active_t2 or s2 == 1) and (not active_t3 or s3 == 1) and (not active_t4 or s4 == 1) and (not active_t5 or s5 == 1)
  619. bool tf_sell_ok = (not active_t1 or s1 == -1) and (not active_t2 or s2 == -1) and (not active_t3 or s3 == -1) and (not active_t4 or s4 == -1) and (not active_t5 or s5 == -1)
  620.  
  621. int activeTFCount = (active_t1 ? 1 : 0) + (active_t2 ? 1 : 0) + (active_t3 ? 1 : 0) + (active_t4 ? 1 : 0) + (active_t5 ? 1 : 0)
  622. bool allActiveBullish = activeTFCount > 0 and (not active_t1 or s1 == 1) and (not active_t2 or s2 == 1) and (not active_t3 or s3 == 1) and (not active_t4 or s4 == 1) and (not active_t5 or s5 == 1)
  623. bool allActiveBearish = activeTFCount > 0 and (not active_t1 or s1 == -1) and (not active_t2 or s2 == -1) and (not active_t3 or s3 == -1) and (not active_t4 or s4 == -1) and (not active_t5 or s5 == -1)
  624. string tfConsensus = activeTFCount == 0 ? "Disabled" : allActiveBullish ? "Bullish" : allActiveBearish ? "Bearish" : "Mixed"
  625. color tfConsensusColor = activeTFCount == 0 ? color.gray : allActiveBullish ? color.lime : allActiveBearish ? color.red : color.yellow
  626.  
  627. tfStatus(bool active, int sign) =>
  628. active ? (sign == 1 ? "Bullish" : sign == -1 ? "Bearish" : "Neutral") : "Disabled"
  629.  
  630. string tf1Status = tfStatus(active_t1, s1)
  631. string tf2Status = tfStatus(active_t2, s2)
  632. string tf3Status = tfStatus(active_t3, s3)
  633. string tf4Status = tfStatus(active_t4, s4)
  634. string tf5Status = tfStatus(active_t5, s5)
  635.  
  636. tfStatusColor(bool active, int sign) =>
  637. active ? (sign == 1 ? color.lime : sign == -1 ? color.red : color.gray) : color.gray
  638.  
  639. color tf1Color = tfStatusColor(active_t1, s1)
  640. color tf2Color = tfStatusColor(active_t2, s2)
  641. color tf3Color = tfStatusColor(active_t3, s3)
  642. color tf4Color = tfStatusColor(active_t4, s4)
  643. color tf5Color = tfStatusColor(active_t5, s5)
  644.  
  645. // --- Persistent Variables ---
  646. var float up_prob = 0.0
  647. var float dn_prob = 0.0
  648. var int up_cons = 0
  649. var int dn_cons = 0
  650. var bool gapTriggeredToday = false
  651.  
  652. // --- Time & Session Logic ---
  653. // Detect the final bars of the normal trading session
  654. int nyHour = hour(time, "America/New_York")
  655. int nyMin = minute(time, "America/New_York")
  656.  
  657. // Identify the execution window (target the 15:55 bar to lock in structure strictly near market close)
  658. bool isEndOfDayWindow = (nyHour == 15 and nyMin >= 55)
  659. bool newDay = ta.change(time("D", "America/New_York")) != 0
  660.  
  661. if newDay
  662. up_prob := 0.0
  663. dn_prob := 0.0
  664. up_cons := 0
  665. dn_cons := 0
  666. gapTriggeredToday := false
  667.  
  668. // --- Price & Structural Data ---
  669. var float dHigh = high
  670. var float dLow = low
  671.  
  672. if newDay
  673. dHigh := high
  674. dLow := low
  675. else
  676. dHigh := math.max(dHigh, high)
  677. dLow := math.min(dLow, low)
  678.  
  679. float day_range = dHigh - dLow
  680. float pos_score = day_range != 0 ? (close - dLow) / day_range : 0.0
  681.  
  682. // Safely pull session VWAP, fallback to EMA for volumeless instruments (SPX)
  683. float v_wap = ta.vwap
  684. if na(v_wap)
  685. v_wap := ta.ema(close, 30)
  686.  
  687. // --- Contextual Proxies (Non-Repainting) ---
  688. // Using closed bars [1] for security to avoid repainting intraday on historical data
  689. float es_close = nz(request.security("CME_MINI:ES1!", timeframe.period, close[1], lookahead=barmerge.lookahead_on))
  690. float es_ema = nz(request.security("CME_MINI:ES1!", timeframe.period, ta.ema(close, 10)[1], lookahead=barmerge.lookahead_on))
  691. float vix_close = nz(request.security("CBOE:VIX", timeframe.period, close[1], lookahead=barmerge.lookahead_on))
  692. float vix_sma = nz(request.security("CBOE:VIX", timeframe.period, ta.sma(close, 10)[1], lookahead=barmerge.lookahead_on))
  693.  
  694. // --- Continuous Probability Engine ---
  695. float final_up_prob = 0.0
  696. float final_dn_prob = 0.0
  697.  
  698. // 1. Structural Conditions (Loosened slightly to account for high-range chop, exported to data window)
  699. bool bull_structure = close > v_wap and pos_score >= 0.65
  700. bool bear_structure = close < v_wap and pos_score <= 0.35
  701.  
  702. // --- Momentum Evaluators ---
  703. // Method 1: 1-Bar Quick
  704. bool vix_up_1 = vix_close < nz(vix_close[1])
  705. bool vix_dn_1 = vix_close > nz(vix_close[1])
  706. bool es_up_1 = es_close > nz(es_close[1])
  707. bool es_dn_1 = es_close < nz(es_close[1])
  708.  
  709. // Method 2: 3-Bar SMA
  710. bool vix_up_2 = ta.sma(vix_close, gapAnchorBars) < nz(ta.sma(vix_close, gapAnchorBars)[1])
  711. bool vix_dn_2 = ta.sma(vix_close, gapAnchorBars) > nz(ta.sma(vix_close, gapAnchorBars)[1])
  712. bool es_up_2 = ta.sma(es_close, gapAnchorBars) > nz(ta.sma(es_close, gapAnchorBars)[1])
  713. bool es_dn_2 = ta.sma(es_close, gapAnchorBars) < nz(ta.sma(es_close, gapAnchorBars)[1])
  714.  
  715. // Method 3: Avg Momentum
  716. bool vix_up_3 = ta.sma(ta.change(vix_close), gapAnchorBars) < 0
  717. bool vix_dn_3 = ta.sma(ta.change(vix_close), gapAnchorBars) > 0
  718. bool es_up_3 = ta.sma(ta.change(es_close), gapAnchorBars) > 0
  719. bool es_dn_3 = ta.sma(ta.change(es_close), gapAnchorBars) < 0
  720.  
  721. // Method 4: Anchored Delta
  722. bool vix_up_4 = vix_close < nz(vix_close[gapAnchorBars])
  723. bool vix_dn_4 = vix_close > nz(vix_close[gapAnchorBars])
  724. bool es_up_4 = es_close > nz(es_close[gapAnchorBars])
  725. bool es_dn_4 = es_close < nz(es_close[gapAnchorBars])
  726.  
  727. // Momentum Consensus Score
  728. int vix_up_score = (vix_up_1 ? 1 : 0) + (vix_up_2 ? 1 : 0) + (vix_up_3 ? 1 : 0) + (vix_up_4 ? 1 : 0)
  729. int vix_dn_score = (vix_dn_1 ? 1 : 0) + (vix_dn_2 ? 1 : 0) + (vix_dn_3 ? 1 : 0) + (vix_dn_4 ? 1 : 0)
  730. int es_up_score = (es_up_1 ? 1 : 0) + (es_up_2 ? 1 : 0) + (es_up_3 ? 1 : 0) + (es_up_4 ? 1 : 0)
  731. int es_dn_score = (es_dn_1 ? 1 : 0) + (es_dn_2 ? 1 : 0) + (es_dn_3 ? 1 : 0) + (es_dn_4 ? 1 : 0)
  732.  
  733. bool vix_mom_up = vix_up_score >= gapConsensusReq
  734. bool vix_mom_dn = vix_dn_score >= gapConsensusReq
  735. bool es_mom_up = es_up_score >= gapConsensusReq
  736. bool es_mom_dn = es_dn_score >= gapConsensusReq
  737.  
  738. // 2. VIX Momentum
  739. bool vix_confirms_up = vix_close < vix_sma and vix_mom_up
  740. bool vix_confirms_dn = vix_close > vix_sma and vix_mom_dn
  741.  
  742. // 3. Futures Pressure
  743. bool es_bullish_trend = es_close > es_ema and es_mom_up
  744. bool es_bearish_trend = es_close < es_ema and es_mom_dn
  745.  
  746. // --- GAP UP LOGIC ---
  747. if bull_structure and vix_confirms_up and es_bullish_trend
  748. final_up_prob := 95.0
  749. else if bull_structure and (vix_confirms_up or es_bullish_trend)
  750. final_up_prob := 80.0
  751. else if bull_structure
  752. final_up_prob := 60.0
  753.  
  754. // --- GAP DOWN LOGIC (Stricter Requirements) ---
  755. if bear_structure and vix_confirms_dn and es_bearish_trend
  756. final_dn_prob := 95.0
  757. else if bear_structure and (vix_confirms_dn or es_bearish_trend)
  758. final_dn_prob := 80.0
  759. else if bear_structure
  760. final_dn_prob := 60.0
  761.  
  762. // Invalidate Gap Down if VIX is dropping (Institutional Buying)
  763. if vix_mom_up
  764. final_dn_prob := 0.0
  765.  
  766. if not gapTriggeredToday
  767. up_prob := final_up_prob
  768. dn_prob := final_dn_prob
  769. // Display the highest driving consensus for active structures, or 0 if probability is blocked
  770. up_cons := final_up_prob > 0 ? math.max(vix_up_score, es_up_score) : 0
  771. dn_cons := final_dn_prob > 0 ? math.max(vix_dn_score, es_dn_score) : 0
  772.  
  773. // --- Execution Logic ---
  774. // We target the first bar in the end of day window.
  775. bool gapBuyCandidate = useOvernightGap and isEndOfDayWindow and not gapTriggeredToday and up_prob >= gapProbThreshold
  776. bool gapSellCandidate = useOvernightGap and isEndOfDayWindow and not gapTriggeredToday and dn_prob >= gapProbThreshold
  777.  
  778. bool overnightGapBuy = gapBuyCandidate
  779. bool overnightGapSell = gapSellCandidate
  780.  
  781. // Only lock out subsequent candles after a signal fully closes, preventing multiple triggers in the window
  782. if (gapBuyCandidate or gapSellCandidate)
  783. if barstate.isconfirmed
  784. gapTriggeredToday := true
  785.  
  786. // --- Plotting ---
  787. // Plotting as columns for the final minute of the day
  788. plot(up_prob, "Gap Up Prob", color=color.new(color.blue, 0), style=plot.style_line, linewidth=4, display=display.data_window)
  789. plot(dn_prob * -1, "Gap Down Prob", color=color.new(color.orange, 0), style=plot.style_line, linewidth=4, display=display.data_window)
  790. plot(pos_score * 100, "Position Score %", color=color.new(color.white, 80), display=display.data_window)
  791. plot(v_wap, "Gap VWAP", color=color.new(color.fuchsia, 50), display=display.data_window)
  792.  
  793. float v_roc = ta.change(vidya_value)
  794. float abs_v_roc_z = math.abs(v_roc / ta.stdev(v_roc, 200))
  795. bool isFlat = nz(abs_v_roc_z) < vidya_flat_cutoff
  796. bool isWeak = nz(abs_v_roc_z) >= vidya_flat_cutoff and nz(abs_v_roc_z) < vidya_weak_cutoff
  797. bool isModerate = nz(abs_v_roc_z) >= vidya_weak_cutoff and nz(abs_v_roc_z) < vidya_moderate_cutoff
  798. bool isStrong = nz(abs_v_roc_z) >= vidya_moderate_cutoff
  799. color vidyaSlopeColor = isStrong ? color.green : isModerate ? color.yellow : isWeak ? color.red : color.gray
  800. plot(showVIDYA_SlopeHistogram ? abs_v_roc_z : na, title="VIDYA Slope Z-Score", color=vidyaSlopeColor, style=plot.style_columns, linewidth=3, display=showVIDYA_SlopeHistogram ? display.pane : display.none)
  801. hline(vidya_flat_cutoff, title="Flat/Weak Threshold", color=color.new(color.gray, 50), linestyle=hline.style_dotted)
  802. hline(vidya_weak_cutoff, title="Weak/Moderate Threshold", color=color.new(color.gray, 50), linestyle=hline.style_dotted)
  803. hline(vidya_moderate_cutoff, title="Moderate/Strong Threshold", color=color.new(color.gray, 50), linestyle=hline.style_dotted)
  804.  
  805. bool slope_aligned_ok = (allowAlignedFlat and isFlat) or (allowAlignedWeak and isWeak) or (allowAlignedModerate and isModerate) or (allowAlignedStrong and isStrong)
  806. bool slope_contra_ok = (allowContraFlat and isFlat) or (allowContraWeak and isWeak) or (allowContraModerate and isModerate) or (allowContraStrong and isStrong)
  807.  
  808. bool vidya_buy_ok = (is_vidya_up and slope_aligned_ok) or (not is_vidya_up and slope_contra_ok)
  809. bool vidya_sell_ok = (not is_vidya_up and slope_aligned_ok) or (is_vidya_up and slope_contra_ok)
  810.  
  811. if showTfTable and barstate.islast
  812. table.cell(statusTable, 0, 0, "TimeFrame Consensus", text_color=color.white, bgcolor=color.new(color.gray, 80))
  813. table.cell(statusTable, 1, 0, tfConsensus, text_color=tfConsensusColor, bgcolor=color.new(color.gray, 80))
  814. table.cell(statusTable, 0, 1, t1, text_color=color.white)
  815. table.cell(statusTable, 1, 1, tf1Status, text_color=tf1Color)
  816. table.cell(statusTable, 0, 2, t2, text_color=color.white)
  817. table.cell(statusTable, 1, 2, tf2Status, text_color=tf2Color)
  818. table.cell(statusTable, 0, 3, t3, text_color=color.white)
  819. table.cell(statusTable, 1, 3, tf3Status, text_color=tf3Color)
  820. table.cell(statusTable, 0, 4, t4, text_color=color.white)
  821. table.cell(statusTable, 1, 4, tf4Status, text_color=tf4Color)
  822. table.cell(statusTable, 0, 5, t5, text_color=color.white)
  823. table.cell(statusTable, 1, 5, tf5Status, text_color=tf5Color)
  824. else if not showTfTable
  825. table.clear(statusTable, 0, 0, 1, 5)
  826.  
  827. // --- Trend Conditioning Logic ---
  828. // Top Finder (Sells only)
  829. bool top_tf_ok = topFilterLogic == "Contrarian" ? tf_buy_ok : tf_sell_ok
  830. bool top_vidya_ok = topFilterLogic == "Contrarian" ? vidya_buy_ok : vidya_sell_ok
  831.  
  832. bool topStrongFiltered = useTop and strongTopConfirmed and (not topFilterByTF or top_tf_ok) and (not topFilterByVIDYA or top_vidya_ok)
  833. bool topModerateFiltered = useTop and moderateTopConfirmed and (not topFilterByTF or top_tf_ok) and (not topFilterByVIDYA or top_vidya_ok)
  834.  
  835. // Bottom Finder (Buys only)
  836. bool bot_tf_ok = botFilterLogic == "Contrarian" ? tf_sell_ok : tf_buy_ok
  837. bool bot_vidya_ok = botFilterLogic == "Contrarian" ? vidya_sell_ok : vidya_buy_ok
  838.  
  839. bool bottomWeakFiltered = useBot and bottomWeakSignal and (not botFilterByTF or bot_tf_ok) and (not botFilterByVIDYA or bot_vidya_ok)
  840. bool bottomModerateFiltered = useBot and bottomModerateSignal and (not botFilterByTF or bot_tf_ok) and (not botFilterByVIDYA or bot_vidya_ok)
  841. bool bottomStrongFiltered = useBot and bottomStrongSignal and (not botFilterByTF or bot_tf_ok) and (not botFilterByVIDYA or bot_vidya_ok)
  842. bool momentumBuyFiltered = useBot and momentumBuySignal and (not botFilterByTF or bot_tf_ok) and (not botFilterByVIDYA or bot_vidya_ok)
  843.  
  844. // HF Signals (Buys and Sells)
  845. bool hf_buy_tf_ok = hfFilterLogic == "Contrarian" ? tf_sell_ok : tf_buy_ok
  846. bool hf_buy_vidya_ok = hfFilterLogic == "Contrarian" ? vidya_sell_ok : vidya_buy_ok
  847. bool hf_sell_tf_ok = hfFilterLogic == "Contrarian" ? tf_buy_ok : tf_sell_ok
  848. bool hf_sell_vidya_ok = hfFilterLogic == "Contrarian" ? vidya_buy_ok : vidya_sell_ok
  849.  
  850. bool hfBuyFiltered = useHfSignals and buySignalB and (not hfFilterByTF or hf_buy_tf_ok) and (not hfFilterByVIDYA or hf_buy_vidya_ok)
  851. bool hfSellFiltered = useHfSignals and sellSignalB and (not hfFilterByTF or hf_sell_tf_ok) and (not hfFilterByVIDYA or hf_sell_vidya_ok)
  852.  
  853. // Overnight Gap (Buys and Sells)
  854. bool gap_buy_tf_ok = gapFilterLogic == "Contrarian" ? tf_sell_ok : tf_buy_ok
  855. bool gap_buy_vidya_ok = gapFilterLogic == "Contrarian" ? vidya_sell_ok : vidya_buy_ok
  856. bool gap_sell_tf_ok = gapFilterLogic == "Contrarian" ? tf_buy_ok : tf_sell_ok
  857. bool gap_sell_vidya_ok = gapFilterLogic == "Contrarian" ? vidya_buy_ok : vidya_sell_ok
  858.  
  859. bool overnightGapBuyFiltered = overnightGapBuy and (not gapFilterByTF or gap_buy_tf_ok) and (not gapFilterByVIDYA or gap_buy_vidya_ok)
  860. bool overnightGapSellFiltered = overnightGapSell and (not gapFilterByTF or gap_sell_tf_ok) and (not gapFilterByVIDYA or gap_sell_vidya_ok)
  861.  
  862. // --- Plotting ---
  863. plotshape(useTop and showTopStrong and topStrongFiltered, title="Top Strong Sell", style=shape.labeldown, location=location.abovebar, color=topStrongLabelColor, text="Sell", textcolor=topStrongTextColor, size=size.tiny)
  864. plotshape(useTop and showTopModerate and topModerateFiltered, title="Top Moderate Sell", style=shape.labeldown, location=location.abovebar, color=topModerateLabelColor, text="Sell", textcolor=topModerateTextColor, size=size.tiny)
  865.  
  866. plotshape((showBottomWeak and bottomWeakFiltered) or (showBottomModerate and bottomModerateFiltered) or (showBottomStrong and bottomStrongFiltered), title="Bottom Buy", style=shape.labelup, location=location.belowbar, color=color.new(bottomLongColor, 0), text="Buy", textcolor=bottomTextColor, size=size.tiny)
  867. plotshape(momentumBuyFiltered, title="Bottom Momentum Buy", style=shape.labelup, location=location.belowbar, color=momentumLabelColor, text="Buy", textcolor=momentumTextColor, size=size.small)
  868.  
  869. plotshape(hfBuyFiltered, title="hf_signals Buy", style=shape.labelup, location=location.belowbar, color=hfSignalsBuyLabelColor, text="HF Buy", textcolor=hfSignalsBuyTextColor, size=size.tiny)
  870. plotshape(hfSellFiltered, title="hf_signals Sell", style=shape.labeldown, location=location.abovebar, color=hfSignalsSellLabelColor, text="HF Sell", textcolor=hfSignalsSellTextColor, size=size.tiny)
  871.  
  872. if overnightGapBuyFiltered and showOvernightGapBuy
  873. label.new(bar_index, low, "GAP UP\n" + str.tostring(up_prob) + "% (C:" + str.tostring(up_cons) + "/4)", style=label.style_label_up, color=color.new(color.blue, 0), textcolor=color.white, size=size.normal)
  874.  
  875. if overnightGapSellFiltered and showOvernightGapSell
  876. label.new(bar_index, high, "GAP DN\n" + str.tostring(dn_prob) + "% (C:" + str.tostring(dn_cons) + "/4)", style=label.style_label_down, color=color.new(color.orange, 0), textcolor=color.white, size=size.normal)
  877.  
  878. weakAlert = bottomWeakFiltered and weakAlertsEnabled
  879. moderateAlert = bottomModerateFiltered and moderateAlertsEnabled
  880. strongAlert = bottomStrongFiltered and strongAlertsEnabled
  881. momentumAlert = momentumBuyFiltered and momentumAlertsEnabled
  882.  
  883. alertcondition(topStrongFiltered and topStrongAlertsEnabled, title="Strong Sell Signal", message="Strong sell signal detected")
  884. alertcondition(topModerateFiltered and topModerateAlertsEnabled, title="Moderate Sell Signal", message="Moderate sell signal detected")
  885. alertcondition(weakAlert, title="Weak Buy Signal", message="Weak buy signal detected")
  886. alertcondition(moderateAlert, title="Moderate Buy Signal", message="Moderate buy signal detected")
  887. alertcondition(strongAlert, title="Strong Buy Signal", message="Strong buy signal detected")
  888. alertcondition(momentumAlert, title="Momentum Buy Signal", message="Momentum buy signal detected")
  889. alertcondition(hfBuyFiltered and hfBuyAlertsEnabled, title="HF Buy Signal", message="Buy: hf_signals")
  890. alertcondition(hfSellFiltered and hfSellAlertsEnabled, title="HF Sell Signal", message="Sell: hf_signals")
  891. alertcondition(overnightGapBuyFiltered and overnightGapAlertsEnabled, title="Overnight Gap Buy", message="Overnight Gap buy signal")
  892. alertcondition(overnightGapSellFiltered and overnightGapAlertsEnabled, title="Overnight Gap Sell", message="Overnight Gap sell signal")
  893.  
  894. // === Webhook / Dynamic Alert Logic ===
  895. // This function constructs a JSON string to send to your webhook. This permits a precise signal description with just one webhook
  896. // Ex: {"ticker": "BTCUSDT", "price": "65432.10", "value_text": "Strong Sell", value_float:-1.0, direction:"bearish", action:"sell"}
  897. // How to set up the WebhookOnce you have saved the modified code and added the script to your chart:
  898. // -- Click the Alerts icon (clock) on the right sidebar or press Alt + A.
  899. // -- Condition: Select BotBoys SuperScript [FTF].
  900. // -- Action: Select "Any alert() function call". This is crucial; it tells TradingView to listen to the code we just added rather than the old static alert conditions.
  901. // -- Notification Tab:
  902. // -- Check Webhook URL.
  903. // -- Paste your destination URL (e.g., from Discord, Zapier, or your trading bot).
  904. // -- Message Box: You can leave this as {{strategy.order.alert_message}} or simply {{alert_message}}. Because we defined the message inside the alert() function in the code, TradingView will pass that JSON string directly to your webhook.
  905.  
  906. // Helper function to generate the JSON payload
  907. get_payload(name, valFloat, dir, act) =>
  908. string expiry = str.tostring(timenow + (alertExpiry * 60000))
  909. '{"ticker": "' + syminfo.ticker +
  910. '", "price": "' + str.tostring(close) +
  911. '", "value_text": "'+ name +
  912. '", "value_float": '+ str.tostring(valFloat) +
  913. ', "direction": "' + dir +
  914. '", "action": "' + act +
  915. '", "secret_key": "' + webhookKey +
  916. '", "expires_at": ' + expiry + '}'
  917.  
  918. // Top Finder Signals
  919. if topStrongFiltered
  920. alert(get_payload("Strong Sell", -1.0, "bearish", "sell"), alert.freq_once_per_bar)
  921. if topModerateFiltered
  922. alert(get_payload("Moderate Sell", -1.0, "bearish", "sell"), alert.freq_once_per_bar)
  923.  
  924. // Bottom Finder Signals
  925. if weakAlert
  926. alert(get_payload("Weak Buy", 1.0, "bullish", "buy"), alert.freq_once_per_bar)
  927. if moderateAlert
  928. alert(get_payload("Moderate Buy", 1.0, "bullish", "buy"), alert.freq_once_per_bar)
  929. if strongAlert
  930. alert(get_payload("Strong Buy", 1.0, "bullish", "buy"), alert.freq_once_per_bar)
  931. if momentumAlert
  932. alert(get_payload("Momentum Buy", 1.0, "bullish", "buy"), alert.freq_once_per_bar)
  933.  
  934. // HF Signals
  935. if hfBuyFiltered and hfBuyAlertsEnabled
  936. alert(get_payload("HF Buy", 1.0, "bullish", "buy"), alert.freq_once_per_bar)
  937. if hfSellFiltered and hfSellAlertsEnabled
  938. alert(get_payload("HF Sell", -1.0, "bearish", "sell"), alert.freq_once_per_bar)
  939.  
  940. // Overnight Gap Signals
  941. if overnightGapBuyFiltered and overnightGapAlertsEnabled
  942. alert(get_payload("Overnight Gap Buy (Prob: " + str.tostring(up_prob) + "% | C:" + str.tostring(up_cons) + "/4)", 1.0, "bullish", "buy"), alert.freq_once_per_bar)
  943. if overnightGapSellFiltered and overnightGapAlertsEnabled
  944. alert(get_payload("Overnight Gap Sell (Prob: " + str.tostring(dn_prob) + "% | C:" + str.tostring(dn_cons) + "/4)", -1.0, "bearish", "sell"), alert.freq_once_per_bar)
  945.  
  946. // --- SPY / ES / SPX Converter ---
  947. float spyClose = showConverter ? request.security("AMEX:SPY", timeframe.period, close) : na
  948. float esClose = showConverter ? request.security("CME_MINI:ES1!", timeframe.period, close) : na
  949. float spxClose = showConverter ? request.security("SP:SPX", timeframe.period, close) : na
  950.  
  951. var table tblConv = na
  952. if showConverter and barstate.islast
  953. string tablePosStr = convPositionStr == "Bottom Right" ? position.bottom_right : convPositionStr == "Top Right" ? position.top_right : convPositionStr == "Bottom Left" ? position.bottom_left : position.top_left
  954. tblConv := table.new(tablePosStr, 4, 4, border_width=1, frame_color=color.new(color.gray, 80), border_color=color.new(color.gray, 80), bgcolor=color.new(color.black, 90))
  955.  
  956. table.cell(tblConv, 0, 0, "Symbol", text_color=color.white, bgcolor=color.new(color.gray, 80))
  957. table.cell(tblConv, 1, 0, "Price", text_color=color.white, bgcolor=color.new(color.gray, 80))
  958. table.cell(tblConv, 2, 0, "to SPX", text_color=color.white, bgcolor=color.new(color.gray, 80))
  959. table.cell(tblConv, 3, 0, "Result", text_color=color.white, bgcolor=color.new(color.gray, 80))
  960.  
  961. table.cell(tblConv, 0, 1, "SPY", text_color=color.white)
  962. table.cell(tblConv, 1, 1, str.tostring(spyClose, format.mintick), text_color=color.white)
  963. table.cell(tblConv, 2, 1, "x" + str.tostring(spxClose / spyClose, "#.####"), text_color=color.white)
  964. table.cell(tblConv, 3, 1, str.tostring(spyClose * (spxClose / spyClose), format.mintick), text_color=color.white)
  965.  
  966. table.cell(tblConv, 0, 2, "ES", text_color=color.white)
  967. table.cell(tblConv, 1, 2, str.tostring(esClose, format.mintick), text_color=color.white)
  968. float esOffset = spxClose - esClose
  969. string esOffStr = (esOffset >= 0 ? "+" : "") + str.tostring(esOffset, "#.##")
  970. table.cell(tblConv, 2, 2, esOffStr, text_color=color.white)
  971. table.cell(tblConv, 3, 2, str.tostring(esClose + esOffset, format.mintick), text_color=color.white)
  972.  
  973. table.cell(tblConv, 0, 3, "SPX", text_color=color.white)
  974. table.cell(tblConv, 1, 3, str.tostring(spxClose, format.mintick), text_color=color.white)
  975. table.cell(tblConv, 2, 3, "-", text_color=color.white)
  976. table.cell(tblConv, 3, 3, str.tostring(spxClose, format.mintick), text_color=color.white)
Advertisement
Add Comment
Please, Sign In to add comment