MACD (The Moving Average Convergence Divergence)The Moving Average Convergence Divergence (MACD) is a momentum indicator used in technical analysis to identify trends, measure their strength, and signal potential reversals. It is calculated by subtracting the 26-period Exponential Moving Average (EMA) from the 12-period EMA, creating the MACD line. A 9-period EMA of the MACD line, known as the signal line, is then plotted to generate buy or sell signals. Positive MACD values suggest upward momentum, while negative values indicate downward momentum. Traders often watch for crossovers, divergences, and movements relative to the zero line to make informed decisions.
Göstergeler ve stratejiler
Ch Enhanced Buy Sell Volume// ========================================
// 📊 HOW TO READ THIS INDICATOR 📊
// ========================================
//
// 🟢 GREEN BARS (Above Zero) = BUY VOLUME
// 🔴 RED BARS (Below Zero) = SELL VOLUME
//
// 💡 BAR COLORS MEANING:
// • DARK GREEN = Strong buyer dominance (high conviction buying)
// • LIGHT GREEN = Weak buyer dominance (low conviction)
// • DARK RED = Strong seller dominance (high conviction selling)
// • LIGHT RED = Weak seller dominance (low conviction)
//
// 🎯 TRADING SIGNALS:
// • Tall dark green bars = Strong bullish momentum
// • Tall dark red bars = Strong bearish momentum
// • Light colored bars = Weak conviction, potential reversal
// • Green bars > Red bars = Buyers winning
// • Red bars > Green bars = Sellers winning
//
// 📈 BULLISH SIGNALS:
// • Buy% > 70% = Strong buying interest
// • Dark green bars with high delta = Professional buying
// • Buy volume above yellow MA line = Above average buying
//
// 📉 BEARISH SIGNALS:
// • Sell% > 70% = Strong selling pressure
// • Dark red bars with high delta = Professional selling
// • Sell volume below yellow MA line = Above average selling
//
// ⚠️ WARNING SIGNALS:
// • Price up + Red dominance = Bearish divergence
// • Price down + Green dominance = Bullish divergence
// • Low delta (<10%) = Market indecision
//
// 📊 INFO TABLE (Top-Right):
// • Buy%: Percentage of volume that was buying
// • Sell%: Percentage of volume that was selling
// • Delta%: Strength of dominance (difference between buy/sell)
// • Dom: Which side is currently dominant (BUYERS/SELLERS)
//
// 🟡 YELLOW LINES = Volume Moving Average
// • Upper line: Reference for buy volume (green bars)
// • Lower line: Reference for sell volume (red bars)
// • Above yellow = Higher than average volume
// • Below yellow = Lower than average volume
Session High Low TrackerTracks the Asia, London, NY AM and NY PM swing highs and lows. What's different here is when a level is broken, it can continue to draw a dotted line so the levels stay on the chart until
end of day. Also has shading options for each session.
AMHA + 4 EMAs + EMA50/200 Counter + Avg10CrossesDescription:
This script combines two types of Heikin-Ashi visualization with multiple Exponential Moving Averages (EMAs) and a counting function for EMA50/200 crossovers. The goal is to make trends more visible, measure recurring market cycles, and provide statistical context without generating trading signals.
Logic in Detail:
Adaptive Median Heikin-Ashi (AMHA):
Instead of the classic Heikin-Ashi calculation, this method uses the median of Open, High, Low, and Close. The result smooths out price movements, emphasizes trend direction, and reduces market noise.
Standard Heikin-Ashi Overlay:
Classic HA candles are also drawn in the background for comparison and transparency. Both HA types can be shifted below the chart’s price action using a customizable Offset (Ticks) parameter.
EMA Structure:
Five exponential moving averages (21, 50, 100, 200, 500) are included to highlight different trend horizons. EMA50 and EMA200 are emphasized, as their crossovers are widely monitored as potential trend signals. EMA21 and EMA100 serve as additional structure layers, while EMA500 represents the long-term trend.
EMA50/200 Counter:
The script counts how many bars have passed since the last EMA50/200 crossover. This makes it easy to see the age of the current trend phase. A colored label above the chart displays the current counter.
Average of the Last 10 Crossovers (Avg10Crosses):
The script stores the last 10 completed count phases and calculates their average length. This provides historical context and allows traders to compare the current cycle against typical past behavior.
Benefits for Analysis:
Clearer trend visualization through adaptive Heikin-Ashi calculation.
Multi-EMA setup for quick structural assessment.
Objective measurement of trend phase duration.
Statistical insight from the average cycle length of past EMA50/200 crosses.
Flexible visualization through adjustable offset positioning below the price chart.
Usage:
Add the indicator to your chart.
For a clean look, you may switch your chart type to “Line” or hide standard candlesticks.
Interpret visual signals:
White candles = bullish phases
Orange candles = bearish phases
EMAs = structural trend filters (e.g., EMA200 as a long-term boundary)
The counter label shows the current number of bars since the last cross, while Avg10 represents the historical mean.
Special Feature:
This script is not a trading system. It does not provide buy/sell recommendations. Instead, it serves as a visual and statistical tool for market structure analysis. The unique combination of Adaptive Median Heikin-Ashi, multi-EMA framework, and EMA50/200 crossover statistics makes it especially useful for trend-followers and swing traders who want to add cycle-length analysis to their toolkit.
Moon Phases Prediction🌙 Moon Phases (with Next Event Projection)
Introduction
This indicator plots Moon Phases (New Moon and Full Moon) directly on your chart.
In addition to showing historical phases, it also calculates and projects the upcoming next moon phase using precise astronomical formulas.
Features
Marks New Moons with circles above bars.
Marks Full Moons with circles below bars.
Dynamically adjusts background color based on waxing/waning phase.
Calculates and displays the next upcoming moon event as a label positioned in the future.
Works on all timeframes (except Monthly).
How It Works
Uses astronomical approximations (Julian Day → UNIX time conversion).
Detects the last occurred New Moon or Full Moon.
Projects the next moon event by adding half a synodic month (~14.77 days).
Displays the next event label at its exact future date on the chart.
Customization
Waxing Moon color (default: Blue)
Waning Moon color (default: White)
Use Cases
Astro-finance: lunar cycles and market psychology.
Trading strategies: aligning entries/exits with cyclical behavior.
Visualization: adding an extra dimension of timing to chart analysis.
Notes
- The future moon event is displayed as a circle label on the correct date.
- If you cannot see the label, increase your chart’s right margin (Chart Settings → Scales → Right Margin).
- Calculations are approximate but astronomically accurate enough for trading or visual use.
Conclusion
This indicator is a simple yet powerful tool for traders interested in the influence of lunar cycles.
By combining historical phases with a projected next event, you can always be aware of where the market stands in the moon cycle timeline.
Adaptive Jump Moving AverageAdaptive Jump Moving Average - Description
This indicator solves the classic moving average lag problem during significant price moves. Traditional MAs (like the 200-day) take forever to catch up after a major drop or rally because they average across all historical periods equally.
How it works:
Tracks price smoothly during normal market conditions
When price moves 20%+ away from the MA, it immediately "resets" to the current price level
Treats that new level as the baseline and continues smooth tracking from there
Advantages over normal MA:
No lag on major moves: A 40% crash doesn't get diluted over 200 days - the MA instantly adapts
Reduces false signals: You won't get late "death cross" signals months after a crash already happened
Better support/resistance: The MA stays relevant to current price action instead of reflecting outdated levels
Keeps the smoothness: During normal volatility, it behaves like a traditional MA without the noise of shorter periods
Volume Aggregated (Lite)Volume Aggregated (Lite) is a lightweight yet powerful tool designed to provide traders with a consolidated view of trading volume across major perpetual futures markets. Instead of relying solely on the volume of a single exchange, this indicator aggregates and normalizes data from multiple venues, giving a broader and more representative measure of market activity.
Supported Exchanges:
Binance (USDT.P & USDC.P)
Bybit (USDT.P & USD.P)
OKX (USDT.P & USD.P)
Bitget (USDT.P & USD.P)
Coinbase (USDC.P)
Users can toggle each exchange individually, allowing flexible customization depending on which markets they consider most relevant.
Denomination Options:
COINS: Volume expressed in the base currency (e.g., BTC, ETH).
USD: Volume normalized to USD values by multiplying with price.
Why it’s useful:
Volume is a critical component of technical analysis, reflecting market participation and conviction behind price moves. However, relying on a single exchange can create blind spots, especially in crypto where liquidity is fragmented. By combining data from multiple large exchanges, this indicator offers:
A more comprehensive measure of market interest.
A normalized comparison between exchanges with different quote currencies (e.g., USDT, USD, USDC).
A volume stream that can be used as a custom source for other indicators, strategies, or overlays within TradingView.
Practical Applications:
Trend Confirmation: Check if aggregated volume supports price direction.
Breakout Validation: Identify whether breakouts are backed by broad participation across venues.
Divergence Detection: Spot situations where price moves without sufficient cross-exchange volume.
Custom Indicator Input: Since it outputs a clean series, it can be plugged into moving averages, oscillators, or custom-built scripts.
Technical Details:
The script uses request.security() to pull volume data across exchanges and normalizes values when required (e.g., USD-quoted pairs divided by the instrument’s price). It then aggregates all valid inputs into a single stream. The result is displayed as color-coded columns (green for bullish candles, red for bearish), making it easy to interpret at a glance.
This “Lite” version keeps the focus on core functionality: aggregation, normalization, and straightforward visualization—avoiding unnecessary complexity while remaining highly adaptable for custom analysis.
Double Top/Bottom Screener - Today Only v3 //@version=6
indicator("Double Top/Bottom Screener - Today Only", overlay=true, max_lines_count=500)
// Inputs
leftBars = input.int(5, "Left Bars")
rightBars = input.int(5, "Right Bars")
tolerance = input.float(0.02, "Max Difference (e.g., 0.02 for 2 cents)", step=0.01)
atrLength = input.int(14, "ATR Length for Normalized Distance", minval=1)
requiredPeaks = input.int(3, "Required Identical Peaks", minval=2, maxval=5)
// Declarations of persistent variables and arrays
var array resistanceLevels = array.new(0)
var array resistanceCounts = array.new(0)
var array supportLevels = array.new(0)
var array supportCounts = array.new(0)
var array resLines = array.new(0)
var array supLines = array.new(0)
var bool hasDoubleTop = false
var bool hasDoubleBottom = false
var float doubleTopLevel = na
var float doubleBottomLevel = na
var int todayStart = na
var float nearestDoubleLevel = na // Explicitly declared as na by default
// Step 1: Identify Swing Highs/Lows
swingHigh = ta.pivothigh(high, leftBars, rightBars)
swingLow = ta.pivotlow(low, leftBars, rightBars)
// Today's premarket start (04:00 AM ET)
todayStart := timestamp(syminfo.timezone, year, month, dayofmonth, 4, 0, 0)
// Clear arrays and delete lines on the first bar or new day
if barstate.isfirst or (dayofmonth != dayofmonth and time >= todayStart)
// Delete all existing lines only if arrays are not empty
if array.size(resLines) > 0
for i = array.size(resLines) - 1 to 0
line.delete(array.get(resLines, i))
if array.size(supLines) > 0
for i = array.size(supLines) - 1 to 0
line.delete(array.get(supLines, i))
// Clear arrays
array.clear(resistanceLevels)
array.clear(supportLevels)
array.clear(resistanceCounts)
array.clear(supportCounts)
array.clear(resLines)
array.clear(supLines)
// Reset flags and levels
hasDoubleTop := false
hasDoubleBottom := false
doubleTopLevel := na
doubleBottomLevel := na
nearestDoubleLevel := na // Ensure reset on new day
// Add new swings only if today and after premarket
if not na(swingHigh) and time >= todayStart and dayofmonth == dayofmonth
bool isEqualHigh = false
int peakIndex = -1
float prevLevel = na
if array.size(resistanceLevels) > 0
for i = 0 to array.size(resistanceLevels) - 1
prevLevel := array.get(resistanceLevels, i)
if math.abs(swingHigh - prevLevel) <= tolerance
isEqualHigh := true
peakIndex := i
break
if isEqualHigh and peakIndex >= 0
array.set(resistanceCounts, peakIndex, array.get(resistanceCounts, peakIndex) + 1)
if array.get(resistanceCounts, peakIndex) == requiredPeaks
hasDoubleTop := true
doubleTopLevel := prevLevel
else
array.push(resistanceLevels, swingHigh)
array.push(resistanceCounts, 1)
line newResLine = line.new(bar_index - rightBars, swingHigh, bar_index, swingHigh, color=color.red, width=2, extend=extend.none)
array.push(resLines, newResLine)
if not na(swingLow) and time >= todayStart and dayofmonth == dayofmonth
bool isEqualLow = false
int peakIndex = -1
float prevLevel = na
if array.size(supportLevels) > 0
for i = 0 to array.size(supportLevels) - 1
prevLevel := array.get(supportLevels, i)
if math.abs(swingLow - prevLevel) <= tolerance
isEqualLow := true
peakIndex := i
break
if isEqualLow and peakIndex >= 0
array.set(supportCounts, peakIndex, array.get(supportCounts, peakIndex) + 1)
if array.get(supportCounts, peakIndex) == requiredPeaks
hasDoubleBottom := true
doubleBottomLevel := prevLevel
else
array.push(supportLevels, swingLow)
array.push(supportCounts, 1)
line newSupLine = line.new(bar_index - rightBars, swingLow, bar_index, swingLow, color=color.green, width=2, extend=extend.none)
array.push(supLines, newSupLine)
// Monitor and remove broken levels/lines; reset pattern if the equal level breaks
if array.size(resistanceLevels) > 0
for i = array.size(resistanceLevels) - 1 to 0
float level = array.get(resistanceLevels, i)
if close > level
line.delete(array.get(resLines, i))
array.remove(resLines, i)
array.remove(resistanceLevels, i)
array.remove(resistanceCounts, i)
if level == doubleTopLevel
hasDoubleTop := false
doubleTopLevel := na
nearestDoubleLevel := na // Reset if level breaks
if array.size(supportLevels) > 0
for i = array.size(supportLevels) - 1 to 0
float level = array.get(supportLevels, i)
if close < level
line.delete(array.get(supLines, i))
array.remove(supLines, i)
array.remove(supportLevels, i)
array.remove(supportCounts, i)
if level == doubleBottomLevel
hasDoubleBottom := false
doubleBottomLevel := na
nearestDoubleLevel := na // Reset if level breaks
// Limit arrays (after removals)
if array.size(resistanceLevels) > 10
line oldLine = array.shift(resLines)
line.delete(oldLine)
array.shift(resistanceLevels)
array.shift(resistanceCounts)
if array.size(supportLevels) > 10
line oldLine = array.shift(supLines)
line.delete(oldLine)
array.shift(supportLevels)
array.shift(supportCounts)
// Pattern Signal: 1 only if the exact required number of peaks is met
patternSignal = (hasDoubleTop or hasDoubleBottom) ? 1 : 0
// New: Nearest Double Level Price - Only update if pattern is active today
if time >= todayStart and dayofmonth == dayofmonth // Restrict to today
if (hasDoubleTop and not na(doubleTopLevel)) or (hasDoubleBottom and not na(doubleBottomLevel))
if hasDoubleTop and not na(doubleTopLevel)
nearestDoubleLevel := doubleTopLevel
if hasDoubleBottom and not na(doubleBottomLevel)
nearestDoubleLevel := na(nearestDoubleLevel) ? doubleBottomLevel : (math.abs(close - doubleBottomLevel) < math.abs(close - nearestDoubleLevel) ? doubleBottomLevel : nearestDoubleLevel)
else
nearestDoubleLevel := na // Reset to na if no pattern today
else
nearestDoubleLevel := na // Reset for historical bars
// New: Distance to Nearest Level (using ATR for normalization)
var float atr = ta.atr(atrLength)
var float distanceNormalizedATR = na
if not na(nearestDoubleLevel) and not na(atr) and atr > 0
distanceNormalizedATR := math.abs(close - nearestDoubleLevel) / atr
// Outputs
plot(patternSignal, title="Pattern Signal", color=patternSignal == 1 ? color.purple : na, style=plot.style_circles)
plot(nearestDoubleLevel, title="Nearest Double Level Price", color=color.orange)
plot(distanceNormalizedATR, title="Normalized Distance (ATR)", color=color.green)
bgcolor(patternSignal == 1 ? color.new(color.purple, 80) : na)
if patternSignal == 1 and barstate.isconfirmed
alert("Double Pattern detected on " + syminfo.ticker + " at " + str.tostring(close), alert.freq_once_per_bar_close)
if barstate.islast
var table infoTable = table.new(position.top_right, 1, 3, bgcolor=color.new(color.black, 50))
table.cell(infoTable, 0, 0, "Pattern: " + str.tostring(patternSignal), bgcolor=patternSignal == 1 ? color.purple : color.gray)
table.cell(infoTable, 0, 1, "Level: " + str.tostring(nearestDoubleLevel, "#.##"), bgcolor=color.orange)
table.cell(infoTable, 0, 2, "ATR Dist: " + str.tostring(distanceNormalizedATR, "#.##"), bgcolor=color.green)
55 ABR Currentcurrent bar range
abr
previous_bar ibs
当前K线范围 (Curr Bar Rng):显示当前正在形成的K线的价格幅度(最高价-最低价)
平均K线范围 (ABR):计算指定周期内(默认8根K线)的平均K线范围,这个数值可以帮助交易者了解市场的平均波动性
内部K线强度 (IBS):显示前一根已完成K线的内部强度百分比
This Pine Script indicator creates a real-time information panel in the top-right corner of TradingView charts, displaying three key trading metrics:Core Features:
Current Bar Range: Shows the price range (high - low) of the currently forming candlestick, providing immediate awareness of intraday volatility.
Average Bar Range (ABR): Calculates the mean candlestick range over a specified lookback period (default: 8 bars). This metric helps traders assess whether current market volatility is above or below recent norms.
Internal Bar Strength (IBS): Displays the previous completed bar's internal strength as a percentage,
RSI Signals Multi-Layer RSI System with Classical Divergence**DrFX RSI Signals Fixed** is an advanced RSI-based trading system that combines duration-filtered extreme conditions with classical divergence detection and momentum confirmation. This enhanced version addresses common RSI false signals through multi-layer filtering while adding proper divergence analysis for identifying high-probability reversal points.
**Core Innovation & Originality**
This indicator uniquely integrates five analytical layers:
1. **Duration-Validated Extreme Zones** - Confirms RSI has remained overbought/oversold for minimum bars within lookback period
2. **Classical Divergence Detection** - Proper implementation comparing swing highs/lows in both price and RSI
3. **Momentum Confirmation Signals** - RSI crossing 50-line after extreme conditions for trend confirmation
4. **Multi-Signal Classification** - Four distinct signal types (Buy, Sell, Strong Buy, Strong Sell, Momentum)
5. **Visual Zone Highlighting** - Background coloring for instant extreme zone identification
**Technical Implementation & Improvements**
**Enhanced Duration Filter:**
Unlike the previous version, this system uses a refined approach:
```
for i = 0 to lookback_bars - 1
if rsi > overbought
barsInOverbought := barsInOverbought + 1
```
This counts actual bars within the lookback period (default 20 bars) where RSI was extreme, requiring minimum duration (default 4 bars) for signal validation.
**Classical Divergence Detection:**
The system implements proper divergence analysis, a significant improvement over simple delta comparison:
**Bullish Divergence Logic:**
- Price makes lower low: `low < prevPriceLow`
- RSI makes higher low: `rsi > prevRsiLow`
- Indicates weakening downward momentum despite lower prices
**Bearish Divergence Logic:**
- Price makes higher high: `high > prevPriceHigh`
- RSI makes lower high: `rsi < prevRsiHigh`
- Indicates weakening upward momentum despite higher prices
**Signal Generation Framework:**
**Primary Signals:**
- **Buy Signal**: RSI crosses above oversold (30) after meeting duration requirements
- **Sell Signal**: RSI crosses below overbought (70) after meeting duration requirements
**Strong Signals:**
- **Strong Buy**: Buy signal + bullish divergence confirmation
- **Strong Sell**: Sell signal + bearish divergence confirmation
**Momentum Signals:**
- **Momentum Buy (M+)**: RSI crosses above 50 after recent oversold conditions
- **Momentum Sell (M-)**: RSI crosses below 50 after recent overbought conditions
**What Makes This Version Superior**
**Compared to Standard RSI:**
1. **Duration Requirement**: Prevents signals on brief RSI spikes
2. **Lookback Validation**: Ensures extreme conditions actually occurred recently
3. **Proper Divergence**: Uses swing high/low comparison, not just bar-to-bar deltas
4. **Momentum Layer**: Adds trend confirmation via 50-line crosses
**Compared to Previous Version:**
1. **Pine Script v5**: Modern syntax with improved performance
2. **Configurable Parameters**: All values adjustable via inputs
3. **Better Divergence**: Classical divergence logic replaces simplified delta method
4. **Additional Signals**: Momentum confirmations for trend following
5. **Visual Enhancements**: Background coloring and improved signal differentiation
6. **Alert System**: Built-in alert conditions for all signal types
**Parameter Configuration**
**Customizable Inputs:**
- **Overbought Level** (70): Upper threshold, range 50-90
- **Oversold Level** (30): Lower threshold, range 10-50
- **RSI Period** (14): Calculation period, range 2-50
- **Minimum Duration** (4): Required bars in extreme zone, range 1-20
- **Lookback Bars** (20): Period to check for extreme conditions, range 5-100
- **Divergence Lookback** (5): Period for divergence swing comparison, range 2-20
**Optimization Guidelines:**
- **Shorter Duration** (2-3): More frequent signals, higher noise
- **Longer Duration** (5-7): Fewer signals, better quality
- **Smaller Lookback** (10-15): Faster response, may miss context
- **Larger Lookback** (30-50): More context, potentially delayed signals
**Signal Interpretation Guide**
**Visual Signal Hierarchy:**
**Light Green Triangle (Buy):**
- RSI recovered from oversold
- Duration requirements met
- Entry on reversal from oversold territory
**Light Red Triangle (Sell):**
- RSI declined from overbought
- Duration requirements met
- Entry on reversal from overbought territory
**Blue Triangle (Strong Buy):**
- Buy signal with bullish divergence
- Highest probability long setup
- Price made lower low, RSI made higher low
**Magenta Triangle (Strong Sell):**
- Sell signal with bearish divergence
- Highest probability short setup
- Price made higher high, RSI made lower high
**Tiny Green Circle (M+):**
- RSI crossed above 50 after oversold
- Momentum confirmation for uptrend
- Secondary entry or trend confirmation
**Tiny Red Circle (M-):**
- RSI crossed below 50 after overbought
- Momentum confirmation for downtrend
- Secondary entry or trend confirmation
**Background Coloring:**
- **Light Red Background**: RSI > 70 (overbought zone)
- **Light Green Background**: RSI < 30 (oversold zone)
**Trading Strategy Application**
**Conservative Approach (Strong Signals Only):**
1. Wait for blue/magenta triangles (divergence confirmed)
2. Enter on signal bar close or next bar open
3. Stop loss beyond recent swing high/low
4. Target minimum 2:1 risk/reward ratio
**Aggressive Approach (All Signals):**
1. Take light green/red triangles for earlier entries
2. Use momentum circles as confirmation
3. Tighter stops with partial profit taking
4. Scale positions based on signal strength
**Momentum Trading:**
1. Use momentum signals (M+/M-) as trend filters
2. Take primary signals aligned with momentum direction
3. Avoid counter-momentum signals in strong trends
4. Exit when opposing momentum signal appears
**Multi-Timeframe Strategy:**
1. Check higher timeframe for strong signals
2. Execute on lower timeframe primary signals
3. Use momentum signals for position management
4. Align all timeframe signals for best probability
**Optimal Market Conditions**
**Best Performance:**
- Mean-reverting markets with clear RSI extremes
- Range-bound or consolidating conditions
- Markets respecting support/resistance levels
- Timeframes: 15min to 4H for active trading
**Strong Signal Advantages:**
- Divergence signals often mark major turning points
- Work well at market structure levels
- Effective in both trending and ranging markets
- Higher success rate justifies waiting for setup
**Momentum Signal Benefits:**
- Confirms trend direction after extreme readings
- Useful for adding to positions
- Helps avoid counter-trend trades
- Works well in trending markets where reversals fail
**Technical Advantages**
**Divergence Accuracy:**
The improved divergence detection uses proper swing analysis rather than simple bar-to-bar comparison. This identifies genuine momentum shifts where price action diverges from oscillator movement over a meaningful period.
**Duration Logic:**
The for-loop counting method ensures the system checks actual RSI values within the lookback period, not just whether RSI touched levels. This distinguishes between sustained conditions and brief spikes.
**Momentum Filter:**
The 50-line crosses after extreme conditions provide an additional confirmation layer, helping traders distinguish between failed reversals (no momentum follow-through) and sustained moves (momentum confirmation).
**Risk Management Integration**
**Signal Priority:**
1. **Highest**: Strong signals with divergence (blue/magenta triangles)
2. **Medium**: Primary signals without divergence (light green/red triangles)
3. **Confirmation**: Momentum signals (tiny circles)
**Position Sizing:**
- Larger positions on strong signals (divergence present)
- Standard positions on primary signals
- Smaller positions or adds on momentum signals
**Stop Placement:**
- Beyond recent swing structure
- Below/above divergence swing low/high for strong signals
- Trail stops when momentum signals align with position
**Alert System**
Built-in alert conditions for:
- Buy Signal: RSI buy without divergence
- Sell Signal: RSI sell without divergence
- Strong Buy Alert: Buy with bullish divergence
- Strong Sell Alert: Sell with bearish divergence
Configure alerts via TradingView's alert system to receive notifications for chosen signal types.
**Important Considerations**
**Strengths:**
- Multiple confirmation layers reduce false signals
- Classical divergence improves reversal detection
- Momentum signals add trend-following capability
- Highly customizable for different trading styles
- No repainting - all signals fixed at bar close
**Limitations:**
- Duration requirements may cause missed quick reversals
- Divergence lookback period affects sensitivity
- Not suitable as standalone system
- Requires understanding of RSI principles and divergence concepts
**Best Practices:**
- Combine with price action and support/resistance
- Use higher timeframe context for directional bias
- Respect overall market trend and structure
- Implement proper position sizing based on signal type
- Test parameters on your specific instrument and timeframe
**Comparison Summary**
This enhanced version represents a significant upgrade:
- Upgraded to Pine Script v5 modern standards
- Proper classical divergence detection (not simplified)
- Added momentum confirmation signals
- Fully customizable parameters via inputs
- Visual background zone highlighting
- Comprehensive alert system
- Better signal differentiation through color coding
The system transforms basic RSI analysis into a multi-dimensional trading tool suitable for various market conditions and trading styles.
**Disclaimer**: This indicator is designed for educational and analytical purposes. While the multi-layer filtering and classical divergence detection improve upon standard RSI implementations, no indicator guarantees profitable trades. The duration filtering reduces false signals but may delay entries. Divergence signals, while statistically favorable, can fail in strong trending conditions. Always use proper risk management, position sizing, and stop-loss orders. Consider multiple confirmation methods and market context before making trading decisions. Past performance does not guarantee future results.
CCI vs Two EMAs + Trendlines + Breakout HighlightPerfect indicator which analyzes the cci4000 & 2 EMAS.
MACD Aspray Hybrid Strategy The MACD Aspray Hybrid Strategy is a trend-following trading system based on a modified version of the MACD indicator.
BOCS AdaptiveBOCS Adaptive Strategy - Automated Volatility Breakout System
WHAT THIS STRATEGY DOES:
This is an automated trading strategy that detects consolidation patterns through volatility analysis and executes trades when price breaks out of these channels. Take-profit and stop-loss levels are calculated dynamically using Average True Range (ATR) to adapt to current market volatility. The strategy closes positions partially at the first profit target and exits the remainder at the second target or stop loss.
TECHNICAL METHODOLOGY:
Price Normalization Process:
The strategy begins by normalizing price to create a consistent measurement scale. It calculates the highest high and lowest low over a user-defined lookback period (default 100 bars). The current close price is then normalized using the formula: (close - lowest_low) / (highest_high - lowest_low). This produces values between 0 and 1, allowing volatility analysis to work consistently across different instruments and price levels.
Volatility Detection:
A 14-period standard deviation is applied to the normalized price series. Standard deviation measures how much prices deviate from their average - higher values indicate volatility expansion, lower values indicate consolidation. The strategy uses ta.highestbars() and ta.lowestbars() functions to track when volatility reaches peaks and troughs over the detection length period (default 14 bars).
Channel Formation Logic:
When volatility crosses from a high level to a low level, this signals the beginning of a consolidation phase. The strategy records this moment using ta.crossover(upper, lower) and begins tracking the highest and lowest prices during the consolidation. These become the channel boundaries. The duration between the crossover and current bar must exceed 10 bars minimum to avoid false channels from brief volatility spikes. Channels are drawn using box objects with the recorded high/low boundaries.
Breakout Signal Generation:
Two detection modes are available:
Strong Closes Mode (default): Breakout occurs when the candle body midpoint math.avg(close, open) exceeds the channel boundary. This filters out wick-only breaks.
Any Touch Mode: Breakout occurs when the close price exceeds the boundary.
When price closes above the upper channel boundary, a bullish breakout signal generates. When price closes below the lower boundary, a bearish breakout signal generates. The channel is then removed from the chart.
ATR-Based Risk Management:
The strategy uses request.security() to fetch ATR values from a specified timeframe, which can differ from the chart timeframe. For example, on a 5-minute chart, you can use 1-minute ATR for more responsive calculations. The ATR is calculated using ta.atr(length) with a user-defined period (default 14).
Exit levels are calculated at the moment of breakout:
Long Entry Price = Upper channel boundary
Long TP1 = Entry + (ATR × TP1 Multiplier)
Long TP2 = Entry + (ATR × TP2 Multiplier)
Long SL = Entry - (ATR × SL Multiplier)
For short trades, the calculation inverts:
Short Entry Price = Lower channel boundary
Short TP1 = Entry - (ATR × TP1 Multiplier)
Short TP2 = Entry - (ATR × TP2 Multiplier)
Short SL = Entry + (ATR × SL Multiplier)
Trade Execution Logic:
When a breakout occurs, the strategy checks if trading hours filter is satisfied (if enabled) and if position size equals zero (no existing position). If volume confirmation is enabled, it also verifies that current volume exceeds 1.2 times the 20-period simple moving average.
If all conditions are met:
strategy.entry() opens a position using the user-defined number of contracts
strategy.exit() immediately places a stop loss order
The code monitors price against TP1 and TP2 levels on each bar
When price reaches TP1, strategy.close() closes the specified number of contracts (e.g., if you enter with 3 contracts and set TP1 close to 1, it closes 1 contract). When price reaches TP2, it closes all remaining contracts. If stop loss is hit first, the entire position exits via the strategy.exit() order.
Volume Analysis System:
The strategy uses ta.requestUpAndDownVolume(timeframe) to fetch up volume, down volume, and volume delta from a specified timeframe. Three display modes are available:
Volume Mode: Shows total volume as bars scaled relative to the 20-period average
Comparison Mode: Shows up volume and down volume as separate bars above/below the channel midline
Delta Mode: Shows net volume delta (up volume - down volume) as bars, positive values above midline, negative below
The volume confirmation logic compares breakout bar volume to the 20-period SMA. If volume ÷ average > 1.2, the breakout is classified as "confirmed." When volume confirmation is enabled in settings, only confirmed breakouts generate trades.
INPUT PARAMETERS:
Strategy Settings:
Number of Contracts: Fixed quantity to trade per signal (1-1000)
Require Volume Confirmation: Toggle to only trade signals with volume >120% of average
TP1 Close Contracts: Exact number of contracts to close at first target (1-1000)
Use Trading Hours Filter: Toggle to restrict trading to specified session
Trading Hours: Session input in HHMM-HHMM format (e.g., "0930-1600")
Main Settings:
Normalization Length: Lookback bars for high/low calculation (1-500, default 100)
Box Detection Length: Period for volatility peak/trough detection (1-100, default 14)
Strong Closes Only: Toggle between body midpoint vs close price for breakout detection
Nested Channels: Allow multiple overlapping channels vs single channel at a time
ATR TP/SL Settings:
ATR Timeframe: Source timeframe for ATR calculation (1, 5, 15, 60, etc.)
ATR Length: Smoothing period for ATR (1-100, default 14)
Take Profit 1 Multiplier: Distance from entry as multiple of ATR (0.1-10.0, default 2.0)
Take Profit 2 Multiplier: Distance from entry as multiple of ATR (0.1-10.0, default 3.0)
Stop Loss Multiplier: Distance from entry as multiple of ATR (0.1-10.0, default 1.0)
Enable Take Profit 2: Toggle second profit target on/off
VISUAL INDICATORS:
Channel boxes with semi-transparent fill showing consolidation zones
Green/red colored zones at channel boundaries indicating breakout areas
Volume bars displayed within channels using selected mode
TP/SL lines with labels showing both price level and distance in points
Entry signals marked with up/down triangles at breakout price
Strategy status table showing position, contracts, P&L, ATR values, and volume confirmation status
HOW TO USE:
For 2-Minute Scalping:
Set ATR Timeframe to "1" (1-minute), ATR Length to 12, TP1 Multiplier to 2.0, TP2 Multiplier to 3.0, SL Multiplier to 1.5. Enable volume confirmation and strong closes only. Use trading hours filter to avoid low-volume periods.
For 5-15 Minute Day Trading:
Set ATR Timeframe to match chart or use 5-minute, ATR Length to 14, TP1 Multiplier to 2.0, TP2 Multiplier to 3.5, SL Multiplier to 1.2. Volume confirmation recommended but optional.
For Hourly+ Swing Trading:
Set ATR Timeframe to 15-30 minute, ATR Length to 14-21, TP1 Multiplier to 2.5, TP2 Multiplier to 4.0, SL Multiplier to 1.5. Volume confirmation optional, nested channels can be enabled for multiple setups.
BACKTEST CONSIDERATIONS:
Strategy performs best during trending or volatility expansion phases
Consolidation-heavy or choppy markets produce more false signals
Shorter timeframes require wider stop loss multipliers due to noise
Commission and slippage significantly impact performance on sub-5-minute charts
Volume confirmation generally improves win rate but reduces trade frequency
ATR multipliers should be optimized for specific instrument characteristics
COMPATIBLE MARKETS:
Works on any instrument with price and volume data including forex pairs, stock indices, individual stocks, cryptocurrency, commodities, and futures contracts. Requires TradingView data feed that includes volume for volume confirmation features to function.
KNOWN LIMITATIONS:
Stop losses execute via strategy.exit() and may not fill at exact levels during gaps or extreme volatility
request.security() on lower timeframes requires higher-tier TradingView subscription
False breakouts inherent to breakout strategies cannot be completely eliminated
Performance varies significantly based on market regime (trending vs ranging)
Partial closing logic requires sufficient position size relative to TP1 close contracts setting
RISK DISCLOSURE:
Trading involves substantial risk of loss. Past performance of this or any strategy does not guarantee future results. This strategy is provided for educational purposes and automated backtesting. Thoroughly test on historical data and paper trade before risking real capital. Market conditions change and strategies that worked historically may fail in the future. Use appropriate position sizing and never risk more than you can afford to lose. Consider consulting a licensed financial advisor before making trading decisions.
ACKNOWLEDGMENT & CREDITS:
This strategy is built upon the channel detection methodology created by AlgoAlpha in the "Smart Money Breakout Channels" indicator. Full credit and appreciation to AlgoAlpha for pioneering the normalized volatility approach to identifying consolidation patterns and sharing this innovative technique with the TradingView community. The enhancements added to the original concept include automated trade execution, multi-timeframe ATR-based risk management, partial position closing by contract count, volume confirmation filtering, and real-time position monitoring.
Double Top/Bottom Screener - Today Only v2 //@version=6
indicator("Double Top/Bottom Screener - Today Only", overlay=true, max_lines_count=500)
// Inputs
leftBars = input.int(5, "Left Bars")
rightBars = input.int(5, "Right Bars")
tolerance = input.float(0.02, "Max Difference (e.g., 0.02 for 2 cents)", step=0.01)
atrLength = input.int(14, "ATR Length for Normalized Distance", minval=1)
requiredPeaks = input.int(3, "Required Identical Peaks", minval=2, maxval=5)
// Declarations of persistent variables and arrays
var array resistanceLevels = array.new(0)
var array resistanceCounts = array.new(0)
var array supportLevels = array.new(0)
var array supportCounts = array.new(0)
var array resLines = array.new(0)
var array supLines = array.new(0)
var bool hasDoubleTop = false
var bool hasDoubleBottom = false
var float doubleTopLevel = na
var float doubleBottomLevel = na
var int todayStart = na
// Step 1: Identify Swing Highs/Lows
swingHigh = ta.pivothigh(high, leftBars, rightBars)
swingLow = ta.pivotlow(low, leftBars, rightBars)
// Today's premarket start (04:00 AM ET)
todayStart := timestamp(syminfo.timezone, year, month, dayofmonth, 4, 0, 0)
// Clear arrays and delete lines on the first bar or new day
if barstate.isfirst or (dayofmonth != dayofmonth and time >= todayStart)
// Delete all existing lines only if arrays are not empty
if array.size(resLines) > 0
for i = array.size(resLines) - 1 to 0
line.delete(array.get(resLines, i))
if array.size(supLines) > 0
for i = array.size(supLines) - 1 to 0
line.delete(array.get(supLines, i))
// Clear arrays
array.clear(resistanceLevels)
array.clear(supportLevels)
array.clear(resistanceCounts)
array.clear(supportCounts)
array.clear(resLines)
array.clear(supLines)
// Reset flags
hasDoubleTop := false
hasDoubleBottom := false
doubleTopLevel := na
doubleBottomLevel := na
// Add new swings only if today and after premarket
if not na(swingHigh) and time >= todayStart and dayofmonth == dayofmonth
bool isEqualHigh = false
int peakIndex = -1
float prevLevel = na
if array.size(resistanceLevels) > 0
for i = 0 to array.size(resistanceLevels) - 1
prevLevel := array.get(resistanceLevels, i)
if math.abs(swingHigh - prevLevel) <= tolerance
isEqualHigh := true
peakIndex := i
break
if isEqualHigh and peakIndex >= 0
array.set(resistanceCounts, peakIndex, array.get(resistanceCounts, peakIndex) + 1)
if array.get(resistanceCounts, peakIndex) == requiredPeaks
hasDoubleTop := true
doubleTopLevel := prevLevel
else
array.push(resistanceLevels, swingHigh)
array.push(resistanceCounts, 1)
line newResLine = line.new(bar_index - rightBars, swingHigh, bar_index, swingHigh, color=color.red, width=2, extend=extend.none)
array.push(resLines, newResLine)
if not na(swingLow) and time >= todayStart and dayofmonth == dayofmonth
bool isEqualLow = false
int peakIndex = -1
float prevLevel = na
if array.size(supportLevels) > 0
for i = 0 to array.size(supportLevels) - 1
prevLevel := array.get(supportLevels, i)
if math.abs(swingLow - prevLevel) <= tolerance
isEqualLow := true
peakIndex := i
break
if isEqualLow and peakIndex >= 0
array.set(supportCounts, peakIndex, array.get(supportCounts, peakIndex) + 1)
if array.get(supportCounts, peakIndex) == requiredPeaks
hasDoubleBottom := true
doubleBottomLevel := prevLevel
else
array.push(supportLevels, swingLow)
array.push(supportCounts, 1)
line newSupLine = line.new(bar_index - rightBars, swingLow, bar_index, swingLow, color=color.green, width=2, extend=extend.none)
array.push(supLines, newSupLine)
// Monitor and remove broken levels/lines; reset pattern if the equal level breaks
if array.size(resistanceLevels) > 0
for i = array.size(resistanceLevels) - 1 to 0
float level = array.get(resistanceLevels, i)
if close > level
line.delete(array.get(resLines, i))
array.remove(resLines, i)
array.remove(resistanceLevels, i)
array.remove(resistanceCounts, i)
if level == doubleTopLevel
hasDoubleTop := false
doubleTopLevel := na
if array.size(supportLevels) > 0
for i = array.size(supportLevels) - 1 to 0
float level = array.get(supportLevels, i)
if close < level
line.delete(array.get(supLines, i))
array.remove(supLines, i)
array.remove(supportLevels, i)
array.remove(supportCounts, i)
if level == doubleBottomLevel
hasDoubleBottom := false
doubleBottomLevel := na
// Limit arrays (after removals)
if array.size(resistanceLevels) > 10
line oldLine = array.shift(resLines)
line.delete(oldLine)
array.shift(resistanceLevels)
array.shift(resistanceCounts)
if array.size(supportLevels) > 10
line oldLine = array.shift(supLines)
line.delete(oldLine)
array.shift(supportLevels)
array.shift(supportCounts)
// Pattern Signal: 1 only if the exact required number of peaks is met
patternSignal = (hasDoubleTop or hasDoubleBottom) ? 1 : 0
// New: Nearest Double Level Price
var float nearestDoubleLevel = na
if hasDoubleTop and not na(doubleTopLevel)
nearestDoubleLevel := doubleTopLevel
if hasDoubleBottom and not na(doubleBottomLevel)
nearestDoubleLevel := na(nearestDoubleLevel) ? doubleBottomLevel : (math.abs(close - doubleBottomLevel) < math.abs(close - nearestDoubleLevel) ? doubleBottomLevel : nearestDoubleLevel)
// New: Distance to Nearest Level (using ATR for normalization)
var float atr = ta.atr(atrLength)
var float distanceNormalizedATR = na
if not na(nearestDoubleLevel) and not na(atr) and atr > 0
distanceNormalizedATR := math.abs(close - nearestDoubleLevel) / atr
// Optional Bounce Signal (for reference)
bounceSignal = 0
if array.size(resistanceLevels) > 0
for i = 0 to array.size(resistanceLevels) - 1
float level = array.get(resistanceLevels, i)
if low <= level and high >= level and close < level
bounceSignal := 1
if array.size(supportLevels) > 0
for i = 0 to array.size(supportLevels) - 1
float level = array.get(supportLevels, i)
if high >= level and low <= level and close > level
bounceSignal := 1
// Outputs
plot(patternSignal, title="Pattern Signal", color=patternSignal == 1 ? color.purple : na, style=plot.style_circles)
plot(bounceSignal, title="Bounce Signal", color=bounceSignal == 1 ? color.yellow : na, style=plot.style_circles)
plot(nearestDoubleLevel, title="Nearest Double Level Price", color=color.orange)
plot(distanceNormalizedATR, title="Normalized Distance (ATR)", color=color.green)
bgcolor(patternSignal == 1 ? color.new(color.purple, 80) : na)
if patternSignal == 1 and barstate.isconfirmed
alert("Double Pattern detected on " + syminfo.ticker + " at " + str.tostring(close), alert.freq_once_per_bar_close)
if barstate.islast
var table infoTable = table.new(position.top_right, 1, 4, bgcolor=color.new(color.black, 50))
table.cell(infoTable, 0, 0, "Pattern: " + str.tostring(patternSignal), bgcolor=patternSignal == 1 ? color.purple : color.gray)
table.cell(infoTable, 0, 1, "Bounce: " + str.tostring(bounceSignal), bgcolor=bounceSignal == 1 ? color.yellow : color.gray)
table.cell(infoTable, 0, 2, "Level: " + str.tostring(nearestDoubleLevel, "#.##"), bgcolor=color.orange)
table.cell(infoTable, 0, 3, "ATR Dist: " + str.tostring(distanceNormalizedATR, "#.##"), bgcolor=color.green)
Oscillator Matrix [Alpha Extract]A comprehensive multi-oscillator system that combines volume-weighted money flow analysis with enhanced momentum detection, providing traders with a unified framework for identifying high-probability market opportunities across all timeframes. By integrating two powerful oscillators with advanced confluence analysis, this indicator delivers precise entry and exit signals while filtering out market noise through sophisticated threshold-based regime detection.
🔶 Volume-Weighted Money Flow Analysis
Utilizes an advanced money flow calculation that tracks volume-weighted price movements to identify institutional activity and smart money flow. This approach provides superior signal quality by emphasizing high-volume price movements while filtering out low-volume market noise.
// Volume-weighted flows
up_volume = price_up ? volume : 0
down_volume = price_down ? volume : 0
// Money Flow calculation
up_vol_sum = ta.sma(up_volume, mf_length)
down_vol_sum = ta.sma(down_volume, mf_length)
total_volume = up_vol_sum + down_vol_sum
money_flow_ratio = total_volume > 0 ? (up_vol_sum - down_vol_sum) / total_volume : 0
🔶 Enhanced Hyper Wave Oscillator
Features a sophisticated MACD-based momentum oscillator with advanced normalization techniques that adapt to different price ranges and market volatility. The system uses percentage-based calculations to ensure consistent performance across various instruments and timeframes.
// Enhanced MACD-based oscillator
fast_ma = ta.ema(src, hw_fast)
slow_ma = ta.ema(src, hw_slow)
macd_line = fast_ma - slow_ma
signal_line = ta.ema(macd_line, hw_signal)
// Proper normalization using percentage of price
price_base = ta.sma(close, 50)
macd_normalized = macd_line / price_base
hyper_wave = macd_range > 0 ? macd_normalized / macd_range : 0
🔶 Multi-Factor Confluence System
Implements an intelligent confluence scoring mechanism that combines signals from both oscillators to identify high-probability trading opportunities. The system assigns strength scores based on multiple confirmation factors, significantly reducing false signals.
🔶 Fixed Threshold Levels
Uses predefined threshold levels optimized for standard oscillator ranges to distinguish between normal market fluctuations and significant momentum shifts. The dual-threshold system provides clear visual cues for overbought/oversold conditions while maintaining consistent signal criteria across different market conditions.
🔶 Overflow Detection Technology
Advanced overflow indicators identify extreme market conditions that often precede major reversals or continuation patterns. These signals highlight moments when market momentum reaches critical levels, providing early warning for potential turning points.
🔶 Dual Oscillator Integration
The indicator simultaneously tracks volume-weighted money flow and momentum-based price action through two independent oscillators. This dual approach ensures comprehensive market analysis by capturing both institutional activity and technical momentum patterns.
// Multi-factor confluence scoring
confluence_bull = (mf_bullish ? 1 : 0) + (hw_bullish ? 1 : 0) +
(mf_overflow_bull ? 1 : 0) + (hw_overflow_bull ? 1 : 0)
confluence_bear = (mf_bearish ? 1 : 0) + (hw_bearish ? 1 : 0) +
(mf_overflow_bear ? 1 : 0) + (hw_overflow_bear ? 1 : 0)
confluence_strength = confluence_bull > confluence_bear ? confluence_bull / 4 : -confluence_bear / 4
🔶 Intelligent Signal Generation
The system generates two tiers of reversal signals: strong signals that require multiple confirmations across both oscillators, and weak signals that identify early momentum shifts. This hierarchical approach allows traders to adjust position sizing based on signal strength.
🔶 Visual Confluence Zones
Background coloring dynamically adjusts based on confluence strength, creating visual zones that immediately communicate market sentiment. The intensity of background shading corresponds to the strength of the confluent signals, making pattern recognition effortless.
🔶 Threshold Visualization
Color-coded threshold zones provide instant visual feedback about oscillator positions relative to key levels. The fill areas between thresholds create clear overbought and oversold regions with graduated color intensity.
🔶 Candle Color Integration
Optional candle coloring applies confluence-based color logic directly to price bars, creating a unified visual framework that helps traders correlate indicator signals with actual price movements for enhanced decision-making.
🔶 Overflow Alert System
Specialized circular markers highlight extreme overflow conditions on both oscillators, drawing attention to potential climax moves that often precede significant reversals or accelerated trend continuation.
🔶 Customizable Display Options
Comprehensive display controls allow traders to toggle individual components on or off, enabling focused analysis on specific aspects of the indicator. This modularity ensures the indicator adapts to different trading styles and analytical preferences.
1 Week
1 Day
15 Min
This indicator provides a complete analytical framework by combining volume analysis with momentum detection in a single, coherent system. By offering multiple confirmation layers and clear visual hierarchies, it empowers traders to identify high-probability opportunities while maintaining precise risk management across all market conditions and timeframes. The sophisticated confluence system ensures that signals are both timely and reliable, making it an essential tool for serious technical analysts.
Double Top/Bottom Screener - Today Only//@version=6
indicator("Double Top/Bottom Screener - Today Only", overlay=true, max_lines_count=500)
// Inputs
leftBars = input.int(5, "Left Bars")
rightBars = input.int(5, "Right Bars")
tolerance = input.float(0.02, "Max Difference (e.g., 0.02 for 2 cents)", step=0.01)
atrLength = input.int(14, "ATR Length for Normalized Distance", minval=1)
requiredPeaks = input.int(3, "Required Identical Peaks", minval=2, maxval=5)
// Declarations of persistent variables and arrays
var array resistanceLevels = array.new(0)
var array resistanceCounts = array.new(0)
var array supportLevels = array.new(0)
var array supportCounts = array.new(0)
var array resLines = array.new(0)
var array supLines = array.new(0)
var bool hasDoubleTop = false
var bool hasDoubleBottom = false
var float doubleTopLevel = na
var float doubleBottomLevel = na
var int todayStart = na
// Step 1: Identify Swing Highs/Lows
swingHigh = ta.pivothigh(high, leftBars, rightBars)
swingLow = ta.pivotlow(low, leftBars, rightBars)
// Today's premarket start (04:00 AM ET)
todayStart := timestamp(syminfo.timezone, year, month, dayofmonth, 4, 0, 0)
// Clear arrays and delete lines on the first bar or new day
if barstate.isfirst or (dayofmonth != dayofmonth and time >= todayStart)
// Delete all existing lines
for i = array.size(resLines) - 1 to 0
line.delete(array.get(resLines, i))
for i = array.size(supLines) - 1 to 0
line.delete(array.get(supLines, i))
// Clear arrays
array.clear(resistanceLevels)
array.clear(supportLevels)
array.clear(resistanceCounts)
array.clear(supportCounts)
array.clear(resLines)
array.clear(supLines)
// Reset flags
hasDoubleTop := false
hasDoubleBottom := false
doubleTopLevel := na
doubleBottomLevel := na
// Add new swings only if today and after premarket
if not na(swingHigh) and time >= todayStart and dayofmonth == dayofmonth
bool isEqualHigh = false
int peakIndex = -1
float prevLevel = na
if array.size(resistanceLevels) > 0
for i = 0 to array.size(resistanceLevels) - 1
prevLevel := array.get(resistanceLevels, i)
if math.abs(swingHigh - prevLevel) <= tolerance
isEqualHigh := true
peakIndex := i
break
if isEqualHigh and peakIndex >= 0
array.set(resistanceCounts, peakIndex, array.get(resistanceCounts, peakIndex) + 1)
if array.get(resistanceCounts, peakIndex) == requiredPeaks
hasDoubleTop := true
doubleTopLevel := prevLevel
else
array.push(resistanceLevels, swingHigh)
array.push(resistanceCounts, 1)
line newResLine = line.new(bar_index - rightBars, swingHigh, bar_index, swingHigh, color=color.red, width=2, extend=extend.none)
array.push(resLines, newResLine)
if not na(swingLow) and time >= todayStart and dayofmonth == dayofmonth
bool isEqualLow = false
int peakIndex = -1
float prevLevel = na
if array.size(supportLevels) > 0
for i = 0 to array.size(supportLevels) - 1
prevLevel := array.get(supportLevels, i)
if math.abs(swingLow - prevLevel) <= tolerance
isEqualLow := true
peakIndex := i
break
if isEqualLow and peakIndex >= 0
array.set(supportCounts, peakIndex, array.get(supportCounts, peakIndex) + 1)
if array.get(supportCounts, peakIndex) == requiredPeaks
hasDoubleBottom := true
doubleBottomLevel := prevLevel
else
array.push(supportLevels, swingLow)
array.push(supportCounts, 1)
line newSupLine = line.new(bar_index - rightBars, swingLow, bar_index, swingLow, color=color.green, width=2, extend=extend.none)
array.push(supLines, newSupLine)
// Monitor and remove broken levels/lines; reset pattern if the equal level breaks
if array.size(resistanceLevels) > 0
for i = array.size(resistanceLevels) - 1 to 0
float level = array.get(resistanceLevels, i)
if close > level
line.delete(array.get(resLines, i))
array.remove(resLines, i)
array.remove(resistanceLevels, i)
array.remove(resistanceCounts, i)
if level == doubleTopLevel
hasDoubleTop := false
doubleTopLevel := na
if array.size(supportLevels) > 0
for i = array.size(supportLevels) - 1 to 0
float level = array.get(supportLevels, i)
if close < level
line.delete(array.get(supLines, i))
array.remove(supLines, i)
array.remove(supportLevels, i)
array.remove(supportCounts, i)
if level == doubleBottomLevel
hasDoubleBottom := false
doubleBottomLevel := na
// Limit arrays (after removals)
if array.size(resistanceLevels) > 10
line oldLine = array.shift(resLines)
line.delete(oldLine)
array.shift(resistanceLevels)
array.shift(resistanceCounts)
if array.size(supportLevels) > 10
line oldLine = array.shift(supLines)
line.delete(oldLine)
array.shift(supportLevels)
array.shift(supportCounts)
// Pattern Signal: 1 only if the exact required number of peaks is met
patternSignal = (hasDoubleTop or hasDoubleBottom) ? 1 : 0
// New: Nearest Double Level Price
var float nearestDoubleLevel = na
if hasDoubleTop and not na(doubleTopLevel)
nearestDoubleLevel := doubleTopLevel
if hasDoubleBottom and not na(doubleBottomLevel)
nearestDoubleLevel := na(nearestDoubleLevel) ? doubleBottomLevel : (math.abs(close - doubleBottomLevel) < math.abs(close - nearestDoubleLevel) ? doubleBottomLevel : nearestDoubleLevel)
// New: Distance to Nearest Level (using ATR for normalization)
var float atr = ta.atr(atrLength)
var float distanceNormalizedATR = na
if not na(nearestDoubleLevel) and not na(atr) and atr > 0
distanceNormalizedATR := math.abs(close - nearestDoubleLevel) / atr
// Optional Bounce Signal (for reference)
bounceSignal = 0
if array.size(resistanceLevels) > 0
for i = 0 to array.size(resistanceLevels) - 1
float level = array.get(resistanceLevels, i)
if low <= level and high >= level and close < level
bounceSignal := 1
if array.size(supportLevels) > 0
for i = 0 to array.size(supportLevels) - 1
float level = array.get(supportLevels, i)
if high >= level and low <= level and close > level
bounceSignal := 1
// Outputs
plot(patternSignal, title="Pattern Signal", color=patternSignal == 1 ? color.purple : na, style=plot.style_circles)
plot(bounceSignal, title="Bounce Signal", color=bounceSignal == 1 ? color.yellow : na, style=plot.style_circles)
plot(nearestDoubleLevel, title="Nearest Double Level Price", color=color.orange)
plot(distanceNormalizedATR, title="Normalized Distance (ATR)", color=color.green)
bgcolor(patternSignal == 1 ? color.new(color.purple, 80) : na)
if patternSignal == 1 and barstate.isconfirmed
alert("Double Pattern detected on " + syminfo.ticker + " at " + str.tostring(close), alert.freq_once_per_bar_close)
if barstate.islast
var table infoTable = table.new(position.top_right, 1, 4, bgcolor=color.new(color.black, 50))
table.cell(infoTable, 0, 0, "Pattern: " + str.tostring(patternSignal), bgcolor=patternSignal == 1 ? color.purple : color.gray)
table.cell(infoTable, 0, 1, "Bounce: " + str.tostring(bounceSignal), bgcolor=bounceSignal == 1 ? color.yellow : color.gray)
table.cell(infoTable, 0, 2, "Level: " + str.tostring(nearestDoubleLevel, "#.##"), bgcolor=color.orange)
table.cell(infoTable, 0, 3, "ATR Dist: " + str.tostring(distanceNormalizedATR, "#.##"), bgcolor=color.green)
[MCN] Volume Weighted Average PriceStandard VWAP with custom stdv colourings and the ability to anchor by midnight price.
Highlight Selected WeekdaysThis indicator allows you to highlight selected trading days of the week directly on the chart with customizable colors.
Features:
Choose which weekdays to highlight (Sunday through Saturday).
Assign a different background color to each selected day.
Option to calculate the weekday based on the daily close or the active bar’s time.
Double Top/Bottom Screener V1//@version=6
indicator("Double Top/Bottom Screener", overlay=true, max_lines_count=500)
// Inputs
leftBars = input.int(5, "Left Bars")
rightBars = input.int(5, "Right Bars")
tolerance = input.float(0.02, "Max Difference (e.g., 0.02 for 2 cents)", step=0.01)
atrLength = input.int(14, "ATR Length for Normalized Distance", minval=1)
requiredPeaks = input.int(3, "Required Identical Peaks", minval=2, maxval=5)
// Declarations of persistent variables and arrays
var array resistanceLevels = array.new(0)
var array resistanceCounts = array.new(0)
var array supportLevels = array.new(0)
var array supportCounts = array.new(0)
var array resLines = array.new(0)
var array supLines = array.new(0)
var bool hasDoubleTop = false
var bool hasDoubleBottom = false
var float doubleTopLevel = na
var float doubleBottomLevel = na
var int todayStart = na
var bool isNewDay = false
// Step 1: Identify Swing Highs/Lows
swingHigh = ta.pivothigh(high, leftBars, rightBars)
swingLow = ta.pivotlow(low, leftBars, rightBars)
// Today's premarket start (04:00 AM ET)
if dayofmonth != dayofmonth
todayStart := timestamp(syminfo.timezone, year, month, dayofmonth, 4, 0, 0)
isNewDay := true
else
isNewDay := false
// Clear arrays and reset flags only once at premarket start
if isNewDay and time >= todayStart
array.clear(resistanceLevels)
array.clear(supportLevels)
array.clear(resistanceCounts)
array.clear(supportCounts)
array.clear(resLines)
array.clear(supLines)
hasDoubleTop := false
hasDoubleBottom := false
doubleTopLevel := na
doubleBottomLevel := na
// Add new swings and check for identical peaks
if not na(swingHigh) and time >= todayStart
bool isEqualHigh = false
int peakIndex = -1
float prevLevel = na
if array.size(resistanceLevels) > 0
for i = 0 to array.size(resistanceLevels) - 1
prevLevel := array.get(resistanceLevels, i)
if math.abs(swingHigh - prevLevel) <= tolerance
isEqualHigh := true
peakIndex := i
break
if isEqualHigh and peakIndex >= 0
array.set(resistanceCounts, peakIndex, array.get(resistanceCounts, peakIndex) + 1)
if array.get(resistanceCounts, peakIndex) == requiredPeaks
hasDoubleTop := true
doubleTopLevel := prevLevel
else
array.push(resistanceLevels, swingHigh)
array.push(resistanceCounts, 1)
line newResLine = line.new(bar_index - rightBars, swingHigh, bar_index, swingHigh, color=color.red, width=2, extend=extend.right)
array.push(resLines, newResLine)
if not na(swingLow) and time >= todayStart
bool isEqualLow = false
int peakIndex = -1
float prevLevel = na
if array.size(supportLevels) > 0
for i = 0 to array.size(supportLevels) - 1
prevLevel := array.get(supportLevels, i)
if math.abs(swingLow - prevLevel) <= tolerance
isEqualLow := true
peakIndex := i
break
if isEqualLow and peakIndex >= 0
array.set(supportCounts, peakIndex, array.get(supportCounts, peakIndex) + 1)
if array.get(supportCounts, peakIndex) == requiredPeaks
hasDoubleBottom := true
doubleBottomLevel := prevLevel
else
array.push(supportLevels, swingLow)
array.push(supportCounts, 1)
line newSupLine = line.new(bar_index - rightBars, swingLow, bar_index, swingLow, color=color.green, width=2, extend=extend.right)
array.push(supLines, newSupLine)
// Monitor and remove broken levels/lines; reset pattern if the equal level breaks
if array.size(resistanceLevels) > 0
for i = array.size(resistanceLevels) - 1 to 0
float level = array.get(resistanceLevels, i)
if close > level
line.delete(array.get(resLines, i))
array.remove(resLines, i)
array.remove(resistanceLevels, i)
array.remove(resistanceCounts, i)
if level == doubleTopLevel
hasDoubleTop := false
doubleTopLevel := na
if array.size(supportLevels) > 0
for i = array.size(supportLevels) - 1 to 0
float level = array.get(supportLevels, i)
if close < level
line.delete(array.get(supLines, i))
array.remove(supLines, i)
array.remove(supportLevels, i)
array.remove(supportCounts, i)
if level == doubleBottomLevel
hasDoubleBottom := false
doubleBottomLevel := na
// Limit arrays (after removals)
if array.size(resistanceLevels) > 10
line oldLine = array.shift(resLines)
line.delete(oldLine)
array.shift(resistanceLevels)
array.shift(resistanceCounts)
if array.size(supportLevels) > 10
line oldLine = array.shift(supLines)
line.delete(oldLine)
array.shift(supportLevels)
array.shift(supportCounts)
// Pattern Signal: 1 only if the exact required number of peaks is met
patternSignal = (hasDoubleTop or hasDoubleBottom) and (array.size(resistanceCounts) > 0 and array.get(resistanceCounts, array.size(resistanceCounts) - 1) == requiredPeaks or array.size(supportCounts) > 0 and array.get(supportCounts, array.size(supportCounts) - 1) == requiredPeaks) ? 1 : 0
// New: Nearest Double Level Price
var float nearestDoubleLevel = na
if hasDoubleTop and not na(doubleTopLevel)
nearestDoubleLevel := doubleTopLevel
if hasDoubleBottom and not na(doubleBottomLevel)
nearestDoubleLevel := na(nearestDoubleLevel) ? doubleBottomLevel : (math.abs(close - doubleBottomLevel) < math.abs(close - nearestDoubleLevel) ? doubleBottomLevel : nearestDoubleLevel)
// New: Distance to Nearest Level (using ATR for normalization)
var float atr = ta.atr(atrLength)
var float distanceNormalizedATR = na
if not na(nearestDoubleLevel) and not na(atr) and atr > 0
distanceNormalizedATR := math.abs(close - nearestDoubleLevel) / atr
// Optional Bounce Signal (for reference)
bounceSignal = 0
if array.size(resistanceLevels) > 0
for i = 0 to array.size(resistanceLevels) - 1
float level = array.get(resistanceLevels, i)
if low <= level and high >= level and close < level
bounceSignal := 1
if array.size(supportLevels) > 0
for i = 0 to array.size(supportLevels) - 1
float level = array.get(supportLevels, i)
if high >= level and low <= level and close > level
bounceSignal := 1
// Outputs
plot(patternSignal, title="Pattern Signal", color=patternSignal == 1 ? color.purple : na, style=plot.style_circles)
plot(bounceSignal, title="Bounce Signal", color=bounceSignal == 1 ? color.yellow : na, style=plot.style_circles)
plot(nearestDoubleLevel, title="Nearest Double Level Price", color=color.orange)
plot(distanceNormalizedATR, title="Normalized Distance (ATR)", color=color.green)
bgcolor(patternSignal == 1 ? color.new(color.purple, 80) : na)
if patternSignal == 1 and barstate.isconfirmed
alert("Double Pattern detected on " + syminfo.ticker + " at " + str.tostring(close), alert.freq_once_per_bar_close)
if barstate.islast
var table infoTable = table.new(position.top_right, 1, 4, bgcolor=color.new(color.black, 50))
table.cell(infoTable, 0, 0, "Pattern: " + str.tostring(patternSignal), bgcolor=patternSignal == 1 ? color.purple : color.gray)
table.cell(infoTable, 0, 1, "Bounce: " + str.tostring(bounceSignal), bgcolor=bounceSignal == 1 ? color.yellow : color.gray)
table.cell(infoTable, 0, 2, "Level: " + str.tostring(nearestDoubleLevel, "#.##"), bgcolor=color.orange)
table.cell(infoTable, 0, 3, "ATR Dist: " + str.tostring(distanceNormalizedATR, "#.##"), bgcolor=color.green)
Double Top/Bottom Screener 3-5 peaks //@version=6
indicator("Double Top/Bottom Screener", overlay=true, max_lines_count=500)
// Inputs
leftBars = input.int(5, "Left Bars")
rightBars = input.int(5, "Right Bars")
tolerance = input.float(0.02, "Max Difference (e.g., 0.02 for 2 cents)", step=0.01)
atrLength = input.int(14, "ATR Length for Normalized Distance", minval=1)
maxPeaks = input.int(5, "Max Identical Peaks", minval=2, maxval=5)
// Declarations of persistent variables and arrays
var array resistanceLevels = array.new(0)
var array resistanceCounts = array.new(0)
var array supportLevels = array.new(0)
var array supportCounts = array.new(0)
var array resLines = array.new(0)
var array supLines = array.new(0)
var bool hasDoubleTop = false
var bool hasDoubleBottom = false
var float doubleTopLevel = na
var float doubleBottomLevel = na
var int todayStart = na
var bool isNewDay = false
// Step 1: Identify Swing Highs/Lows
swingHigh = ta.pivothigh(high, leftBars, rightBars)
swingLow = ta.pivotlow(low, leftBars, rightBars)
// Today's premarket start (04:00 AM ET)
if dayofmonth != dayofmonth
todayStart := timestamp(syminfo.timezone, year, month, dayofmonth, 4, 0, 0)
isNewDay := true
else
isNewDay := false
// Clear arrays and reset flags only once at premarket start
if isNewDay and time >= todayStart
array.clear(resistanceLevels)
array.clear(supportLevels)
array.clear(resistanceCounts)
array.clear(supportCounts)
array.clear(resLines)
array.clear(supLines)
hasDoubleTop := false
hasDoubleBottom := false
doubleTopLevel := na
doubleBottomLevel := na
// Add new swings and check for identical peaks
if not na(swingHigh) and time >= todayStart
bool isEqualHigh = false
int peakIndex = -1
float prevLevel = na // Declare prevLevel with initial value
if array.size(resistanceLevels) > 0
for i = 0 to array.size(resistanceLevels) - 1
prevLevel := array.get(resistanceLevels, i)
if math.abs(swingHigh - prevLevel) <= tolerance
isEqualHigh := true
peakIndex := i
break
if isEqualHigh and peakIndex >= 0
array.set(resistanceCounts, peakIndex, array.get(resistanceCounts, peakIndex) + 1)
if array.get(resistanceCounts, peakIndex) >= maxPeaks
hasDoubleTop := true
doubleTopLevel := prevLevel
else
array.push(resistanceLevels, swingHigh)
array.push(resistanceCounts, 1)
line newResLine = line.new(bar_index - rightBars, swingHigh, bar_index, swingHigh, color=color.red, width=2, extend=extend.right)
array.push(resLines, newResLine)
if not na(swingLow) and time >= todayStart
bool isEqualLow = false
int peakIndex = -1
float prevLevel = na // Declare prevLevel with initial value
if array.size(supportLevels) > 0
for i = 0 to array.size(supportLevels) - 1
prevLevel := array.get(supportLevels, i)
if math.abs(swingLow - prevLevel) <= tolerance
isEqualLow := true
peakIndex := i
break
if isEqualLow and peakIndex >= 0
array.set(supportCounts, peakIndex, array.get(supportCounts, peakIndex) + 1)
if array.get(supportCounts, peakIndex) >= maxPeaks
hasDoubleBottom := true
doubleBottomLevel := prevLevel
else
array.push(supportLevels, swingLow)
array.push(supportCounts, 1)
line newSupLine = line.new(bar_index - rightBars, swingLow, bar_index, swingLow, color=color.green, width=2, extend=extend.right)
array.push(supLines, newSupLine)
// Monitor and remove broken levels/lines; reset pattern if the equal level breaks
if array.size(resistanceLevels) > 0
for i = array.size(resistanceLevels) - 1 to 0
float level = array.get(resistanceLevels, i)
if close > level
line.delete(array.get(resLines, i))
array.remove(resLines, i)
array.remove(resistanceLevels, i)
array.remove(resistanceCounts, i)
if level == doubleTopLevel
hasDoubleTop := false
doubleTopLevel := na
if array.size(supportLevels) > 0
for i = array.size(supportLevels) - 1 to 0
float level = array.get(supportLevels, i)
if close < level
line.delete(array.get(supLines, i))
array.remove(supLines, i)
array.remove(supportLevels, i)
array.remove(supportCounts, i)
if level == doubleBottomLevel
hasDoubleBottom := false
doubleBottomLevel := na
// Limit arrays (after removals)
if array.size(resistanceLevels) > 10
line oldLine = array.shift(resLines)
line.delete(oldLine)
array.shift(resistanceLevels)
array.shift(resistanceCounts)
if array.size(supportLevels) > 10
line oldLine = array.shift(supLines)
line.delete(oldLine)
array.shift(supportLevels)
array.shift(supportCounts)
// Pattern Signal: 1 if any pattern with maxPeaks is active and unbroken
patternSignal = (hasDoubleTop or hasDoubleBottom) ? 1 : 0
// New: Nearest Double Level Price
var float nearestDoubleLevel = na
if hasDoubleTop and not na(doubleTopLevel)
nearestDoubleLevel := doubleTopLevel
if hasDoubleBottom and not na(doubleBottomLevel)
nearestDoubleLevel := na(nearestDoubleLevel) ? doubleBottomLevel : (math.abs(close - doubleBottomLevel) < math.abs(close - nearestDoubleLevel) ? doubleBottomLevel : nearestDoubleLevel)
// New: Distance to Nearest Level (using ATR for normalization)
var float atr = ta.atr(atrLength)
var float distanceNormalizedATR = na
if not na(nearestDoubleLevel) and not na(atr) and atr > 0
distanceNormalizedATR := math.abs(close - nearestDoubleLevel) / atr
// Optional Bounce Signal (for reference)
bounceSignal = 0
if array.size(resistanceLevels) > 0
for i = 0 to array.size(resistanceLevels) - 1
float level = array.get(resistanceLevels, i)
if low <= level and high >= level and close < level
bounceSignal := 1
if array.size(supportLevels) > 0
for i = 0 to array.size(supportLevels) - 1
float level = array.get(supportLevels, i)
if high >= level and low <= level and close > level
bounceSignal := 1
// Outputs
plot(patternSignal, title="Pattern Signal", color=patternSignal == 1 ? color.purple : na, style=plot.style_circles)
plot(bounceSignal, title="Bounce Signal", color=bounceSignal == 1 ? color.yellow : na, style=plot.style_circles)
plot(nearestDoubleLevel, title="Nearest Double Level Price", color=color.orange)
plot(distanceNormalizedATR, title="Normalized Distance (ATR)", color=color.green)
bgcolor(patternSignal == 1 ? color.new(color.purple, 80) : na)
if patternSignal == 1 and barstate.isconfirmed
alert("Double Pattern detected on " + syminfo.ticker + " at " + str.tostring(close), alert.freq_once_per_bar_close)
if barstate.islast
var table infoTable = table.new(position.top_right, 1, 4, bgcolor=color.new(color.black, 50))
table.cell(infoTable, 0, 0, "Pattern: " + str.tostring(patternSignal), bgcolor=patternSignal == 1 ? color.purple : color.gray)
table.cell(infoTable, 0, 1, "Bounce: " + str.tostring(bounceSignal), bgcolor=bounceSignal == 1 ? color.yellow : color.gray)
table.cell(infoTable, 0, 2, "Level: " + str.tostring(nearestDoubleLevel, "#.##"), bgcolor=color.orange)
table.cell(infoTable, 0, 3, "ATR Dist: " + str.tostring(distanceNormalizedATR, "#.##"), bgcolor=color.green)
NOK Basket (Equal-Weighted)Measures the Norwegian crown's relative value to a basket of other currencies: EUR, USD, GBP, SEK AND DKK.
Anchored VWAP (Triple) MYRAXESAnchored VWAP Triple Indicator
The Anchored VWAP Triple indicator is a powerful tool for technical analysis, allowing traders to plot three customizable anchored Volume Weighted Average Price (VWAP) lines on a chart. Unlike traditional VWAP, which resets daily, this indicator lets you anchor each VWAP to a specific date and time, providing a unique perspective on price action relative to key market events.
Features
Three Independent VWAPs: Plot up to three VWAP lines, each anchored to a user-defined date and time.
Customizable Inputs: Set the year, month, day, hour, and minute for each VWAP anchor point. Choose distinct colors for easy identification.
Pure Anchored Design: VWAP lines start only from the anchor point, with no pre-anchor extensions, ensuring a clean and focused analysis.
Debug Mode: Optional display of hour and minute for troubleshooting or educational purposes.
Default Settings: Pre-configured with practical defaults (e.g., September 2025 dates) for immediate use.
How to Use
Add the indicator to your TradingView chart.
Adjust the anchor dates and times for each VWAP (VWAP 1, VWAP 2, VWAP 3) via the input settings.
Select custom colors for each VWAP line to differentiate them on the chart.
Enable Debug Mode if needed to verify time alignment.
Analyze price movements relative to the anchored VWAPs to identify support, resistance, or trend shifts.
Benefits
Ideal for swing traders and long-term analysts who need to anchor VWAP to significant price levels or events.
Enhances decision-making by comparing multiple VWAPs from different anchor points.
Fully compatible with TradingView’s Pine Script v6 for smooth performance.
This indicator is perfect for traders looking to deepen their market analysis with a flexible, multi-VWAP approach. Share your feedback or custom setups in the comments!
Quadro Volume Profile [BigBeluga]🔵 OVERVIEW
The Quadro Volume Profile is a precision-engineered volume profiling tool that segments market activity into four distinct quadrants surrounding the current price. By separating bullish and bearish volume above and below the current price, it helps traders identify dominant forces and high-interest price zones with ease. Each quadrant includes label annotations showing total volume and its share of overall activity — delivering powerful insights into the market’s internal structure.
🔵 CONCEPTS
Four-Quadrant Volume Distribution : Volume is separated into Buy and Sell profiles both above and below the current price.
Directional Volume Logic : Bullish and bearish candle volume is allocated to specific bins, creating color-coded volume stacks.
Dynamic PoC Detection : Point of Control (PoC) levels are calculated per quadrant and optionally displayed.
Lookback-Based Anchoring : The volume histogram is anchored to a fixed lookback window, ensuring consistency and historical context.
Label-Based Analytics : Each quadrant displays a labeled breakdown of direction, total volume, and percentage weight of total activity.
🔵 FEATURES
Four separate volume profiles:
Upper Left: Bearish volume (Sell Quad above price)
Upper Right: Bullish volume (Buy Quad above price)
Lower Left: Bullish volume (Buy Quad below price)
Lower Right: Bearish volume (Sell Quad below price)
Live Labels for Each Quad:
Displays BUY or SELL direction
Shows total volume per quadrant (e.g. 607.49K)
Displays percent share of total quad volume (e.g. 18.87%)
Toggle visibility for each profile and each Point of Control (PoC) dashed PoC lines with volume annotations
Adjustable calculation period (lookBack), number of bins, and horizontal offset
Color gradient intensity represents volume strength per bin
Auto-cleaning visuals to keep the chart uncluttered
Gradient color control for Buy and Sell volumes
Clean midline split between upper and lower quadrants
🔵 HOW TO USE
Select your desired calculation period (default: 200 bars) to define the range for volume analysis.
Adjust the bins parameter for more or less resolution in volume distribution.
Toggle each quadrant on/off depending on your preference using the settings panel:
“Upper Sell Quad” – shows bearish volume above current price (left)
“Upper Buy Quad” – shows bullish volume above current price (right)
“Lower Buy Quad” – shows bullish volume below current price (left)
“Lower Sell Quad” – shows bearish volume below current price (right)
Enable or disable PoC lines for each quad to highlight where volume peaked.
Use the gradient coloring to identify volume imbalances — sharp differences between opposing quads often indicate key zones of rejection or breakout.
Monitor the midline level which splits the four quadrants — it serves as a psychological pivot zone.
🔵 CONCLUSION
The Quadro Volume Profile offers a powerful and visually intuitive way to dissect market activity around price. By splitting volume into four quadrants, traders can better interpret order flow, identify dominant volume zones, and spot potential reversals or continuation setups. Whether you're trading breakouts, liquidity sweeps, or range-bound behavior — this tool adds a structured layer of volume context to your charting workflow.