Created
May 25, 2025 23:45
-
-
Save valmont/f068fd53e1cba7f776abe34f0a8e80e2 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=6 | |
| strategy("TTR + Supertrend + NY Clarity Filter", overlay=true) | |
| // --- Supertrend Parameters --- | |
| atrPeriod = input.int(10, "ATR Length", minval=1) | |
| factor = input.float(3.0, "Factor", minval=0.01, step=0.01) | |
| // --- TTR Inputs (simplified example placeholders) --- | |
| ttrLongCondition = ta.crossover(ta.sma(close, 5), ta.sma(close, 20)) // Replace with actual TTR logic | |
| ttrShortCondition = ta.crossunder(ta.sma(close, 5), ta.sma(close, 20)) // Replace with actual TTR logic | |
| // --- Supertrend Calculation --- | |
| [supertrend, direction] = ta.supertrend(factor, atrPeriod) | |
| // --- NY Clarity Filter Inputs --- | |
| nyOpenHour = input.int(9, "NY Open Hour (ET)", minval=0, maxval=23) | |
| nyOpenMin = input.int(30, "NY Open Minute (ET)", minval=0, maxval=59) | |
| premarketStartHour = input.int(7, "Premarket Start Hour (ET)", minval=0, maxval=23) | |
| premarketStartMin = input.int(0, "Premarket Start Minute (ET)", minval=0, maxval=59) | |
| premarketVolThreshold = input.float(80, "Premarket Volume % Threshold", minval=0, maxval=200) | |
| overnightRangeCompressionPct = input.float(50, "Max Overnight Range Compression %", minval=0, maxval=100) | |
| openingVolumeThrustMultiplier = input.float(2.0, "Opening Minute Volume Thrust Multiplier", minval=0.1, maxval=10) | |
| // --- Helper Function --- | |
| f_isInSession(_startH, _startM, _endH, _endM) => | |
| (hour > _startH or (hour == _startH and minute >= _startM)) and | |
| (hour < _endH or (hour == _endH and minute <= _endM)) | |
| // Premarket and NY session determination | |
| premarketSession = f_isInSession(premarketStartHour, premarketStartMin, nyOpenHour, nyOpenMin) | |
| nySession = f_isInSession(nyOpenHour, nyOpenMin, 16, 0) | |
| // --- NY Clarity Filter Data Storage --- | |
| var float[] premarketVols = array.new_float() | |
| var float premarketVolToday = 0.0 | |
| var int premarketDay_ = na // <<< FIX: changed variable name from "premarketDay" to "premarketDay_" | |
| // Reset daily premarket volume | |
| if dayofmonth != premarketDay_ | |
| premarketDay_ := dayofmonth | |
| premarketVolToday := 0.0 | |
| // Accumulate premarket volume | |
| if premarketSession | |
| premarketVolToday += volume | |
| // Store premarket volume at NY open | |
| if (hour == nyOpenHour and minute == nyOpenMin and barstate.islast) | |
| array.unshift(premarketVols, premarketVolToday) | |
| if array.size(premarketVols) > 10 | |
| array.pop(premarketVols) | |
| // 10-day avg premarket volume | |
| premarketVolAvg = 0.0 | |
| if array.size(premarketVols) > 0 | |
| sumVol = 0.0 | |
| for i = 0 to array.size(premarketVols) - 1 | |
| sumVol += array.get(premarketVols, i) | |
| premarketVolAvg := sumVol / array.size(premarketVols) | |
| // Filter 1: Premarket volume % | |
| premarketVolPct = premarketVolAvg > 0 ? (premarketVolToday / premarketVolAvg) * 100 : 100 | |
| filter1 = premarketVolPct >= premarketVolThreshold | |
| // Filter 2: Overnight Range Compression | |
| prevClose = request.security(syminfo.tickerid, "D", close[1]) | |
| todayOpen = open | |
| overnightRange = math.abs(todayOpen - prevClose) | |
| var float[] overnightRanges = array.new_float() | |
| if (hour == nyOpenHour and minute == nyOpenMin and barstate.islast) | |
| array.unshift(overnightRanges, overnightRange) | |
| if array.size(overnightRanges) > 10 | |
| array.pop(overnightRanges) | |
| overnightRangeAvg = 0.0 | |
| if array.size(overnightRanges) > 0 | |
| sumRange = 0.0 | |
| for i = 0 to array.size(overnightRanges) - 1 | |
| sumRange += array.get(overnightRanges, i) | |
| overnightRangeAvg := sumRange / array.size(overnightRanges) | |
| compressionPct = overnightRangeAvg > 0 ? (overnightRange / overnightRangeAvg) * 100 : 100 | |
| filter2 = compressionPct <= overnightRangeCompressionPct | |
| // Filter 3: PDH/PDL Sweep + Rejection | |
| prevHigh = request.security(syminfo.tickerid, "D", high[1]) | |
| prevLow = request.security(syminfo.tickerid, "D", low[1]) | |
| sweptPDH = high > prevHigh and close < prevHigh | |
| sweptPDL = low < prevLow and close > prevLow | |
| filter3 = sweptPDH or sweptPDL | |
| // Filter 4: Opening Minute Volume Thrust | |
| var float openingMinVolume = na | |
| if (hour == nyOpenHour and minute == nyOpenMin) | |
| openingMinVolume := volume | |
| var float[] preNyVolumes = array.new_float() | |
| if not nySession and not premarketSession and barstate.islast | |
| array.unshift(preNyVolumes, volume) | |
| if array.size(preNyVolumes) > 10 | |
| array.pop(preNyVolumes) | |
| preNyVolAvg = 0.0 | |
| if array.size(preNyVolumes) > 0 | |
| sumVol = 0.0 | |
| for i = 0 to array.size(preNyVolumes) - 1 | |
| sumVol += array.get(preNyVolumes, i) | |
| preNyVolAvg := sumVol / array.size(preNyVolumes) | |
| filter4 = openingMinVolume >= preNyVolAvg * openingVolumeThrustMultiplier | |
| // Final filter score and boolean | |
| filterScore = (filter1 ? 1 : 0) + (filter2 ? 1 : 0) + (filter3 ? 1 : 0) + (filter4 ? 1 : 0) | |
| sessionLikelyClean = filterScore >= 3 | |
| // --- Strategy Entry Conditions --- | |
| longSupertrend = direction < 0 // uptrend | |
| shortSupertrend = direction > 0 // downtrend | |
| ttrLongSignal = ttrLongCondition and longSupertrend | |
| ttrShortSignal = ttrShortCondition and shortSupertrend | |
| longEntryAllowed = sessionLikelyClean and ttrLongSignal | |
| shortEntryAllowed = sessionLikelyClean and ttrShortSignal | |
| if (longEntryAllowed) | |
| strategy.entry("Long", strategy.long) | |
| else if (ttrLongSignal and not sessionLikelyClean) | |
| label.new(bar_index, high, "Long Blocked", color=color.red, style=label.style_label_down, textcolor=color.white, size=size.small) | |
| if (shortEntryAllowed) | |
| strategy.entry("Short", strategy.short) | |
| else if (ttrShortSignal and not sessionLikelyClean) | |
| label.new(bar_index, low, "Short Blocked", color=color.red, style=label.style_label_up, textcolor=color.white, size=size.small) | |
| // --- Dashboard Plot --- | |
| var label dash = na | |
| dashboardText = "NY Clarity Filter\n" + | |
| "Premkt Vol %: " + str.tostring(premarketVolPct, "#.0") + "% (" + (filter1 ? "✔" : "✘") + ")\n" + | |
| "Overnight Range Compression: " + str.tostring(compressionPct, "#.0") + "% (" + (filter2 ? "✔" : "✘") + ")\n" + | |
| "PDH/PDL Sweep+Reject: " + (filter3 ? "✔" : "✘") + "\n" + | |
| "Opening Vol Thrust: " + (filter4 ? "✔" : "✘") + "\n" + | |
| "Score: " + str.tostring(filterScore) + "/4\n" + | |
| "Session Clean: " + (sessionLikelyClean ? "✔" : "✘") | |
| if na(dash) | |
| dash := label.new(bar_index, high, dashboardText, xloc.bar_index, yloc.price, style=label.style_label_left, color=color.new(color.black, 80), textcolor=color.white, size=size.small) | |
| else | |
| label.set_xy(dash, bar_index, high) | |
| label.set_text(dash, dashboardText) | |
| bgcolor(sessionLikelyClean ? color.new(color.green, 90) : color.new(color.red, 90)) | |
| alertcondition(not sessionLikelyClean and (ttrLongSignal or ttrShortSignal), title="Blocked Trade Due to NY Clarity Filter", message="Trade blocked because NY session likely not clean.") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment