Supply In Profit Z-Score | Wave BackgroundSupply in Profit Z-Score
Modified by Quant_Hustler | Original by QuantChook
What it does
The Supply in Profit Z-Score measures how extreme the balance is between BTC addresses in profit versus those in loss compared to historical norms.
It highlights periods of excessive optimism or pessimism, helping traders identify market sentiment extremes that can signal potential turning points or confirm ongoing trends.
This version is designed for longer-term strategies, using smoothing and statistical normalization to focus on broader market sentiment cycles rather than short-term noise.
How it works
--Data Retrieval: Pulls on-chain data showing the percentage of Bitcoin addresses currently in profit and in loss.
--Spread Calculation: Finds the difference between the two to gauge overall sentiment balance.
--Alpha Decay Adjustment (optional): Normalizes extreme values to stabilize the signal over time.
--Smoothing: Applies a moving average to filter daily volatility and improve long-term clarity.
--Z-Score Conversion: Standardizes the data to show how far current sentiment deviates from historical averages.
--Visualization: Plots the result around a neutral midpoint (zero line) — positive values indicate profit dominance, negative values indicate loss dominance.
How to use it
--Above Zero: More addresses in profit → bullish sentiment and strong trend conditions.
--Below Zero: More addresses in loss → bearish sentiment or potential accumulation zones.
--Extreme Values: Mark overly optimistic or capitulated sentiment, often preceding major reversals.
Why use it in trend following
--This indicator serves as an on-chain sentiment confirmation layer for trend-following systems, especially on higher timeframes (daily or weekly).
--In uptrends, sustained positive readings confirm market strength and investor confidence.
--In downtrends, persistent negative readings confirm weakness and help avoid false reversal signals.
--Divergences between price and sentiment (e.g., rising price but weakening sentiment) often signal momentum loss or potential trend transitions.
Modifications from the original by QuantChook
Added EMA, adaptive Z-score smoothing and capping to reduce volatility and noise.
Introduced a wave-style visualization for intuitive sentiment shifts.
Improved calculation structure and upgraded for Pine Script v6 efficiency.
Tuned signal responsiveness and smoothing parameters for long-term trend accuracy.
Simplified user inputs and grouping for easier customization and integration.
In summary:
A refined, statistically grounded on-chain sentiment oscillator — originally developed by QuantChook and enhanced by Quant_Hustler — built to support long-term trend-following strategies by quantifying Bitcoin market sentiment through real-time profit and loss dynamics.
廣量指標
ULTIMATE Smart Trading Pro 🔥
## 🇬🇧 ENGLISH
### 📊 The Most Complete All-in-One Trading Indicator
**ULTIMATE Smart Trading Pro** combines the best technical analysis tools and Smart Money Concepts into a single powerful and intelligent indicator. Designed for serious traders who want a real edge in the markets.
---
### ✨ KEY FEATURES
#### 💰 **SMART MONEY CONCEPTS**
- **Order Blocks**: Automatically detects institutional zones where "smart money" enters positions
- **Break of Structure (BOS)**: Identifies structure breaks to confirm trend changes
- **Liquidity Zones**: Spots equal highs/lows areas where institutions hunt stops
- **Market Structure**: Visually displays bullish (green background) or bearish (red background) structure
#### 📈 **ADVANCED TECHNICAL INDICATORS**
- **RSI with Auto Divergences**: Classic RSI + automatic detection of bullish and bearish divergences
- **MACD with Signals**: Identifies bullish and bearish crossovers in real-time
- **Dynamic Support & Resistance**: Adaptive zones with intelligent scoring based on volume, multiple touches, and ATR
- **Fair Value Gaps (FVG)**: Detects unfilled price gaps (imbalance zones)
#### 📐 **AUTOMATIC TOOLS**
- **Auto Fibonacci**: Automatically calculates Fibonacci retracement levels on the last major trend
- **Pivot Points**: Daily, Weekly, or Monthly pivot points (PP, R1, R2, S1, S2)
- **Pattern Finder**: Automatically detects candlestick patterns (Hammer, Shooting Star, Engulfing, Morning/Evening Star) and chart patterns (Double Top/Bottom)
---
### 🎯 HOW TO USE IT
#### Quick Setup:
1. **Add the indicator** to your chart
2. **Open Settings** and enable/disable modules as needed
3. **Adjust parameters** for your trading style (scalping, swing, day trading)
#### Optimal Trading Setup:
🔥 **ULTRA STRONG Signal** when you have:
- An institutional **Order Block**
- Aligned with a **Support/Resistance** tested 3+ times
- An unfilled **FVG** nearby
- An **RSI divergence** confirming the reversal
- On a key **Fibonacci** level (50%, 61.8%, or 78.6%)
- Favorable market structure (green background for buys, red for sells)
---
### 💡 UNIQUE ADVANTAGES
✅ **Adaptive Intelligence**: Automatically adjusts to market volatility (ATR)
✅ **Volume Filters**: Validates important levels with volume confirmation
✅ **Multi-Timeframe Ready**: Works on all timeframes (1m to 1M)
✅ **Complete Alerts**: Notifications for all important signals
✅ **Clear Interface**: Emojis and colored labels for quick identification
✅ **Intelligent Scoring**: Levels ranked by importance (🔴🔴🔴 = very strong)
✅ **100% Customizable**: Enable only what you need
---
### 🎨 SYMBOL LEGEND
**Smart Money:**
- 🟢 OB = Bullish Order Block
- 🔴 OB = Bearish Order Block
- BOS ↑/↓ = Break of Structure
- 💧 LIQ = Liquidity Zone
**Candlestick Patterns:**
- 🔨 = Hammer (bullish signal)
- ⭐ = Shooting Star (bearish signal)
- 📈 = Bullish Engulfing
- 📉 = Bearish Engulfing
- 🌅 = Morning Star (bullish reversal)
- 🌆 = Evening Star (bearish reversal)
**Indicators:**
- 🚀 MACD ↑ = Bullish crossover
- 📉 MACD ↓ = Bearish crossover
- ⚠️ DIV = Bearish RSI divergence
- ✅ DIV = Bullish RSI divergence
**Support & Resistance:**
- 🟢/🔴 S1, R1 = Support/Resistance
- 🟢🟢🟢/🔴🔴🔴 = VERY strong level (3+ touches)
- (×N) = Number of times touched
---
### ⚙️ RECOMMENDED SETTINGS
**For Scalping (1m - 5m):**
- SR Lookback: 15
- Structure Strength: 3
- RSI: 14
- Volume Filter: ON
**For Day Trading (15m - 1H):**
- SR Lookback: 20
- Structure Strength: 5
- RSI: 14
- All filters: ON
**For Swing Trading (4H - Daily):**
- SR Lookback: 30
- Structure Strength: 7
- Pattern Lookback: 100
- Fibonacci: ON
---
### 🚨 DISCLAIMER
This indicator is a decision support tool. It does not guarantee profits and does not constitute financial advice. Always test on a demo account before real use. Trading involves significant risks.
---
## 📞 SUPPORT & UPDATES
For questions, suggestions, or bug reports, please comment below or contact the author.
**Version:** 1.0
**Last Updated:** October 2025
**Compatible:** TradingView Pine Script v6
---
### 🌟 If you find this indicator useful, please give it a 👍 and share it with other traders!
**Happy Trading! 🚀📈**
Breakout buy and sell//@version=6
indicator("突破 + 反轉指標(嚴格版)", overlay=true)
// 均線計算
ma5 = ta.sma(close, 5)
ma20 = ta.sma(close, 20)
ma_cross_up = ta.crossover(ma5, ma20)
ma_cross_down = ta.crossunder(ma5, ma20)
// 成交量判斷(嚴格:放量 1.5 倍以上)
vol = volume
vol_avg = ta.sma(vol, 20)
vol_increase = vol > vol_avg * 1.5
// 價格突破(嚴格:創 20 根新高/新低)
price_breakout_up = close > ta.highest(close, 20)
price_breakout_down = close < ta.lowest(close, 20)
// KDJ 隨機指標(抓反轉)
k = ta.stoch(close, high, low, 14)
d = ta.sma(k, 3)
kd_cross_up = ta.crossover(k, d)
kd_cross_down = ta.crossunder(k, d)
// 時間過濾(美股正規交易時段)
isRegularSession = (hour >= 14 and hour < 21) or (hour == 21 and minute == 0)
// 冷卻時間(避免連續訊號)
var int lastEntryBar = na
var int lastExitBar = na
entryCooldown = na(lastEntryBar) or (bar_index - lastEntryBar > 5)
exitCooldown = na(lastExitBar) or (bar_index - lastExitBar > 5)
// 嚴格進場條件
entryBreakout = ma_cross_up and vol_increase and price_breakout_up
entryReversal = kd_cross_up
entrySignal = (entryBreakout or entryReversal) and isRegularSession and entryCooldown
// 嚴格出場條件
exitBreakdown = ma_cross_down and vol_increase and price_breakout_down
exitReversal = kd_cross_down
exitSignal = (exitBreakdown or exitReversal) and isRegularSession and exitCooldown
// 更新冷卻時間
if entrySignal
lastEntryBar := bar_index
if exitSignal
lastExitBar := bar_index
// 顯示訊號
plotshape(entrySignal, location=location.belowbar, color=color.green, style=shape.labelup, title="進場訊號", text="買入")
plotshape(exitSignal, location=location.abovebar, color=color.red, style=shape.labeldown, title="出場訊號", text="賣出")
// 均線顯示
plot(ma5, color=color.orange, title="5MA")
plot(ma20, color=color.blue, title="20MA")
// 提醒條件(alertcondition)
alertcondition(entrySignal, title="買入訊號", message="出現買入訊號")
alertcondition(exitSignal, title="賣出訊號", message="出現賣出訊號")
10 分钟 / 20 分钟均线The yellow line (10-minute moving average) crosses above the purple line (20-minute moving average), forming a golden cross.
WHANG EMA-MACD🔥 Smart EMA14 x EMA70 + MACD Trend Alert System
Description:
Tired of chasing false signals?
This simple but powerful indicator helps you catch real trend moves — not the noise.
When EMA14 crosses EMA70 with MACD confirmation, and both EMAs point the same way, you’ll get a clean Buy or Sell alert right on your chart.
No messy settings, no guessing — just clear signals in strong trends.
✨ Features:
🔔 Real-time alerts via “Any alert() function call”
🟢 Buy when EMA14 crosses above EMA70 + MACD > 0
🔴 Sell when EMA14 crosses below EMA70 + MACD < 0
📈 Trades only when both EMAs slope in the same direction
⚙️ Customizable inputs for any market or timeframe
How to use:
Add the indicator to your chart
Create an alert → choose Any alert() function call
Relax and wait for your signals — no need to watch every candle!
Perfect for traders who want to follow the trend, avoid sideways traps, and get early alerts when momentum kicks in 🚀
Correlazione Inversa - Segnali Chiaritrova correlazioni tra asset forex con possibile ritorno alla media
Niveles Históricos + EMA 200 (zoom fijo) by flavexIndicador estrategia minimos y maximos diarios de 4 h. muestra ema 200 suavizada.
Daily High/Low/Mid (Prev Day Extended Split + VWAP BG) it will tell you market bias with the help of vwap and previous day middle line
Daily High/Low/Mid (Prev Day Mid-vs-Next-Mid BG)it gives background depending upon previous day and next day midline.
10/21 EMA + 50/200 Daily SMAAll four relevant moving averages in one script to allow you to add move indicators.
Daily ATR% Dashboard george_pirlog//@version=6
indicator("ATR(14) – Daily + % vs Daily Close & Current (Heat + Alerts)", overlay=true)
// ── Inputs
atrLen = input.int(14, "ATR Length")
tfATR = input.timeframe("D", "ATR Timeframe (for ATR & daily close)")
decATR = input.int(2, "Decimals (ATR)", minval=0, maxval=6)
decPct = input.int(2, "Decimals (%)", minval=0, maxval=6)
pos = input.string("Top Right", "Table Position", options= )
bgAlpha = input.int(75, "Table BG Transparency (0-100)", minval=0, maxval=100)
showLabel = input.bool(false, "Show floating label")
yOffsetATR = input.float(0.25, "Label Y offset (× ATR)", step=0.05)
// Praguri culoare / alerte
warnPct = input.float(2.0, "Warn Threshold % (yellow/orange)", step=0.1)
highPct = input.float(3.0, "High Threshold % (red)", step=0.1)
// ── Helpers
f_pos(p) =>
if p == "Top Left"
position.top_left
else if p == "Top Right"
position.top_right
else if p == "Bottom Left"
position.bottom_left
else
position.bottom_right
f_heatColor(pct) =>
if pct >= highPct
color.new(color.red, 0)
else if pct >= warnPct
color.new(color.orange, 0)
else
color.new(color.teal, 0)
// ── Serii daily
atrDaily = request.security(syminfo.tickerid, tfATR, ta.atr(atrLen))
closeD = request.security(syminfo.tickerid, tfATR, close)
// ── Ultima valoare & procente
atrLast = atrDaily
pctOfDailyClose = atrLast / closeD * 100
pctOfCurrent = atrLast / close * 100
// ── Tabel static (3×2)
var table box = table.new(f_pos(pos), 3, 2, border_width=1, frame_color=color.new(color.gray, 0), bgcolor=color.new(color.black, bgAlpha))
if barstate.islast
table.cell(box, 0, 0, "ATR14 (Last D)", text_color=color.white, text_size=size.small, bgcolor=color.new(color.black, bgAlpha))
table.cell(box, 1, 0, "% of Daily Close", text_color=color.white, text_size=size.small, bgcolor=color.new(color.black, bgAlpha))
table.cell(box, 2, 0, "% of Current", text_color=color.white, text_size=size.small, bgcolor=color.new(color.black, bgAlpha))
table.cell(box, 0, 1, str.tostring(atrLast, "0." + str.repeat("0", decATR)), text_color=color.white, bgcolor=color.new(color.black, bgAlpha))
table.cell(box, 1, 1, str.tostring(pctOfDailyClose, "0." + str.repeat("0", decPct)) + "%", text_color=f_heatColor(pctOfDailyClose), bgcolor=color.new(color.black, bgAlpha))
table.cell(box, 2, 1, str.tostring(pctOfCurrent, "0." + str.repeat("0", decPct)) + "%", text_color=f_heatColor(pctOfCurrent), bgcolor=color.new(color.black, bgAlpha))
// ── Etichetă opțională (apel pe o singură linie)
var label info = na
if showLabel and barstate.islast
label.delete(info)
txt = "ATR14 (Last D): " + str.tostring(atrLast, "0." + str.repeat("0", decATR)) +
" vs Daily Close: " + str.tostring(pctOfDailyClose, "0." + str.repeat("0", decPct)) + "%" +
" vs Current: " + str.tostring(pctOfCurrent, "0." + str.repeat("0", decPct)) + "%"
info := label.new(x=bar_index, y=close + atrLast * yOffsetATR, text=txt, xloc=xloc.bar_index, yloc=yloc.price, style=label.style_label_left, textcolor=color.white, color=color.new(color.black, 0), size=size.normal)
// ── Alerts (cross peste praguri)
dailyWarnUp = ta.crossover(pctOfDailyClose, warnPct)
dailyHighUp = ta.crossover(pctOfDailyClose, highPct)
currWarnUp = ta.crossover(pctOfCurrent, warnPct)
currHighUp = ta.crossover(pctOfCurrent, highPct)
alertcondition(dailyWarnUp, "Daily % crossed WARN", "ATR% vs Daily Close crossed above WARN threshold")
alertcondition(dailyHighUp, "Daily % crossed HIGH", "ATR% vs Daily Close crossed above HIGH threshold")
alertcondition(currWarnUp, "Current % crossed WARN", "ATR% vs Current Price crossed above WARN threshold")
alertcondition(currHighUp, "Current % crossed HIGH", "ATR% vs Current Price crossed above HIGH threshold")
StochRSI + MACD with Fixed TP ExitAutor WickDipper
Liquidity Finder: The liquidity zones are heuristic and based on volume and swing points. You may need to tweak the volumeThreshold and lookback to match the asset's volatility and timeframe.
Timeframe: This script works on any timeframe, but signals may vary in reliability (e.g., higher timeframes like 4H or 1D may reduce noise).
Customization: You can modify signal conditions (e.g., require only RSI or MACD) or add filters like trend direction using moving averages.
Backtesting: Use TradingView's strategy tester to evaluate performance by converting the indicator to a strategy (replace plotshape with strategy.entry/strategy.close).
Euro Area vs US10YThe Euro Area GDP-Weighted Yield vs US10Y Spread is a macroeconomic indicator designed for forex traders and institutional investors who want to monitor the fundamental interest rate differential between the Eurozone and the United States. This tool aggregates sovereign bond yields from the major Eurozone member states using a weighted methodology based on outstanding government debt, providing a comprehensive view of the Euro Area’s fixed income market dynamics.
This indicator calculates a composite 10-year government bond yield for the Eurozone by combining data from seven major member countries: Germany, France, Italy, Spain, Netherlands, Belgium, and Austria. The weights are based on the proportion of government debt outstanding in each country, reflecting the actual composition of the European sovereign bond market rather than just GDP size.
The indicator then compares this Euro Area weighted yield against the US 10-Year Treasury yield (US10Y), producing a yield spread that serves as a powerful leading indicator for EUR/USD price movements.
9:30 USA OPENEasy if it go up it will turn green and you can lng if it goes down it will turn red and you can short
MACD / AO Alineación (V21) PublicA long or short indicator for any timeframe. It's important to consider volatility and ADX to find the most appropriate momentum. There are also other details to consider.
Volume Aggregated Spot & Futures -- Crypto (by plyst & more)📊 Volume Aggregated Spot & Futures - Enhanced Edition
🎯 Overview
Advanced volume aggregation indicator that combines spot and perpetual futures volume across the top 10 cryptocurrency exchanges. This enhanced version builds upon the original work by @HALDRO Project with optimized calculations and expanded functionality.
✨ Key Features
- 📈 Real-time aggregated volume from 10 major exchanges (Binance, Bybit, OKX, Coinbase, Bitget, KuCoin, Kraken, MEXC, Gate.io, HTX)
- 🔄 Multiple visualization modes: Volume, Delta, Cumulative Delta, Spot vs Perp analysis, Liquidations, OBV, and MFI
- 💱 Multi-currency support: Display volume in COIN, USD, or EUR
- 🎨 Clean, single-color bar chart showing total cumulative volume
- 📊 Multiple calculation methods: SUM, AVG, MEDIAN, VARIANCE
- 🎯 Separate spot (USDT, USD, USDC, etc.) and perpetual futures (.P contracts) tracking
🔧 Technical Improvements
✓ Corrected MFI formula for accurate money flow calculations
✓ Optimized volume aggregation logic with proper NA handling
✓ Support for 10 exchanges (up from 9)
✓ Streamlined codebase for better performance
✓ Updated perpetual contract naming conventions (.P format)
📖 Usage
Perfect for analyzing total market volume, identifying liquidation events, tracking buyer/seller pressure through delta analysis, and understanding the spot vs futures market dynamics.
🙏 Credits
Original concept and framework by @HALDRO Project. This version includes mathematical corrections, code optimizations, and expanded exchange support.
⚠️ Note
Aggregated volume is calculated from external exchange data using request.security(). Ensure your plan supports the necessary security calls for optimal performance.
Candle Pattern Detector SMC with Alerts @AshokTrendJust Follow Hammer, Inverted Hammer, Hanging Man, Engulfing, volume adn smc consideration,
Trading the candlestick patterns (Hammer, Inverted Hammer, Hanging Man, Bullish/Bearish Engulfing) with volume confirmation adds an important layer of validation, helping to filter false signals and improve trade success. Here’s how to integrate volume into your strategy:
***
### How to Trade Candlestick Patterns with Volume Confirmation
#### 1. Understand Volume Role
- Volume shows the strength behind price moves:
- Higher volume on a pattern (compared to recent average) indicates strong participation, increasing the pattern’s reliability.
- Low volume may mean weak conviction and higher risk of failure.
#### 2. Volume Confirmation Rules
- Define a volume threshold, for example:
- Current candle’s volume > average volume of last 10 or 20 candles (or a fixed multiplier, e.g., 1.2× average).
- For bullish patterns (Hammer, Inverted Hammer, Bullish Engulfing): confirm with rising volume on pattern candle or next candle.
- For bearish patterns (Hanging Man, Bearish Engulfing): confirm with higher volume on pattern candle indicating strong selling.
#### 3. Entry Signals with Volume
- **Bullish Entry:**
- Signal candle (Hammer, Bullish Engulfing, etc.) appears near support or order block.
- Volume on the signal candle or immediate next candle is higher than average.
- Enter long on confirmation candle or close of signal candle.
- **Bearish Entry:**
- Signal candle (Hanging Man, Bearish Engulfing, etc.) appears near resistance or supply zone.
- Volume on the signal candle or immediate next candle exceeds average.
- Enter short on confirmation candle or close of signal candle.
#### 4. Stop Loss & Targets
- Place stop loss just below (for longs) or above (for shorts) the low/high wick of the signal candle or the order block zone.
- Set take profit based on nearby support/resistance, risk-reward ratio, or a fixed number of candle closes.
#### 5. Avoid Trading Without Volume Confirmation
- Reject candles if volume is below threshold to reduce false signals.
### Summary
Trading candlestick patterns combined with volume confirmation ensures only well-supported setups are taken, improving win rates and reducing noisy or fake signals. Volume adds a critical dimension to the SMC candle patterns for binary or any form of trading.
Would you like me to generate a full Pine Script that integrates volume confirmation with the patterns you requested?
my_strategy_2.0Overview:
This is a high-speed scalping strategy optimized for volatile crypto assets (BTC, ETH, etc.) on timeframes 1m–5m. It combines trend-following SuperTrend with confirmations from MACD, RSI, Bollinger Bands, and volume spikes for precise entries. Focus on quick profits (1–3 ATR) with strict risk control: partial take-profits, stop-loss, and trailing breakeven after the first TP.
Key Signals:
Long: SuperTrend flip up + MACD crossover up + RSI >50 + BB Upper breakout + volume spike + volatility filter (ATR >0.5%).
Short: Similar but downward.
Exits and Risks:
TP: 33% at +1 ATR, 33% at +2 ATR, 34% at +3 ATR (customizable).
SL: Initial at -1 ATR, after TP1 — to breakeven with trailing on BB midline (optional).
Filters: Minimum ATR to avoid flat markets; realistic commissions in backtests.
Recommendations:
Test on 2020–2025 data (out-of-sample 2024+). Expected Win Rate ~55%, Profit Factor >1.8, Drawdown <10%. Ideal for 1–2% risk per trade. Not for beginners — use paper trading.
Disclaimer: Past results do not guarantee future performance. Trade at your own risk.
(Pine v6 code, ready for publication. Author: gopog777 with expert fixes.)
Advanced Market Trend Analyzer//@version=5
indicator("Advanced Market Trend Analyzer", shorttitle="AMT Analyzer", overlay=true)
// Input parameters
rsi_length = input.int(14, "RSI Length")
ema_fast = input.int(9, "Fast EMA")
ema_slow = input.int(21, "Slow EMA")
volume_ma_length = input.int(20, "Volume MA Length")
overbought = input.int(70, "Overbought Level")
oversold = input.int(30, "Oversold Level")
BIF ASK WITH TREND Price Trend with PercentageBID ASK WITH TREND Price Trend with Percentage SHOW MARKET TREND AND MARKET VOLLUME
SM OTC style Supply/Demand Zones Lite+//@version=6
indicator("OTC SD MTF Lite+", "OTCSDmtf+", overlay=true, max_boxes_count=200, max_labels_count=200)
// ================= Inputs =================
useH4 = input.bool(true, "Show 4H zones")
useD1 = input.bool(true, "Show 1D zones")
useW1 = input.bool(true, "Show 1W zones")
useM1 = input.bool(false, "Show 1M zones")
baseLen = input.int(2, "Base length (HTF bars)", 1, 5)
wickPctMax = input.float(35.0, "Max wick % in base", 0, 100)
impulseX = input.float(1.5, "Departure body vs ATR (x)", 0.5, 5.0)
atrLen = input.int(14, "ATR length (HTF)")
extendBars = input.int(2000, "Extend bars on chart", 200, 10000)
maxPerTF = input.int(12, "Max zones per TF", 3, 30)
showLegend = input.bool(true, "Show tiny legend (4H/1D/1W/1M)")
onlyNearest = input.bool(false, "Show ONLY nearest zone above/below")
hideOverlapTF = input.bool(true, "Hide overlapping zones within each TF (keep newest)")
showNearestLabels = input.bool(false, "Show distance labels to nearest above/below")
// --- Hard cap for future drawing with xloc.bar_index ---
FUTURE_CAP = 500
// Colors (Demand hues per TF). Supply uses red for contrast.
colH4 = color.new(color.teal, 78)
colD1 = color.new(color.blue, 78)
colW1 = color.new(color.orange, 78)
colM1 = color.new(color.purple, 78)
colSup= color.new(color.red, 78)
// ================= Helpers =================
wickiness(h, l, o, c) =>
rng = math.max(h - l, syminfo.mintick)
topW = h - math.max(o, c)
botW = math.min(o, c) - l
100.0 * (topW + botW) / rng
// Returns: (dTrig, dProx, dDist, sTrig, sProx, sDist)
f_htfSignals(baseBars, wickMax, xImpulse, aLen) =>
float _o = open
float _h = high
float _l = low
float _c = close
float _atr = ta.atr(aLen)
bool ok = true
for i = 1 to baseBars
ok := ok and (wickiness(_h , _l , _o , _c ) <= wickMax)
bool bullDepart = _c > _o and (_c - _o) > xImpulse * _atr
bool bearDepart = _c < _o and (_o - _c) > xImpulse * _atr
float dTrig = 0.0
float dProx = na
float dDist = na
float sTrig = 0.0
float sProx = na
float sDist = na
if ok and bullDepart
float hi = ta.highest(_h, baseBars)
float lo = ta.lowest(_l, baseBars)
dTrig := 1.0
dProx := lo
dDist := hi
if ok and bearDepart
float hi2 = ta.highest(_h, baseBars)
float lo2 = ta.lowest(_l, baseBars)
sTrig := 1.0
sProx := hi2
sDist := lo2
// ================= Pull HTF signals =================
= request.security(syminfo.tickerid, "240", f_htfSignals(baseLen, wickPctMax, impulseX, atrLen))
= request.security(syminfo.tickerid, "D", f_htfSignals(baseLen, wickPctMax, impulseX, atrLen))
= request.security(syminfo.tickerid, "W", f_htfSignals(baseLen, wickPctMax, impulseX, atrLen))
= request.security(syminfo.tickerid, "M", f_htfSignals(baseLen, wickPctMax, impulseX, atrLen))
// ================= Storage per TF =================
var zH4 = array.new_box()
var aH4 = array.new_bool()
var lH4 = array.new_label()
var sH4 = array.new_int() // 1 = Demand, -1 = Supply
var zD1 = array.new_box()
var aD1 = array.new_bool()
var lD1 = array.new_label()
var sD1 = array.new_int()
var zW1 = array.new_box()
var aW1 = array.new_bool()
var lW1 = array.new_label()
var sW1 = array.new_int()
var zM1 = array.new_box()
var aM1 = array.new_bool()
var lM1 = array.new_label()
var sM1 = array.new_int()
// ================= Overlap utils =================
overlap(topA, botA, topB, botB) =>
not (topA < botB or botA > topB)
purgeOverlaps(arrB, arrA, arrL, newTop, newBot) =>
if hideOverlapTF and array.size(arrB) > 0
for i = 0 to array.size(arrB) - 1
if array.get(arrA, i)
box bOld = array.get(arrB, i)
float t = box.get_top(bOld)
float btm = box.get_bottom(bOld)
if overlap(newTop, newBot, t, btm)
box.delete(bOld)
label.delete(array.get(arrL, i))
array.set(arrA, i, false)
// ================= Add zone =================
addZone(arrB, arrA, arrL, arrS, topV, botV, baseColor, isDemand) =>
purgeOverlaps(arrB, arrA, arrL, topV, botV)
int leftX = bar_index - 1
int rightX = bar_index + math.min(extendBars, FUTURE_CAP) // respect +500 cap
box b = box.new(leftX, topV, rightX, botV, xloc=xloc.bar_index, bgcolor=baseColor, border_color=color.new(color.black, 0))
float ly = isDemand == 1 ? topV : botV
st = isDemand == 1 ? label.style_label_down : label.style_label_up
string tagTxt = isDemand == 1 ? "Demand" : "Supply"
label l = label.new(leftX, ly, tagTxt, xloc=xloc.bar_index, style=st, textcolor=color.white, color=color.new(color.black, 0), size=size.tiny)
array.push(arrB, b)
array.push(arrA, true)
array.push(arrL, l)
array.push(arrS, isDemand)
if array.size(arrB) > maxPerTF
box.delete(array.shift(arrB))
array.shift(arrA)
label.delete(array.shift(arrL))
array.shift(arrS)
// ================= Maintain / Invalidate =================
extendAll(arrB, arrA) =>
if array.size(arrB) > 0
for i = 0 to array.size(arrB) - 1
if array.get(arrA, i)
box.set_right(array.get(arrB, i), bar_index + math.min(extendBars, FUTURE_CAP)) // respect +500 cap
invalidate(arrB, arrA, arrL) =>
if array.size(arrB) > 0
for i = 0 to array.size(arrB) - 1
if array.get(arrA, i)
box b = array.get(arrB, i)
float t = box.get_top(b)
float btm = box.get_bottom(b)
// Close outside band → remove
if close > t or close < btm
box.delete(b)
label.delete(array.get(arrL, i))
array.set(arrA, i, false)
// ================= New HTF bar flags (strict booleans) =================
int chH4 = ta.change(time("240"))
int chD1 = ta.change(time("D"))
int chW1 = ta.change(time("W"))
int chM1 = ta.change(time("M"))
bool newBarH4 = useH4 and (not na(chH4)) and (chH4 != 0)
bool newBarD1 = useD1 and (not na(chD1)) and (chD1 != 0)
bool newBarW1 = useW1 and (not na(chW1)) and (chW1 != 0)
bool newBarM1 = useM1 and (not na(chM1)) and (chM1 != 0)
// ================= Create zones on new HTF bar =================
if newBarH4
if d4t > 0 and not na(d4p) and not na(d4d)
addZone(zH4, aH4, lH4, sH4, d4d, d4p, colH4, 1)
if s4t > 0 and not na(s4p) and not na(s4d)
addZone(zH4, aH4, lH4, sH4, s4p, s4d, colSup, -1)
if newBarD1
if d1t > 0 and not na(d1p) and not na(d1d)
addZone(zD1, aD1, lD1, sD1, d1d, d1p, colD1, 1)
if s1t > 0 and not na(s1p) and not na(s1d)
addZone(zD1, aD1, lD1, sD1, s1p, s1d, colSup, -1)
if newBarW1
if w1t > 0 and not na(w1p) and not na(w1d)
addZone(zW1, aW1, lW1, sW1, w1d, w1p, colW1, 1)
if swt > 0 and not na(swp) and not na(swd)
addZone(zW1, aW1, lW1, sW1, swp, swd, colSup, -1)
if newBarM1
if m1t > 0 and not na(m1p) and not na(m1d)
addZone(zM1, aM1, lM1, sM1, m1d, m1p, colM1, 1)
if smt > 0 and not na(smp) and not na(smd)
addZone(zM1, aM1, lM1, sM1, smp, smd, colSup, -1)
// ================= Maintain & Invalidate (every bar) =================
extendAll(zH4, aH4)
extendAll(zD1, aD1)
extendAll(zW1, aW1)
extendAll(zM1, aM1)
invalidate(zH4, aH4, lH4)
invalidate(zD1, aD1, lD1)
invalidate(zW1, aW1, lW1)
invalidate(zM1, aM1, lM1)
// ================= Nearest across all TFs =================
tfNearest(arrB, arrA) =>
int upIdx = -1
int dnIdx = -1
float upDist = 1e10
float dnDist = 1e10
float upBtm = na
float dnTop = na
if array.size(arrB) > 0
for i = 0 to array.size(arrB) - 1
if array.get(arrA, i)
box b = array.get(arrB, i)
float t = box.get_top(b)
float btm = box.get_bottom(b)
if btm >= close
float d = btm - close
if d < upDist
upDist := d
upIdx := i
upBtm := btm
if t <= close
float d2 = close - t
if d2 < dnDist
dnDist := d2
dnIdx := i
dnTop := t
= tfNearest(zH4, aH4)
= tfNearest(zD1, aD1)
= tfNearest(zW1, aW1)
= tfNearest(zM1, aM1)
float upBest = 1e10, dnBest = 1e10
int upArr = -1, upIdxSel = -1, dnArr = -1, dnIdxSel = -1
color upColor = color.new(color.white, 100), dnColor = color.new(color.white, 100)
if (not na(uh4y)) and uh4d < upBest
upBest := uh4d, upArr := 0, upIdxSel := uh4i, upColor := colH4
if (not na(ud1y)) and ud1d < upBest
upBest := ud1d, upArr := 1, upIdxSel := ud1i, upColor := colD1
if (not na(uw1y)) and uw1d < upBest
upBest := uw1d, upArr := 2, upIdxSel := uw1i, upColor := colW1
if (not na(um1y)) and um1d < upBest
upBest := um1d, upArr := 3, upIdxSel := um1i, upColor := colM1
if (not na(dh4y)) and dh4d < dnBest
dnBest := dh4d, dnArr := 0, dnIdxSel := dh4i, dnColor := colH4
if (not na(dd1y)) and dd1d < dnBest
dnBest := dd1d, dnArr := 1, dnIdxSel := dd1i, dnColor := colD1
if (not na(dw1y)) and dw1d < dnBest
dnBest := dw1d, dnArr := 2, dnIdxSel := dw1i, dnColor := colW1
if (not na(dm1y)) and dm1d < dnBest
dnBest := dm1d, dnArr := 3, dnIdxSel := dm1i, dnColor := colM1
// ================= Nearest-only visibility (optional) =================
hideAll(arrB, arrA) =>
if array.size(arrB) > 0
for i = 0 to array.size(arrB) - 1
if array.get(arrA, i)
box.set_bgcolor(array.get(arrB, i), color.new(color.white, 100))
box.set_border_color(array.get(arrB, i), color.new(color.white, 100))
showOne(arrB, arrA, arrS, idx, demColor) =>
if idx >= 0 and idx < array.size(arrB)
if array.get(arrA, idx)
bool isDemand = array.get(arrS, idx) == 1
color c = isDemand ? demColor : colSup
box.set_bgcolor(array.get(arrB, idx), c)
box.set_border_color(array.get(arrB, idx), color.new(color.black, 0))
if onlyNearest
hideAll(zH4, aH4), hideAll(zD1, aD1), hideAll(zW1, aW1), hideAll(zM1, aM1)
if upArr == 0
showOne(zH4, aH4, sH4, upIdxSel, upColor)
if upArr == 1
showOne(zD1, aD1, sD1, upIdxSel, upColor)
if upArr == 2
showOne(zW1, aW1, sW1, upIdxSel, upColor)
if upArr == 3
showOne(zM1, aM1, sM1, upIdxSel, upColor)
if dnArr == 0
showOne(zH4, aH4, sH4, dnIdxSel, dnColor)
if dnArr == 1
showOne(zD1, aD1, sD1, dnIdxSel, dnColor)
if dnArr == 2
showOne(zW1, aW1, sW1, dnIdxSel, dnColor)
if dnArr == 3
showOne(zM1, aM1, sM1, dnIdxSel, dnColor)
// ================= Nearest distance labels (optional) =================
var label nearUp = na
var label nearDn = na
makeNearLabel(y, txt) =>
label.new(bar_index, y, txt, xloc=xloc.bar_index, style=label.style_label_left, color=color.new(color.black, 0), textcolor=color.white, size=size.tiny)
if showNearestLabels
if not na(nearUp)
label.delete(nearUp)
if not na(nearDn)
label.delete(nearDn)
if upArr != -1
box bUp = upArr == 0 ? array.get(zH4, upIdxSel) : upArr == 1 ? array.get(zD1, upIdxSel) : upArr == 2 ? array.get(zW1, upIdxSel) : array.get(zM1, upIdxSel)
float upBtm = box.get_bottom(bUp)
float pctUp = math.round(10000.0 * (upBtm - close) / close) / 100.0
nearUp := makeNearLabel(upBtm, "Nearest Above ~ " + str.tostring(pctUp) + "%")
if dnArr != -1
box bDn = dnArr == 0 ? array.get(zH4, dnIdxSel) : dnArr == 1 ? array.get(zD1, dnIdxSel) : dnArr == 2 ? array.get(zW1, dnIdxSel) : array.get(zM1, dnIdxSel)
float dnTop = box.get_top(bDn)
float pctDn = math.round(10000.0 * (close - dnTop) / close) / 100.0
nearDn := makeNearLabel(dnTop, "Nearest Below ~ " + str.tostring(pctDn) + "%")
// ================= Tiny legend (dots) =================
var table legend = na
if showLegend and na(legend)
legend := table.new(position.top_left, 4, 1)
if showLegend and not na(legend)
table.cell(legend, 0, 0, "● 4H", text_color=color.white, bgcolor=color.new(color.black, 0))
table.cell(legend, 1, 0, "● 1D", text_color=color.white, bgcolor=color.new(color.black, 0))
table.cell(legend, 2, 0, "● 1W", text_color=color.white, bgcolor=color.new(color.black, 0))
table.cell(legend, 3, 0, "● 1M", text_color=color.white, bgcolor=color.new(color.black, 0))
table.cell_set_bgcolor(legend, 0, 0, color.new(color.teal, 70))
table.cell_set_bgcolor(legend, 1, 0, color.new(color.blue, 70))
table.cell_set_bgcolor(legend, 2, 0, color.new(color.orange, 70))
table.cell_set_bgcolor(legend, 3, 0, color.new(color.purple, 70))