ChannellerChanneller Pro - Multi-Pivot Regression Channels with Trend Validation
What This Indicator Does
Channeller Pro automatically detects and draws price channels by connecting multiple pivot points using linear regression rather than simply connecting two points. The indicator displays parallel support and resistance lines that define the current trend channel, along with an optional mid-line for mean reversion analysis.
Channels automatically appear when valid trend conditions are met and disappear when the trend structure breaks, keeping your chart clean and showing only actionable information.
---
How It Works (Methodology)
1. Multi-Pivot Linear Regression
Unlike simple channel indicators that connect only 2 pivot points, this indicator collects 3-5 pivot lows (for bullish channels) or pivot highs (for bearish channels) and calculates a least-squares linear regression line through them. This produces a statistically best-fit trendline that is more resistant to noise from a single errant pivot.
The regression calculation outputs:
- Slope: The angle/direction of the trend
- Intercept: The starting price level
- R² (coefficient of determination): A value from 0 to 1 measuring how well the pivot points align. Higher R² means the pivots form a cleaner, more reliable trendline. The default minimum is 0.70.
2. Higher-Low / Lower-High Pattern Validation
For a bullish channel to form, the indicator requires each successive pivot low to be higher than the previous pivot low (the definition of an uptrend). For bearish channels, each pivot high must be lower than the previous (downtrend structure). This filter prevents channels from forming during choppy, non-trending conditions.
3. ADX Trend Strength Filter
The indicator calculates the Average Directional Index (ADX) to measure trend strength. Channels only appear when ADX exceeds a user-defined threshold (default: 20). When ADX drops below this level, indicating the trend has weakened, channels automatically disappear. This prevents false channels during sideways/ranging markets.
4. Channel Width Calculation
Once the regression support line is established, the indicator finds the highest high (for bull channels) or lowest low (for bear channels) between the first and last pivot. A parallel line is drawn at this distance to form the opposite channel boundary.
5. Channel Respect Monitoring
The indicator tracks how price interacts with channel boundaries:
- Bounces: Price touches the boundary and reverses
- Pierces: Price closes beyond the boundary
If price pierces through a channel boundary multiple times, the channel is invalidated and removed, signaling the trend structure has broken.
---
How to Use This Indicator
Identifying Trends
- A green channel (bullish) indicates an uptrend with higher lows
- A red channel (bearish) indicates a downtrend with lower highs
- The R² value in the label shows channel quality (higher = more reliable)
Trading Applications
- Trend Following: Trade in the direction of the channel slope
- Support/Resistance: Use channel boundaries as potential reaction zones
- Mean Reversion: The optional mid-line (dashed) can serve as a target for pullback entries
- Breakout Preparation: When a channel disappears, it signals the prior trend structure has ended
Reading the Labels
- "BULL R²:0.85 (4 pivots)" means a bullish channel with 85% regression fit using 4 pivot points
- Orange-colored labels indicate weaker channels (R² between 0.70-0.85)
- Green/red labels indicate stronger channels (R² above 0.85)
---
Input Settings Explained
| Setting | Description |
|---------|-------------|
| Pivot Lookback Left/Right | Bars required on each side to confirm a pivot high/low |
| Min Pivots for Channel | Minimum pivot points required (more = stricter) |
| Max Pivots to Track | Maximum pivots stored (older pivots are dropped) |
| Min R² Score | Minimum regression quality (0.70 = 70% fit) |
| ADX Threshold | Minimum ADX value to show channels (20 = moderate trend) |
| Require HL/LH Pattern | Enforce higher-lows for bull, lower-highs for bear |
---
What Makes This Different
This indicator combines multiple validation layers that work together:
1. Regression vs. 2-point lines: More statistically robust trendlines
2. R² quality scoring: Quantifies how clean the trend structure is
3. Pattern validation: Ensures proper trend structure (HL/LH)
4. ADX filtering: Confirms trend exists before drawing channels
5. Auto-invalidation: Channels disappear when broken, not manually
These components create a self-cleaning channel system that only displays high-probability trend channels.
---
Alerts Available
- Bull/Bear Channel Formed
- Bull/Bear Channel Broken
- New Pivot High/Low Detected
Educational
Order Blocks INDIBOT 3D | INDIBOT ABO SALTAN 11 //@version=6
indicator("Order Blocks INDIBOT 3D | INDIBOT ABO SALTAN ", overlay = true,
max_boxes_count = 500, max_labels_count = 500, max_lines_count = 500, max_polylines_count = 100, max_bars_back = 5000)
//#region CONSTANTS
// Core constants that control stored OB capacity and label size.
const int MAX_STORED_OBS = 50
const int retestSize = 4
//#endregion
//#region INPUTS
// Core user controls for OB behavior, volume delta, 3D style and alerts.
grpOB = "ORDER BLOCKS"
swingLen = input.int(5, "Swing Length", minval = 1, group = grpOB, inline = "sw", display = display.none)
bullObColor = input.color(color.new(color.teal, 55), "", group = grpOB, inline = "sw")
bearObColor = input.color(color.new(color.red, 55), "", group = grpOB, inline = "sw")
invMethod = input.string("Wick", "Invalidation", options = , group = grpOB, display = display.none)
showNearestX = input.int(3, "Show Nearest", minval = 1, maxval = 20, group = grpOB, display = display.none)
extendZones = input.int(10, "Extend Zones", minval = 0, group = grpOB,
tooltip = "This will extend the zones by X candles.", display = display.none)
showRetestLbl = input.bool(true, "Retest Labels", group = grpOB, inline = "tog")
hideInvalid = input.bool(true, "Hide Invalidated Zones", group = grpOB, inline = "tog")
grpVD = "VOLUME DELTA"
vdEnable = input.bool(true, "Enable", group = grpVD, inline = "vd")
vdBullColor = input.color(color.new(color.teal, 65), "", group = grpVD, inline = "vd")
vdBearColor = input.color(color.new(color.red, 65), "", group = grpVD, inline = "vd")
vd3D = input.bool(true, "3D", group = grpVD, inline = "3d", tooltip = "Adds 3D-style depth faces.") and vdEnable
vd3DDepth = input.int(5, "", group = grpVD, inline = "3d", minval = 1, maxval = 5, display = display.none)
displayStyle = input.string("Vertical", "Display Style", options = , group = grpVD,
tooltip = "Horizontal: split shown top/bottom. Vertical: split shown left/right across the zone.", display = display.none)
vdTfIn = input.timeframe("", "Volume Delta Timeframe", group = grpVD,
tooltip = "Lower timeframe used to estimate delta")
showTotalVol = input.bool(true, "Display Total Volume", group = grpVD,
tooltip = "Displays total volume (Bull+Bear) from the active delta source.", inline = "vd2") and vdEnable
showDeltaPct = input.bool(true, "Show Delta %", group = grpVD, inline = "vd2",
tooltip = "Shows bullish vs bearish volume split. If selected TF is lower than chart TF, uses LTF data; otherwise uses chart TF.") and vdEnable
vdTextColor = input.color(color.white, "", group = grpVD, inline = "vd2")
grpAL = "ALERTS"
alBullOB = input.bool(true, "Bullish Order Block", group = grpAL, inline = "oba")
alBearOB = input.bool(true, "Bearish Order Block", group = grpAL, inline = "oba")
alBullRetest = input.bool(true, "Bullish OB Retest", group = grpAL, inline = "obr")
alBearRetest = input.bool(true, "Bearish OB Retest", group = grpAL, inline = "obr")
//#endregion
//#region TYPES
// Custom structs for order blocks and 3D poly drawing.
type PolyParams
array points
color lineColor
color fillColor
int lineWidth
type ObRec
int leftIndex
int leftTime
int createdIndex
int createdTime
float top
float bottom
bool isBull
bool active
bool retested
int retestIndex
int retestTime
int invalidIndex
int invalidTime
float bullVol
float bearVol
float totalVol
float bullPct
float bearPct
bool hasDelta
type RetestRec
int barIndex
bool isBull
int obLeftIndex
int obCreatedIndex
//#endregion
//#region GENERIC HELPERS
// Small utilities: clearing drawings, geometry helpers, nearest-OB picking.
method clearAll(array bx, array pl, array lb) =>
if bx.size() > 0
for i = 0 to bx.size() - 1
bx.get(i).delete()
bx.clear()
if pl.size() > 0
for i = 0 to pl.size() - 1
pl.get(i).delete()
pl.clear()
if lb.size() > 0
for i = 0 to lb.size() - 1
lb.get(i).delete()
lb.clear()
// Builds a simple side face for 3D-style boxes using chart points.
method sideBox(array pts, int x, float btm, float top, float depthY, int widthX) =>
pts.unshift(chart.point.from_index(x, btm))
pts.unshift(chart.point.from_index(x + widthX, btm + depthY))
pts.unshift(chart.point.from_index(x + widthX, top + depthY))
pts.unshift(chart.point.from_index(x, top))
pts.unshift(chart.point.from_index(x, btm))
// Returns true if a candle's high/low intersects the OB zone.
touchesZone(float zTop, float zBot, float cHigh, float cLow) =>
cHigh >= zBot and cLow <= zTop
// Distance from price to zone in price units, used to rank nearest zones.
zoneDistance(float px, float zTop, float zBot) =>
px > zTop ? px - zTop : px < zBot ? zBot - px : 0.0
// Inserts a distance+index pair into a sorted list, capped at kMax.
method insertBest(array dists, array idxs, float dist, int idx, int kMax) =>
if dists.size() == 0
dists.push(dist)
idxs.push(idx)
else
int pos = dists.size()
if dists.size() > 0
for j = 0 to dists.size() - 1
if dist < dists.get(j)
pos := j
break
dists.insert(pos, dist)
idxs.insert(pos, idx)
while dists.size() > kMax
dists.pop()
idxs.pop()
// Picks the k nearest bull/bear OBs to current price (optionally including invalid).
pickNearest(array store, bool wantBull, int kMax, bool includeInvalid) =>
array dists = array.new_float()
array idxs = array.new_int()
if store.size() > 0
for i = 0 to store.size() - 1
ObRec ob = store.get(i)
if ob.isBull == wantBull
bool ok = includeInvalid ? true : ob.active
if ok
float dist = zoneDistance(close, ob.top, ob.bottom)
dists.insertBest(idxs, dist, i, kMax)
idxs
formatVol(float v) =>
str.tostring(v, format.volume)
//#endregion
//#region VOLUME ENGINE (CHART OR LOWER TF)
// Per-bar total / bull / bear volume
tfSec(string tf) =>
timeframe.in_seconds(tf)
int chartSec = tfSec(timeframe.period)
int srcSec = tfSec(vdTfIn)
bool useLtf = not na(chartSec) and not na(srcSec) and srcSec < chartSec
getBarVols() =>
float tot = na
float bull = na
float bear = na
if not useLtf or vdTfIn == ""
float v = volume
bool up = close > open
bool dn = close < open
tot := v
bull := up ? v : 0.0
bear := dn ? v : 0.0
else
array oArr = request.security_lower_tf(syminfo.tickerid, vdTfIn, open)
array cArr = request.security_lower_tf(syminfo.tickerid, vdTfIn, close)
array vArr = request.security_lower_tf(syminfo.tickerid, vdTfIn, volume)
float tSum = 0.0
float bSum = 0.0
float sSum = 0.0
int n = array.size(vArr)
if n > 0
for i = 0 to n - 1
float v2 = array.get(vArr, i)
float o2 = array.get(oArr, i)
float c2 = array.get(cArr, i)
tSum += v2
if c2 > o2
bSum += v2
else if c2 < o2
sSum += v2
tot := tSum
bull := bSum
bear := sSum
= getBarVols()
//#endregion
//#region POC ENGINE (MOST-TOUCHED PRICE + VOLUME)
// Finds a POC between swing and BOS, then aggregates volume.
findMostTouchedPrice(int fromIdx, int toIdx, int nBins) =>
int span = toIdx - fromIdx
if span <= 0 or na(fromIdx) or na(toIdx)
else
float minP = 1e10
float maxP = -1e10
for idx = fromIdx to toIdx
int rel = bar_index - idx
if rel >= 0
float lo = low
float hi = high
if not na(lo) and not na(hi)
if lo < minP
minP := lo
if hi > maxP
maxP := hi
if not (minP < maxP)
else
float step = (maxP - minP) / nBins
step := step <= 0 ? syminfo.mintick : step
array diffCnt = array.new_float(nBins, 0.0)
for idx = fromIdx to toIdx
int rel2 = bar_index - idx
if rel2 >= 0
float lo2 = low
float hi2 = high
if not na(lo2) and not na(hi2)
int sBin = int(math.floor((lo2 - minP) / step))
int eBin = int(math.floor((hi2 - minP) / step))
sBin := sBin < 0 ? 0 : sBin > nBins - 1 ? nBins - 1 : sBin
eBin := eBin < 0 ? 0 : eBin > nBins - 1 ? nBins - 1 : eBin
float cStart = diffCnt.get(sBin)
diffCnt.set(sBin, cStart + 1.0)
if eBin + 1 < nBins
float cEnd = diffCnt.get(eBin + 1)
diffCnt.set(eBin + 1, cEnd - 1.0)
int bestBin = 0
float bestCnt = 0.0
float runCnt = 0.0
for i = 0 to nBins - 1
runCnt += diffCnt.get(i)
if runCnt > bestCnt
bestCnt := runCnt
bestBin := i
float poc = minP + (bestBin + 0.5) * step
// Aggregates total / bull / bear volume at a single price level (POC) for a range.
volumeAtPrice(int fromIdx, int toIdx, float poc) =>
int touches = 0
float totVol = 0.0
float bullVol = 0.0
float bearVol = 0.0
int span = toIdx - fromIdx
if not na(poc) and span >= 0
for step = 0 to span
int idx = toIdx - step
int rel = bar_index - idx
if rel >= 0
float lo = low
float hi = high
if not na(lo) and not na(hi) and lo <= poc and hi >= poc
touches += 1
float vTot = barTotVol
float vBull = barBullVol
float vBear = barBearVol
if not na(vTot)
totVol += vTot
if not na(vBull)
bullVol += vBull
if not na(vBear)
bearVol += vBear
// Wrapper: find POC first, then compute volume at that POC for the BOS range.
calcMostTouchedPriceVol(int fromIdx, int toIdx, int nBins) =>
= findMostTouchedPrice(fromIdx, toIdx, nBins)
= volumeAtPrice(fromIdx, toIdx, poc)
//#endregion
//#region ORDER BLOCK ENGINE (POC-BASED)
// Detects swing highs/lows, confirms BOS, anchors OB at first POC touch.
var array obs = array.new()
var array obRetests = array.new()
var int lastBullRetestBar = na
var int lastBearRetestBar = na
var float shPrice = na
var int shIdx = na
var float slPrice = na
var int slIdx = na
bool evNewBullOB = false
bool evNewBearOB = false
bool evBullRetest = false
bool evBearRetest = false
float ph = ta.pivothigh(high, swingLen, swingLen)
float pl = ta.pivotlow(low, swingLen, swingLen)
if not na(ph)
shPrice := ph
shIdx := bar_index - swingLen
if not na(pl)
slPrice := pl
slIdx := bar_index - swingLen
bool bosBearNow = not na(slPrice) and bar_index > slIdx and close < slPrice and close >= slPrice
bool bosBullNow = not na(shPrice) and bar_index > shIdx and close > shPrice and close <= shPrice
bool bosBear = bosBearNow
bool bosBull = bosBullNow
// Precompute BOS ranges and POC stats in global scope
int bosIdxBear = bar_index - 1
int fromIdxBear = slIdx
int toIdxBear = bosIdxBear
= calcMostTouchedPriceVol(fromIdxBear, toIdxBear, 40)
int bosIdxBull = bar_index - 1
int fromIdxBull = shIdx
int toIdxBull = bosIdxBull
= calcMostTouchedPriceVol(fromIdxBull, toIdxBull, 40)
// Keeps OB array trimmed to recent history and limits max stored OBs.
pruneObs() =>
int minLeft = math.max(0, bar_index - 4999)
if obs.size() > 0
for i = obs.size() - 1 to 0
ObRec ob = obs.get(i)
if ob.leftIndex < minLeft
obs.remove(i)
while obs.size() > MAX_STORED_OBS
bool removed = false
if obs.size() > 0
for j = obs.size() - 1 to 0
ObRec ob2 = obs.get(j)
if not ob2.active
obs.remove(j)
removed := true
break
if not removed and obs.size() > 0
obs.pop()
// Creates and seeds an OB record using a POC-anchored candle and BOS volumes.
addObFromPoc(int baseIdx, float top, float bottom, bool isBull, float totSeed, float bullSeed, float bearSeed, int createdIdx) =>
int offLeft = bar_index - baseIdx
int offCreated = bar_index - createdIdx
int leftTime = time
int createdTm = time
float tot = totSeed
float bVol = bullSeed
float sVol = bearSeed
bool hasDelta = tot > 0.0
float bullPct = hasDelta ? math.round((bVol / tot) * 100.0) : 50.0
float bearPct = hasDelta ? 100.0 - bullPct : 50.0
obs.unshift(ObRec.new(baseIdx, leftTime, createdIdx, createdTm, top, bottom, isBull,
true, false, na, na, na, na, bVol, sVol, tot, bullPct, bearPct, hasDelta))
pruneObs()
// Returns true if a proposed zone overlaps any active OB
obOverlapsActive(float zoneTop, float zoneBottom) =>
float zTop = math.max(zoneTop, zoneBottom)
float zBot = math.min(zoneTop, zoneBottom)
bool overlaps = false
if obs.size() > 0
for i = 0 to obs.size() - 1
ObRec ob = obs.get(i)
if ob.active
float oTop = math.max(ob.top, ob.bottom)
float oBot = math.min(ob.top, ob.bottom)
bool rangeOverlap = zTop >= oBot and zBot <= oTop
if rangeOverlap
overlaps := true
break
overlaps
// Returns true if there is a price gap between anchorIdx and bosIdx.
hasGapBetween(int anchorIdx, int bosIdx, bool isBull) =>
bool gap = false
int fromIdx = math.min(anchorIdx, bosIdx)
int toIdx = math.max(anchorIdx, bosIdx)
if toIdx - fromIdx >= 1
for absIdx = fromIdx + 1 to toIdx
int relNow = bar_index - absIdx
int relPrev = relNow + 1
if relNow >= 0 and relPrev >= 0
float hiPrev = high
float loPrev = low
float hiNow = high
float loNow = low
if not na(hiPrev) and not na(loPrev) and not na(hiNow) and not na(loNow)
if isBull
if loNow > hiPrev
gap := true
break
else
if hiNow < loPrev
gap := true
break
gap
// Bearish BOS → Bearish OB
if bosBear
int bosIdx = bosIdxBear
int fromIdx = fromIdxBear
int toIdx = toIdxBear
if not na(pocB) and touchesB > 0 and not na(fromIdx) and not na(toIdx)
int spanB = toIdx - fromIdx
int bestIdx = na
float runMaxHigh = na
if spanB >= 0
for step = 0 to spanB
int idx = toIdx - step
int rel = bar_index - idx
if rel >= 0
float lo = low
float hi = high
if not na(lo) and not na(hi)
runMaxHigh := na(runMaxHigh) ? hi : math.max(runMaxHigh, hi)
bool touches = lo <= pocB and hi >= pocB
if touches and hi == runMaxHigh
bestIdx := idx
bool gapLeg = not na(bestIdx) ? hasGapBetween(bestIdx, bosIdx, false) : false
if not na(bestIdx) and not gapLeg
int relBest = bar_index - bestIdx
float top = high
float bottom = low
if not obOverlapsActive(top, bottom)
addObFromPoc(bestIdx, top, bottom, false, totVolB, bullVolB, bearVolB, bosIdx)
evNewBearOB := true
slPrice := na
slIdx := na
// Bullish BOS → Bullish OB
if bosBull
int bosIdx2 = bosIdxBull
int fromIdx2 = fromIdxBull
int toIdx2 = toIdxBull
if not na(pocH) and touchesH > 0 and not na(fromIdx2) and not na(toIdx2)
int spanH = toIdx2 - fromIdx2
int bestIdx2 = na
float runMinLow = na
if spanH >= 0
for step = 0 to spanH
int idx2 = toIdx2 - step
int rel2 = bar_index - idx2
if rel2 >= 0
float lo2 = low
float hi2 = high
if not na(lo2) and not na(hi2)
runMinLow := na(runMinLow) ? lo2 : math.min(runMinLow, lo2)
bool touches = lo2 <= pocH and hi2 >= pocH
if touches and lo2 == runMinLow
bestIdx2 := idx2
bool gapLeg2 = not na(bestIdx2) ? hasGapBetween(bestIdx2, bosIdx2, true) : false
if not na(bestIdx2) and not gapLeg2
int relBest2 = bar_index - bestIdx2
float top2 = high
float bottom2 = low
if not obOverlapsActive(top2, bottom2)
addObFromPoc(bestIdx2, top2, bottom2, true, totVolH, bullVolH, bearVolH, bosIdx2)
evNewBullOB := true
shPrice := na
shIdx := na
// Invalidation and retest detection for existing OBs.
if obs.size() > 0
for i = 0 to obs.size() - 1
ObRec ob = obs.get(i)
if ob.active
bool invalid = false
int invIdx = na
int invTime = na
if ob.isBull
if invMethod == "Wick"
invalid := low < ob.bottom
invIdx := bar_index
invTime := time
else
if bar_index > 0
invalid := close < ob.bottom
invIdx := bar_index - 1
invTime := time
else
if invMethod == "Wick"
invalid := high > ob.top
invIdx := bar_index
invTime := time
else
if bar_index > 0
invalid := close > ob.top
invIdx := bar_index - 1
invTime := time
if invalid
ob.active := false
ob.invalidIndex := invIdx
ob.invalidTime := invTime
bool retestPrev = false
int retestBar = na
int retestTm = na
if bar_index > 0
if ob.isBull
bool opensAbovePrev = open > ob.top
bool closesAbovePrev = close > ob.top
bool wickTouchesPrev = low <= ob.top and low >= ob.bottom
retestPrev := opensAbovePrev and closesAbovePrev and wickTouchesPrev
else
bool opensBelowPrev = open < ob.bottom
bool closesBelowPrev = close < ob.bottom
bool wickTouchesPrev = high >= ob.bottom and high <= ob.top
retestPrev := opensBelowPrev and closesBelowPrev and wickTouchesPrev
if retestPrev
retestBar := bar_index - 1
retestTm := time
if retestPrev and not na(retestBar) and retestBar > ob.createdIndex
ob.retested := true
ob.retestIndex := retestBar
ob.retestTime := retestTm
int lastSideBar = ob.isBull ? lastBullRetestBar : lastBearRetestBar
bool canLog = na(lastSideBar) or retestBar - lastSideBar >= 4
if canLog
obRetests.unshift(RetestRec.new(retestBar, ob.isBull, ob.leftIndex, ob.createdIndex))
if ob.isBull
evBullRetest := true
lastBullRetestBar := retestBar
else
evBearRetest := true
lastBearRetestBar := retestBar
obs.set(i, ob)
//#endregion
//#region DRAW ENGINE (ZONES + VOLUME + 3D)
// Handles all boxes, polylines and labels for OBs and 3D faces.
bool showVD = vdEnable
bool isVert = displayStyle == "Vertical"
bool isHorz = not isVert
float dayAtr = ta.atr(14)
var array allBoxes = array.new()
var array allPolys = array.new()
var array allLabels = array.new()
drawPoly(PolyParams pp) =>
if not na(pp) and not na(pp.points) and pp.points.size() > 0
allPolys.unshift(polyline.new(points = pp.points, line_color = pp.lineColor, fill_color = pp.fillColor))
method pushBox(array store, box b) =>
store.unshift(b)
method pushLabel(array store, label l) =>
store.unshift(l)
// Chooses base colors for OB zones depending on vdEnable and bull/bear type.
obColors(ObRec ob) =>
color bullCol = vdEnable ? vdBullColor : bullObColor
color bearCol = vdEnable ? vdBearColor : bearObColor
color baseCol = ob.isBull ? bullCol : bearCol
color faded = ob.active ? baseCol : color.new(baseCol, 85)
// Computes right-most bar index for drawing an OB, considering extension and invalidation.
obRightIndex(ObRec ob) =>
int activeRight = bar_index + extendZones
if ob.active
activeRight
else
na(ob.invalidIndex) ? activeRight : ob.invalidIndex
// Draws the main OB zone box on the chart.
drawObZoneBox(ObRec ob, color faded) =>
int xR = obRightIndex(ob)
int xL = ob.leftIndex
int minBar = bar_index - 4999
if xL < minBar
xL := minBar
xR := math.max(xR, xL)
box bx = box.new(left = xL, right = xR, top = ob.top, bottom = ob.bottom, xloc = xloc.bar_index, bgcolor = faded, border_color = na, border_width = 0)
allBoxes.pushBox(bx)
// Draws a retest marker (triangle) when price revisits an OB.
drawRetestLabels(array bullAct, array bearAct, array bullInv, array bearInv) =>
int ret = 0
if showRetestLbl and obRetests.size() > 0
int minBar = bar_index - 4999
int lastBullLbl = na
int lastBearLbl = na
for i = obRetests.size() - 1 to 0
RetestRec r = obRetests.get(i)
if r.barIndex < minBar or r.barIndex > bar_index
RetestRec _trash = obRetests.remove(i)
else
bool hasDisplayedParent = false
if r.isBull
if bullAct.size() > 0
for j = 0 to bullAct.size() - 1
ObRec ob = obs.get(bullAct.get(j))
if ob.leftIndex == r.obLeftIndex and ob.createdIndex == r.obCreatedIndex
hasDisplayedParent := true
break
if not hasDisplayedParent and not hideInvalid and bullInv.size() > 0
for j = 0 to bullInv.size() - 1
ObRec ob = obs.get(bullInv.get(j))
if ob.leftIndex == r.obLeftIndex and ob.createdIndex == r.obCreatedIndex
hasDisplayedParent := true
break
else
if bearAct.size() > 0
for j = 0 to bearAct.size() - 1
ObRec ob = obs.get(bearAct.get(j))
if ob.leftIndex == r.obLeftIndex and ob.createdIndex == r.obCreatedIndex
hasDisplayedParent := true
break
if not hasDisplayedParent and not hideInvalid and bearInv.size() > 0
for j = 0 to bearInv.size() - 1
ObRec ob = obs.get(bearInv.get(j))
if ob.leftIndex == r.obLeftIndex and ob.createdIndex == r.obCreatedIndex
hasDisplayedParent := true
break
if not hasDisplayedParent
continue
int age = bar_index - r.barIndex
if age >= 0 and age <= 4999
if r.isBull
if not na(lastBullLbl) and r.barIndex - lastBullLbl < 3
continue
lastBullLbl := r.barIndex
else
if not na(lastBearLbl) and r.barIndex - lastBearLbl < 3
continue
lastBearLbl := r.barIndex
float yPrice = close
color baseCol = r.isBull ? bullObColor : bearObColor
st = r.isBull ? label.style_triangleup : label.style_triangledown
yl = r.isBull ? yloc.belowbar : yloc.abovebar
label newLbl = label.new(r.barIndex, yPrice, "", xloc = xloc.bar_index, yloc = yl, style = st,
color = color.new(baseCol, 0), textcolor = color.new(baseCol, 0), size = retestSize, force_overlay = true)
allLabels.pushLabel(newLbl)
ret
// Returns geometry used for volume overlay and 3D top view.
obGeom(ObRec ob) =>
int rawL = ob.leftIndex
int rawR = obRightIndex(ob)
int minBar = bar_index - 4999
int xL = math.max(rawL, minBar)
int xR = math.max(rawR, xL)
int widthX = vd3DDepth
int xR2 = xR + widthX
float yT = ob.top
float yB = ob.bottom
float h = yT - yB
// Converts bull/bear percentages into display strings (if enabled).
deltaTexts(float bullPct, float bearPct) =>
string bullTxt = showDeltaPct ? str.tostring(bullPct) + "%" : ""
string bearTxt = showDeltaPct ? str.tostring(bearPct) + "%" : ""
// Draws a text label with total volume on the right-bottom corner of the OB.
drawTotalVolLabel(int xL, int xR, float yT, float yB, float h, float total) =>
if showTotalVol
int cx = xR - 1
if cx < xL
cx := xL
float cy = yB + h * 0.25
string txt = formatVol(total)
label lb = label.new(cx, cy, txt, xloc = xloc.bar_index, style = label.style_label_right,
textcolor = vdTextColor, color = #ffffff00, size = size.small, force_overlay = true)
allLabels.pushLabel(lb)
// Fills the OB with bull/bear split either vertically or horizontally.
drawDeltaFills(int xL, int xR, float yT, float yB, float h, float bullPct, string bullTxt, string bearTxt) =>
color bullCol = vdEnable ? vdBullColor : bullObColor
color bearCol = vdEnable ? vdBearColor : bearObColor
if isVert
int splitX = xL + int((xR - xL) * (bullPct / 100.0))
splitX := xR - xL >= 2 ? math.max(xL + 1, math.min(xR - 1, splitX)) : xL
box bBull = box.new(xL, yT, splitX, yB, xloc = xloc.bar_index, bgcolor = bullCol, border_width = 0, text = bullTxt, text_color = vdTextColor, text_size = size.small)
box bBear = box.new(splitX, yT, xR, yB, xloc = xloc.bar_index, bgcolor = bearCol, border_width = 0, text = bearTxt, text_color = vdTextColor, text_size = size.small)
allBoxes.pushBox(bBull)
allBoxes.pushBox(bBear)
else
float midY = yB + h * (bullPct / 100.0)
box bBull = box.new(xL, midY, xR, yB, xloc = xloc.bar_index, bgcolor = bullCol, border_width = 0, text = bullTxt, text_color = vdTextColor, text_size = size.small)
box bBear = box.new(xL, yT, xR, midY, xloc = xloc.bar_index, bgcolor = bearCol, border_width = 0, text = bearTxt, text_color = vdTextColor, text_size = size.small)
allBoxes.pushBox(bBull)
allBoxes.pushBox(bBear)
// Track first visible bar index for 3D top face clipping.
var int leftVisIdx = na
if na(leftVisIdx) and time >= chart.left_visible_bar_time
leftVisIdx := bar_index
// Draws the 3D front faces and top faces based on bull/bear split and style.
drawDelta3D(int xL, int xR, int widthX, int xR2, float yT, float yB, float h, float bullPct) =>
color bullCol = vdEnable ? vdBullColor : bullObColor
color bearCol = vdEnable ? vdBearColor : bearObColor
float depthY = dayAtr * (0.1 * vd3DDepth)
int visibleLeft = na(leftVisIdx) ? xL : math.max(xL, leftVisIdx)
int visibleRight = xR
if isHorz
float midY = yB + h * (bullPct / 100.0)
if bullPct > 0
array ptsFrontBull = array.new()
ptsFrontBull.sideBox(xR, yB, midY, depthY, widthX)
drawPoly(PolyParams.new(ptsFrontBull, color.new(chart.fg_color, 90), color.new(bullCol, 70), 1))
if bullPct < 100
array ptsFrontBear = array.new()
ptsFrontBear.sideBox(xR, midY, yT, depthY, widthX)
drawPoly(PolyParams.new(ptsFrontBear, color.new(chart.fg_color, 90), color.new(bearCol, 70), 1))
if visibleRight > visibleLeft
array ptsTop = array.new()
ptsTop.unshift(chart.point.from_index(visibleRight + widthX, yT + depthY))
ptsTop.unshift(chart.point.from_index(visibleLeft + widthX, yT + depthY))
ptsTop.unshift(chart.point.from_index(visibleLeft, yT))
ptsTop.unshift(chart.point.from_index(visibleRight, yT))
ptsTop.unshift(chart.point.from_index(visibleRight + widthX, yT + depthY))
drawPoly(PolyParams.new(ptsTop, color.new(chart.fg_color, 90), color.new(bearCol, 70), 1))
else
array ptsFront = array.new()
ptsFront.sideBox(xR, yB, yT, depthY, widthX)
drawPoly(PolyParams.new(ptsFront, color.new(chart.fg_color, 90), color.new(bearCol, 70), 1))
if visibleRight > visibleLeft
float frac = bullPct / 100.0
int bullRight = visibleLeft + int((visibleRight - visibleLeft) * frac)
bullRight := math.max(visibleLeft, math.min(visibleRight, bullRight))
if bullPct > 0 and bullRight > visibleLeft
array ptsTopBull = array.new()
ptsTopBull.unshift(chart.point.from_index(bullRight + widthX, yT + depthY))
ptsTopBull.unshift(chart.point.from_index(visibleLeft + widthX, yT + depthY))
ptsTopBull.unshift(chart.point.from_index(visibleLeft, yT))
ptsTopBull.unshift(chart.point.from_index(bullRight, yT))
ptsTopBull.unshift(chart.point.from_index(bullRight + widthX, yT + depthY))
drawPoly(PolyParams.new(ptsTopBull, color.new(chart.fg_color, 90), color.new(bullCol, 70), 1))
if bullPct < 100 and visibleRight > bullRight
array ptsTopBear = array.new()
ptsTopBear.unshift(chart.point.from_index(visibleRight + widthX, yT + depthY))
ptsTopBear.unshift(chart.point.from_index(bullRight + widthX, yT + depthY))
ptsTopBear.unshift(chart.point.from_index(bullRight, yT))
ptsTopBear.unshift(chart.point.from_index(visibleRight, yT))
ptsTopBear.unshift(chart.point.from_index(visibleRight + widthX, yT + depthY))
drawPoly(PolyParams.new(ptsTopBear, color.new(chart.fg_color, 90), color.new(bearCol, 70), 1))
// Draws a full OB: zone, retest label, volume fill and 3D faces.
drawZoneAndVolume(ObRec ob) =>
= obColors(ob)
drawObZoneBox(ob, faded)
if showVD and ob.hasDelta
= obGeom(ob)
= deltaTexts(ob.bullPct, ob.bearPct)
drawTotalVolLabel(xL, xR, yT, yB, h, ob.totalVol)
drawDeltaFills(xL, xR, yT, yB, h, ob.bullPct, bullTxt, bearTxt)
if vd3D
drawDelta3D(xL, xR, widthX, xR2, yT, yB, h, ob.bullPct)
true
// Clear all previous drawings each bar before re-rendering current selection.
allBoxes.clearAll(allPolys, allLabels)
// Pick active and invalid OBs based on hideInvalid + showNearestX.
array bullActive = array.new_int()
array bearActive = array.new_int()
array bullInvalid = array.new_int()
array bearInvalid = array.new_int()
if hideInvalid
bullActive := pickNearest(obs, true, showNearestX, false)
bearActive := pickNearest(obs, false, showNearestX, false)
else
bullActive := pickNearest(obs, true, showNearestX, false)
bearActive := pickNearest(obs, false, showNearestX, false)
if obs.size() > 0
for i = 0 to obs.size() - 1
ObRec o = obs.get(i)
if not o.active
if o.isBull
bullInvalid.push(i)
else
bearInvalid.push(i)
if bearInvalid.size() > 0 and not hideInvalid
for i = 0 to bearInvalid.size() - 1
ObRec ob = obs.get(bearInvalid.get(i))
drawZoneAndVolume(ob)
if bearActive.size() > 0
for i = 0 to bearActive.size() - 1
ObRec ob = obs.get(bearActive.get(i))
drawZoneAndVolume(ob)
if bullInvalid.size() > 0 and not hideInvalid
for i = 0 to bullInvalid.size() - 1
ObRec ob = obs.get(bullInvalid.get(i))
drawZoneAndVolume(ob)
if bullActive.size() > 0
for i = 0 to bullActive.size() - 1
ObRec ob = obs.get(bullActive.get(i))
drawZoneAndVolume(ob)
// Draw all stored retest events on top of zones
drawRetestLabels(bullActive, bearActive, bullInvalid, bearInvalid)
//#endregion
//#region ALERTS
alertcondition(alBullOB and evNewBullOB, "Bullish Order Block", "New Bullish Order Block detected.")
alertcondition(alBearOB and evNewBearOB, "Bearish Order Block", "Bearish Order Block detected.")
alertcondition(alBullRetest and evBullRetest, "Bullish OB Retest", "Bullish Order Block retest.")
alertcondition(alBearRetest and evBearRetest, "Bearish OB Retest", "Bearish Order Block retest.")
if alBullOB and evNewBullOB
alert("Bullish Order Block detected.", alert.freq_once_per_bar)
if alBearOB and evNewBearOB
alert("Bearish Order Block detected.", alert.freq_once_per_bar)
if alBullRetest and evBullRetest
alert("Bullish Order Block retest.", alert.freq_once_per_bar)
if alBearRetest and evBearRetest
alert("Bearish Order Block retest.", alert.freq_once_per_bar)
// ==========================================================================================
// === Dashboard with Telegram Link ===
var table myTable = table.new(position.top_center, 1, 1, border_width=1, frame_color=color.black, bgcolor=color.white)
// Add Telegram Message to Dashboard
table.cell(myTable, 0, 0, "Join Telegram @STRATEGY INDIBOT", bgcolor=color.blue, text_color=color.white, text_size=size.normal)
Order Blocks & Breaker Blocks Destek DirencOrder Blocks & Breaker Blocks Destek Direnc Al Sat Bölgeleri
Multi-Symbol RSI Portfolio Simulator [Honestcowboy]The Multi-Symbol RSI Portfolio Simulator was build to test a theory, does the RSI indicator work in FOREX assets. Does it have predictive power. In this example the security function is used to fetch data for 40 different Forex pairs and it executes a very simple trading strategy. Sell when RSI hits 80, flatten if back below. Buy when RSI hits 20, flatten if back above. All executed on bar closes so no intra bar stuff.
🟦 🟦 🟦 Very Important Disclaimer
This is a very crude indicator which does not calculate trading costs and assumes perfect execution of trades with zero slippage. Forex markets carry high risk and most CFD brokers ask high spreads and trading costs so this approach will most likely only work on the H4 or above Daily charts. We are observing market behaviour here, it's a study of price action not an executable ready strategy. Do your own cost analysis, simulation if you want to take this idea further.
🟦 What is the point?
I build this indicator to prove that RSI indeed causes price action reactions especially on the intraday level in forex. Just like any study or paper not accounting for trading costs, this is just hypothetical and a starting point.
🟦 CALCULATION
On each bar close it will check RSI value for each pair in the list. If one of the pairs meets the condition for a long or short it will open that trade on next bar open and hold it till close. Add the profits/losses to the equity line. And if condition still true on next bar do it again, this is a very crude simple form of testing. Tradingview strategy tester is superior but does not allow for multi-pair trading.
Short Condition: RSI above 80
Short Exit: RSI below 70
Long Condition: RSI below 20
Long Exit: RSI above 30
The indicator also has 2 modes: Mean reversion and Trend mode. On default it uses Mean Reversion which is explained above. Trend mode does the exact opposite, so long above 80 short below 20.
I've also included a table with a heatmap showing all the trading pairs the indicator uses, it's current RSI value and color based on how close indicator is to shorting or longing it from green to red with gray being middle so no direction.
🟦 USE CASES
You can tweak the setting for different RSI values. Different RSI lengths and also freely change any trading pair inside the list to make your own test. I'm including some screenshots of tests here below:
KCP EMA Trend [Dr.K.C.Prakash]KCP EMA Trend
KCP EMA Trend is a clean, rule-based trend indicator designed to capture early and reliable trend shifts using EMA 20 and EMA 50 crossovers, with VWAP shown only as a visual reference.
🔹 Core Logic
BUY Signal
EMA 20 crosses above EMA 50
First signal of the bullish trend (no re-entry)
SELL Signal
EMA 20 crosses below EMA 50
First signal of the bearish trend (no re-entry)
🔹 VWAP Usage
VWAP is plotted only for visual guidance
Helps judge:
Strength of trend
Over-extension from mean
VWAP does not affect signals
🔹 Key Features
One signal per trend (no over-trading)
Works on all instruments
Best suited for intraday trading
Clean chart with minimal lag
Non-repainting logic
🔹 Best Use Case
Timeframes: 3-min / 5-min
Instruments: Index & liquid stocks
Trade direction confidence improves when:
BUY occurs near or above VWAP
SELL occurs near or below VWAP
🔹 Trading Philosophy
Trend first. Discipline always.
One clean signal is better than many noisy ones.
Session Highs & LowsCustom Highs & Lows
This indicator displays Previous Day High & Low along with session Highs & Lows for the Asian, London, and New York sessions.
Each session can be configured individually, allowing you to show or hide Highs, Lows, or both.
Basic customization options are included, such as:
level colors
line thickness
line extension length
transparency
line style
The main feature of this indicator is sweep detection.
For example, when the London session sweeps the Asian High or Low, the level automatically changes:
from a solid line to a dotted or dashed line
with reduced opacity
This makes it easy to see that the level has already been swept, while keeping the chart clean and uncluttered when looking for further confluences.
The indicator also supports alerts for all session Highs and Lows when they are swept, so you can receive notifications without constantly watching the chart.
Use it, test it, and if you have a solid idea for improvement, feel free to reach out. A lot of time went into building this indicator, and meaningful enhancements can always be discussed.
Directional Auto TrendlinesFeatures of This Script
Resistance trendlines: red, only downward connecting highs
Support trendlines: green, only upward connecting lows
Non-repainting, confirmed pivots
Optional pivot labels
Adjustable maxTLines and lineWidth
Lanovyx# Lanovyx
A comprehensive day trading indicator that generates **Pullback**, **Reversal**, and **Breakout** signals using the confluence of Stochastic oscillator lanes, VWAP standard deviation bands, and a unique Setup Window system.
---
## 🎯 Three Signal Families
| Signal | Label | Best For |
|--------|-------|----------|
| **Pullback (P)** | Blue | Trend continuation days |
| **Reversal (R)** | Green/Red | Range-bound markets |
| **Breakout (B)** | Orange | Compression breakouts |
**Strong signals (★)** appear when multiple confluence factors align—these are your highest probability setups.
---
## 📊 How It Works
**1. Regime Detection**
Lanovyx identifies market regime (Bull Trend, Bear Trend, Ranging, Coiling) using EMA alignment, market structure, and VWAP position.
**2. Setup Windows**
Unlike traditional indicators requiring all conditions on the same bar, Lanovyx uses Setup Windows. When a context event occurs (VWAP band touch, S/R level, divergence), a setup activates and stays valid for N bars, allowing the trigger to fire within that window.
**3. Signal Generation**
When regime, VWAP zone, stochastic position, and setup all align—a signal appears on your chart.
---
## 📋 Clean Info Table
The top-right table shows 6 essential rows for quick decision-making:
- **Regime** — Market direction (Bull/Bear Trend, Ranging, Coiling)
- **VWAP Zone** — Price location (Discount for buys, Premium for sells)
- **Stoch %D** — Oscillator position for timing
- **Session** — Market hours status
- **Last Signal** — Most recent signal type
- **Trade** — Current position status
Enable **Debug Mode** for additional diagnostic information.
---
## ✅ Entry Rules
**LONG Setup:**
✓ Regime = BULL TREND (or RANGING for reversal)
✓ VWAP Zone = Discount (-1, -2, -3)
✓ Stoch %D = 20-50 rising
✓ Session = ACTIVE
✓ Signal = P, R, or B below candle
**SHORT Setup:**
✓ Regime = BEAR TREND (or RANGING for reversal)
✓ VWAP Zone = Premium (+1, +2, +3)
✓ Stoch %D = 50-80 falling
✓ Session = ACTIVE
✓ Signal = P, R, or B above candle
---
## ⚙️ Key Features
- **3 Stochastic Lanes** — Fast (14), Mid (21), Slow (55) for multi-timeframe momentum
- **VWAP + Bands** — Session-anchored with ±1σ, ±2σ, ±3σ bands
- **Market Structure** — Higher High/Low, Lower High/Low detection
- **HTF Bias Filter** — Optional higher timeframe trend alignment
- **Volume Analysis** — Spike, dry-up, and climax detection
- **ATR Momentum** — Strong/Moderate/Weak classification
- **Trade Management** — ATR-based stop loss and profit targets
- **Signal Statistics** — Win rate and R-multiple tracking
- **Non-Repainting** — Strict mode enabled by default
- **Per-Direction Cooldown** — Prevents signal spam
---
## 🎛️ Recommended Settings
| Timeframe | Setup Window | Cooldown |
|-----------|--------------|----------|
| 5-minute | 10 bars | 5 bars |
| 15-minute | 10 bars | 5 bars |
---
## 📈 Best On
- **ETFs**: SPY, QQQ, IWM
- **Tech**: TSLA, NVDA, AMD, META, GOOG, AAPL
- **Futures**: MNQ, MES, NQ, ES
---
## ⚠️ Disclaimer
This indicator is for educational purposes only. It is not financial advice. Past performance does not guarantee future results. Always use proper risk management and never risk more than you can afford to lose.
---
## 📝 Version
v3.0
---
**Questions or feedback?** Drop a comment below!
Candle PatternsOverview
This indicator is a modernized, high-signal-quality candlestick pattern detector designed for the price-action trader. Unlike standard pattern recognizers that trigger on "weak" or indecisive candles (Dojis), this script uses a Momentum-Verified Logic to ensure that multi-candle patterns represent true market conviction.
The script scans for the most reliable reversal and continuation patterns while providing a built-in Moving Average filter to align signals with the prevailing trend.
Key Features
1. Momentum-Verified Logic (Anti-Doji)
Standard patterns like 3 Soldiers or 3 Crows often trigger with small-bodied candles that lack momentum. This indicator uses a custom isStrong() function requiring the candle body to be at least 50% of the total candle range. This effectively filters out weak signals and "leggy" wicks, showing you only when the bulls or bears are truly in control.
2. "Real Body" Engulfing
To reduce noise, the Engulfing logic is calculated using the Real Bodies (Open to Close). The current candle's body must completely engulf the previous candle's body, ignoring the "noise" of long wicks (thicks).
3. Integrated MA Filter
Trade only in the direction of the trend. When the MA Filter is enabled, bullish signals are only shown if price is above the Moving Average, and bearish signals if price is below it.
Supported Patterns
Engulfing (Body-to-Body): Powerful reversal signals ignoring wick noise.
3 Soldiers & 3 Crows: Momentum-verified (no Dojis allowed).
Morning Star & Evening Star: Three-candle bottom/top reversal patterns.
Meeting Line: Strike patterns where closing prices align.
Piercing Line & Dark Cloud: Deep-penetration reversal signals.
Harami: Traditional "inside bar" reversal setups.
How to Use
Select Your Patterns: Use the Settings menu to toggle specific patterns on or off.
Trend Alignment: Enable the "MA Filter" and set your period (e.g., 50 or 200) to filter for high-probability trend-following setups.
Y-Axis Alignment: For the best experience, ensure your Price Scale is set to "Merge All Scales into One (Right)" to keep labels perfectly pinned to price action.
Technical Details
Version: Pine Script v5
Overlay: Yes (Plots directly on candles)
Alerts: Compatible with alertcondition for "Once Per Bar Close" notifications.
Ichimoku bull bear trend Multi-BG by Pranojit Dey It gives you bullish and bearish bias using ichimoku, VWAP, SMA and Pivot. can be used as a great confirmation tool for trading. Use it. You will love it. Lets trade traders....
Momentum Screener: 1M/3M/52W HighThis script is a specialized momentum-tracking tool designed to identify "Stage 2" breakout candidates and high-growth stocks. It filters for three specific technical strengths simultaneously, ensuring you are only looking at tickers with both short-term explosive growth and long-term trend confirmation.
ICT 7/8/9am lines NY session + 7.30/8.30/9.30 linesThis script show the 7, 8, 9 AM NY session lines, together with the 7.30, 8.30 and 9.30AM lines, like ICT teaches in the 2024 Mentorship, lesson 2.
Feel free to use it!
BTC Spot Premium Index (Coinbase - Binance )Overview
This indicator measures the price difference between Bitcoin (BTC) on Coinbase and Binance, providing insights into the buying pressure from US-based investors versus the global market. A positive premium suggests stronger buying activity on Coinbase, which is often interpreted as a bullish signal for BTC.
Key Features
•
Premium Calculation: The core of the indicator is the formula: Coinbase BTC Price - Binance BTC Price.
•
Visual Representation: The premium is plotted as an oscillator with a zero line. Positive values are colored green, and negative values are red, making it easy to identify the prevailing market sentiment.
•
Moving Average: A customizable moving average (default is a 20-period SMA) is included to help identify the trend of the premium. The MA line is displayed in white.
•
Adjustable Parameters: You can adjust the moving average length and type (SMA, EMA, WMA, RMA) to fit your trading style.
How to Use
1.
Identify US Market Sentiment: A sustained positive (green) premium suggests strong buying interest from the US market, which can be a precursor to price appreciation.
2.
Spot Trend Reversals: A crossover of the premium line above the zero line can signal a shift from bearish to bullish sentiment. Conversely, a cross below the zero line may indicate weakening US demand.
3.
Confirm with Moving Average: When the premium line crosses above its moving average, it can signal strengthening momentum. A cross below the MA may suggest a potential slowdown.
Interpretation
•
Green Area (Positive Premium): Indicates that BTC is trading at a higher price on Coinbase than on Binance. This is generally considered a bullish sign, as it reflects strong demand from US investors.
•
Red Area (Negative Premium): Indicates that BTC is trading at a lower price on Coinbase. This may suggest weaker demand in the US market or stronger selling pressure.
•
White Line (Moving Average): Helps to smooth out the premium data and identify the underlying trend. Use it as a dynamic support or resistance level for the premium itself.
This indicator is a powerful tool for gauging market sentiment and can be a valuable addition to any BTC trader's toolkit. However, it should be used in conjunction with other technical analysis tools and not as a standalone signal for making trading decisions.
Ichimoku Multi-BG System by Pranojit Dey (Exact Alignment)It shows trend of different levels with the help of Ichimoku, VWAP, SMA and Pivot. Use it as a strong confluence for any entry. Lets trade guys...
Thick Wick OverlayI have a hard time seeing the wick and made a simple overlay indicator to create a "thicker wick". You can change the thickness and wick color to your desired color and thickness.
Chart This in GoldProduces a historical line chart in the bottom pane to reflect how many units of spot gold (XAU) could be exchanged for one unite of the underlying asset.
Gemini Trend & Momentum Synergy (With Sound Alerts)** هذا المؤشر لا يعمل ك محلل تداول بديل لكنه يستخدم لمعرفة الاتجاه العام و مناطق الدخول والخروج لطفا ..
خطوة مهمة جداً: كيف تفعل الصوت؟ 🔊
الكود وحده لا يصدر صوتاً، هو فقط يرسل "إشارة" للمنصة. لكي تسمع الصوت، عليك اتباع الخطوات التالية في TradingView بعد حفظ الكود:
1. اضغط على أيقونة "الساعة" (Alerts) في القائمة الجانبية اليمنى، أو اضغط Alt + A.
2. اضغط على زر Create Alert.
3. في خانة Condition، اختر اسم المؤشر: Gemini Trend & Momentum....
سيكون لديك خياران الآن:
الخيار السهل: اختر "Any alert() function call". هذا سيفعل التنبيه تلقائياً لأي إشارة شراء أو بيع يطلقها الكود.
الخيار المخصص: اختر Gemini Buy Alert أو Gemini Sell Alert إذا كنت تريد تنبيهاً لاتجاه واحد فقط.
الأهم: اذهب لتبويب Notifications وتأكد من وضع علامة صح (✅) على Play Sound.
اضغط Create.
Here is the translation of the text, organized exactly as requested:
**Please Note: This indicator does not serve as a replacement for a trading analyst; rather, it is used to identify the general trend as well as potential entry and exit zones.**
**Very Important Step: How to Enable Sound Alerts? 🔊**
The code alone does not generate sound; it merely sends a "signal" to the platform. To hear audio alerts, you must follow these steps in TradingView after saving the code:
1. Click the **"Clock" icon (Alerts)** in the right-hand sidebar, or press `Alt + A`.
2. Click the **Create Alert** button.
3. In the **Condition** field, select the indicator name: `Gemini Trend & Momentum...`.
4. You will now have two options:
* **The Easy Option:** Select **"Any alert() function call"**. This automatically activates the alert for any Buy or Sell signal triggered by the code.
* **The Custom Option:** Select `Gemini Buy Alert` or `Gemini Sell Alert` if you only want alerts for a specific direction.
5. **Most Importantly:** Go to the **Notifications** tab and ensure the **Play Sound** box is checked (✅).
6. Click **Create**.
---
**Would you like me to translate the installation instructions or the strategy logic as well?**
SMC and FVGHLThis indicator shows FVG and fib level also shows previous day high low , weekly high low, and monthly high low.. apply this indicator on chart and make trading easy...
Non-Repainting Support/Resistance TrendlinesFeatures of This Version
Support lines: upward only, start at lowest low → next higher low
Resistance lines: downward only, start at highest high → next lower high
Lines do not cross price action (validated by every bar along the line)
Non-repainting, confirmed pivots only
Maximum number of trendlines is adjustable
The Fantastic 4 - Momentum Rotation StrategyOverview
The Fantastic 4 is a tactical momentum rotation indicator. It rotates capital monthly across four carefully selected assets based on their 75-day Rate of Change (ROC), allocating only to assets with positive momentum and proportionally weighting them by their momentum strength.
This indicator tracks the strategy's historical performance, displays current allocation recommendations, and sends monthly rebalance alerts so you can easily manage your portfolio. Simply set your capital amount and the indicator shows exactly how much to invest in each asset.
Why These Four Assets?
The selection of 20-year Bonds, Gold, Russell 2000, and Emerging Markets is based on their specific volatility and decorrelation characteristics, which allow the strategy to react quickly to market shifts while providing protection during downturns.
Russell 2000 (Small Caps)
Chosen over the S&P 500 because it is more "lively" and active (Nowadays you could use also the Nasdaq). Its trends are steeper and more vertical, making it easier for a momentum indicator to catch clear trends. While the S&P 500 has more inertia, the Russell 2000 develops faster, allowing the strategy to capture gains in shorter periods.
Emerging Markets
Included because they can act like a "rocket," offering explosive growth potential while maintaining high decorrelation from developed equity markets. When emerging markets trend, they trend hard.
20-Year Bonds
Selected because they are the most decorrelated asset from equities. When a stock market crash occurs, capital typically flows into fixed income, and long-term bonds (20-year) notice this influx the most, making their price reaction more significant and easier to trade. This is the strategy's primary "safe haven."
Gold
Along with bonds, gold serves as a defensive asset providing a "shield" for the portfolio when general market conditions deteriorate. It offers additional decorrelation and crisis protection.
How the Strategy Works
The 75-Day Momentum Engine
The strategy uses a 75-day momentum lookback (roughly 3.5 months), which is considered very "agile" compared to other models like Global Equity Momentum (GEM) that use 200-day periods. This shorter window allows the strategy to:
React quickly to changes in trend
Catch upward movements in volatile assets early
Exit quickly when trends break
Monthly Rebalancing Process
At the end of each month:
Step 1: Calculate 75-day ROC for each asset
Step 2: Filter out assets with negative momentum (they receive 0% allocation)
Step 3: Distribute capital proportionally based on momentum strength
Step 4: Apply 5% minimum threshold (smaller allocations become zero)
Step 5: Apply 80% maximum cap (no single asset exceeds 80%, remainder stays in cash)
The 80% Ceiling Rule
There is an 80% investment ceiling for any single asset to prevent over-exposure. If only one asset (like bonds) has positive momentum, 80% goes to that asset and 20% remains in cash/liquidity.
Behavior in Bearish Markets
When markets turn bearish, the strategy protects capital through several mechanisms:
Automatic Risk-Off
Because the strategy only invests in assets with positive momentum, it automatically moves away from crashing equities. If an asset's trend becomes negative, the strategy stays "on the sidelines" for that asset.
The Bond Haven
During prolonged bearish periods or sudden crashes (like COVID-19), the strategy typically shifts into 20-year bonds. During the COVID-19 crash in March 2020, while global markets were collapsing, strategies like this reportedly yielded positive returns by being positioned in bonds.
Full Liquidity Option
If no assets show positive momentum, the strategy moves to 100% cash. This is rare given the decorrelation between the four assets—when equities crash, bonds and gold typically rise.
What This Indicator Does
This is a tracking and alerting tool that:
Calculates the optimal allocation based on current momentum
Shows historical monthly performance of the strategy
Simulates portfolio equity growth from your specified starting capital
Displays exact dollar amounts to invest in each asset
Sends monthly rebalance alerts with complete instructions
Detects missing data to prevent false signals
Features
Dynamic allocation table showing weights, dollar amounts, and ROC values
Monthly returns history with color-coded performance
Data availability detection with visual status indicators
Configurable alerts for rebalancing, go-to-cash, and missing data
Simulated equity curve from initial capital
Settings Guide
Assets
Configure your four ETFs. The default European ETFs are:
Asset 1 - XETR:IS04: iShares 20+ Year Treasury Bond (Bonds)
Asset 2 - XETR:GZUR: Gold ETC
Asset 3 - XETR:XRS2: Xtrackers Russell 2000 (Small Caps)
Asset 4 - XETR:XMME: Xtrackers Emerging Markets (EM)
For US markets, consider: TLT (20-year bonds), GLD (Gold), IWM (Russell 2000), EEM (Emerging Markets)
Strategy Settings
ROC Period - Momentum lookback in daily bars. Default: 75 days (~3.5 months)
Max Allocation % - Maximum weight for any single asset. Default: 80%
Min Allocation % - Threshold below which allocation becomes zero. Default: 5%
Capital
Initial Capital - Your portfolio value. The indicator calculates exact amounts for each asset based on this. Default: $20,000
Display
Table Positions - Position the allocation and history tables on screen
Months of History - How many past months to display (3-24)
Alerts
Monthly Rebalance Alert - Sends complete allocation details at month end
Go-to-Cash Alert - Alerts when all assets have negative momentum
Missing Data Alert - Warns when asset data is unavailable
How to Use
Initial Setup
Add indicator to any chart and switch to MONTHLY timeframe
Configure your four ETF tickers
Set your portfolio capital amount
Position the tables where you prefer
Setting Up Alerts
Click Alert button or press Alt+A
Set Condition to "Fanta4"
Select "Any alert() function call"
Choose notification method (Email, Push, Webhook, etc.)
Set expiration to "Open-ended"
Monthly Workflow
Receive rebalance alert at the start of each month
Alert shows exact percentages AND dollar amounts for each asset
Adjust your portfolio accordingly
No action needed during the month
Reading the Tables
Green = positive returns/momentum
Red = negative returns/momentum
Orange "N/A" = missing data
Alloc column shows weight distribution (e.g., "45/35/20/—")
Alert Message Example
Monthly alerts include:
Target month for the new allocation
Current portfolio value
Each asset's percentage AND dollar amount
Each asset's momentum (ROC) value
Cash allocation if applicable
Total return since inception
Historical Context
This strategy combines elements of:
Dual Momentum (Gary Antonacci) - Relative and absolute momentum
Global Equity Momentum (GEM) - But with shorter 75-day vs 200-day lookback
Risk parity concepts - Decorrelated asset selection
The key innovation is the specific asset selection optimized for momentum trading and the agile 75-day lookback period that allows faster reactions to trend changes.
Data Requirements
The strategy activates only when all four assets have valid price data (minimum 75 days of history). The data status row shows checkmarks for available data. Note: Some ETFs have limited history (e.g., XMME data starts June 2017).
Limitations
This is a tracking indicator, not an automated trading system
Past performance is hypothetical and does not guarantee future results
Requires all four assets to have valid data; partial allocation not supported
Monthly rebalancing may miss shorter-term momentum shifts
Transaction costs, slippage, and taxes are not included in simulation
ETF availability and liquidity vary by region
The 75-day momentum may whipsaw in choppy, trendless markets
Disclaimer
This indicator is for educational and informational purposes only. It does not constitute financial advice.
Version History
v1.0 - Initial release with momentum rotation, allocation tables, data validation, and monthly alerts






















