Multi-Asset Arbitrage CalculatorMulti-Asset Arbitrage Calculator
📊 Overview
A comprehensive Pine Script indicator designed to identify and monitor arbitrage opportunities across multiple trading pairs in real-time. This tool calculates potential profit percentages from various transaction paths while accounting for trading fees and market inefficiencies.
🎯 Purpose
- Arbitrage Detection : Automatically identifies price discrepancies between related trading pairs
- Multi-Path Analysis : Supports up to 10 simultaneous arbitrage loops with different transaction sequences
- Fee Integration : Incorporates comprehensive fee structures for realistic profit calculations
- Real-Time Monitoring : Provides continuous monitoring with customizable alert thresholds
🚀 Key Features
Flexible Transaction Paths
- Triangular Arbitrage : A→B→C→A patterns for three-asset opportunities
- Direct Pairs : Simple A→B conversions
- Reverse Paths : Inverse transaction sequences
- Custom Routing : Multiple path options for diverse market scenarios
Comprehensive Fee Structure
- Start/End transaction fees
- Deposit/Withdrawal fees
- Inter-asset conversion fees
- Configurable percentage-based calculations
Professional Tools
- Moving Average Smoothing: Reduces noise with configurable MA periods
- Alert System : Individual and combined alert conditions
- Weekend Detection : Visual highlighting for market hours
- Clean Interface : Organized input groups for easy configuration
📋 Supported Transaction Types
1. `A→B→C→A` - Standard triangular arbitrage
2. `B→A→C→A` - Reverse entry triangular
3. `A→B→A→C` - Split conversion path
4. `A→C→B→A` - Alternative triangular route
5. `A→C→A→B` - Modified split path
6. `A→B` - Direct pair conversion
7. `A→B (Inverse)` - Inverse direct conversion
8. `B→A (Inverse)` - Reverse inverse conversion
🛠️ Configuration Options
General Settings
- Alert threshold percentage
- Moving average period
- Enable/disable individual loops
Per Loop Settings
- Transaction path selection
- Three symbol inputs (A, B, C)
- Six fee parameters (Start, Deposit, Step1, Step2, End, Withdraw)
- Individual on/off controls
📈 Use Cases
- Cross-Exchange Arbitrage : Identify price differences between exchanges
- Currency Triangulation : Find inefficiencies in forex/crypto triangular paths
- Fee Analysis : Understand the impact of trading costs on profitability
- Market Research : Study price relationships and correlations
⚙️ Technical Specifications
- Pine Script Version : v6
- Chart Type : Oscillator (overlay=false)
- Data Source : Real-time price feeds via TradingView
- Calculations : Percentage-based profit/loss with fee adjustments
- Alerts : TradingView alert system integration
📊 Visual Elements
- Clean Charts : Plots hidden by default for uncluttered interface
- Weekend Highlighting : Yellow background during market closures
- Color Coding : Distinct colors for each arbitrage loop
- MA Overlay : Optional moving average display
🔧 Installation & Setup
1. Add indicator to TradingView chart
2. Configure desired number of arbitrage loops
3. Set symbol pairs for each active loop
4. Adjust fee parameters based on your broker/exchange
5. Set alert threshold percentage
6. Enable alerts for desired loops
⚠️ Important Notes
- Real-time Data : Requires live market data for accurate calculations
- Fee Accuracy : Ensure fee parameters match your actual trading costs
- Market Hours : Consider exchange operating hours and liquidity
- Risk Management : This is an analysis tool, not investment advice
Indicadores y estrategias
Adjustable Day MarkersPlaces vertical dashed lines for each new day at midnight in light grey, so you have a visual reference on the chart rather than having to look at the time at the bottom.
To adjust it to your time zone: go to settings , then give a - or + value for " Timezone Offset ".
I'm at GMT+2, so I set it to 2 .
If you rather have the line appear at the beginning of your trading day, then that's also possible. Say I start every day at 8 AM, I would have to set it to +10 (since I'm currently GMT +2).
MajorTop DeltaVol ma5-52wThe idea is to identify major tops on the weekly when both are above 0 at the same time; to look just for mkt tops.
Major tops use to drag on for a little with increasing volatility before crashing.
green is 5-52sma
fuchsia 3-9sma
Sma are on the candle's range ratio on the close.
Global M2 Money SupplyThis indicator calculates and plots an aggregated estimate of the Global M2 money supply, expressed in U.S. dollar terms. It combines M2 data from major economies and regions—including the U.S., Eurozone, Canada, the U.K., Switzerland, China, Japan, India, Brazil, and others—and adjusts each by its respective FX rate to USD. By summing these series, the script provides a broad view of worldwide liquidity conditions in one line.
A user-defined offset in days allows you to shift the global M2 line forward or backward, making it easier to visually compare liquidity trends against asset prices such as Bitcoin, gold, or equities. This tool is designed for traders and macro observers who want to study how global money supply growth or contraction correlates with financial markets over time.
이 지표는 전 세계 주요 국가와 지역의 M2 통화량을 달러 기준으로 합산하여 글로벌 유동성 지표로 보여줍니다. 미국, 유로존, 캐나다, 영국, 스위스, 중국, 일본, 인도, 브라질 등 여러 지역의 M2 데이터를 각 통화의 환율(USD 환산)로 조정한 뒤 합산해 하나의 흐름으로 표현합니다. 이를 통해 글로벌 차원의 통화 공급 변화를 한눈에 파악할 수 있습니다.
또한 사용자가 지정한 일 단위 오프셋 기능을 통해 글로벌 M2 라인을 앞뒤로 이동시켜, 비트코인·금·주식 등 다양한 자산 가격과의 시차적 관계를 직관적으로 비교할 수 있습니다. 거시경제 환경과 자산시장 간의 상관성을 연구하거나 시장 유동성 추이를 모니터링하려는 투자자에게 유용한 도구입니다.
Multi-Timeframe MACD Score(Customized)this is a momentum based indicator to know the direction of the market
Gold Lagging (N days)This indicator overlays the price of gold (XAUUSD) on any chart with a customizable lag in days. You can choose the price source (open, high, low, close, hlc3, ohlc4), shift the series by a set number of daily bars, and optionally normalize the values so that the first visible bar equals 100. The original gold line can also be displayed alongside the lagged series for direct comparison.
It is especially useful for analyzing delayed correlations between gold and other assets, observing shifts in safe-haven demand, or testing hypotheses about lagging market reactions. Since the lag is calculated on daily data, it remains consistent even if applied on intraday charts, while the indicator itself can be plotted on a separate price scale for clarity.
이 지표는 금(XAUUSD) 가격을 원하는 차트 위에 N일 지연된 형태로 표시합니다. 가격 소스(시가, 고가, 저가, 종가, hlc3, ohlc4)를 선택할 수 있으며, 지정한 일 수만큼 시리즈를 뒤로 이동시킬 수 있습니다. 또한 첫 값 기준으로 100에 맞춰 정규화하거나, 원래 금 가격선을 함께 표시해 비교할 수도 있습니다.
금과 다른 자산 간의 지연 상관관계를 분석하거나 안전자산 수요 변화를 관찰할 때 유용하며, 시장 반응의 시차 효과를 검증하는 데에도 활용할 수 있습니다. 지연은 일봉 데이터 기준으로 계산되므로 단기 차트에 적용해도 일 단위 기준이 유지되며, 별도의 가격 스케일에 표시되어 가독성을 높일 수 있습니다.
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.
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,
CFR - Candle Formation RatioDescription
This indicator is designed to detect candles with small bodies and significant wick-to-body ratios, often useful for identifying doji-like structures and potential accumulation areas.
Features
Filter candles by maximum body size (% of the total candle range).
Require that wicks are at least X times larger than the body.
Define the position of the body within the candle (e.g., body must be between 40% and 60% of the candle height).
Visual output: a single arrow marker when conditions are met.
Fully customizable marker color and size.
⚠️ Note: The settings of this version are currently in Turkish. An English version of the settings will be released in the future.
Multi-Timeframe MACD Score(Customizable)this is a momentum based indicator to know the direction of the market
Double Top/Bottom Screener with ATR otential Issues in the Latest Script
Based on the code and your previous feedback, here are possible mistakes:
Syntax or Compilation Error:
The script might have a typo or incomplete logic, especially with the new nearestDoubleLevel and distanceNormalizedATR additions.
Check: The table definition in the if barstate.islast block has 4 columns defined but tries to access a 5th with table.cell(infoTable, 0, 4, ...), which causes an "index out of bounds" error. This is a clear mistake.
Distance or Level Calculation:
If "Dist: NaN%" or "Level: NaN" appears, it might indicate that doubleTopLevel or doubleBottomLevel isn’t being set correctly, possibly due to the tolerance or array logic.
Check: The ATR-normalized distance (distanceNormalizedATR) might fail if atr is na due to insufficient bars.
Screener Column Issue:
The new columns ("Nearest Double Level Price" and "Normalized Distance (ATR)") might not display or sort correctly in the Pine Screener due to plotting or naming conflicts.
Multi-Timeframe Sweep IndicatorsLiquidity Sweeps: Identify when price sweeps stops above/below key levels
Breakout Confirmation: Confirm breakouts across multiple timeframes
Entry Timing: Use lower timeframe sweeps for precise entries
Risk Management: Higher timeframe sweeps may indicate stronger moves
The indicator works best when combined with other analysis techniques like support/resistance levels, volume analysis, and market structure.
Previous Day Close LinesWhat does the script do?
--Draws a line on the current session from previous day close.
--Leaves previous day close lines behind, notice the reaction around them.
Guided Advisor with DXY ContextThis indicator will constantly will be looking for DXY direction in the background.
Opening Range TraderThis indicator, "Opening Range Trader," provides visual tools for defining and tracking two customizable intraday ranges plus today’s open, high, and low. It is designed for day traders to identify support, resistance, and breakout opportunities by automatically marking key price levels that often shape the day's momentum.
It offers:
Customizable start and end times for two independent time ranges.
Toggle options to display lines for the selected ranges and for today’s open, high, and low.
Automatic adaptation for New York market hours.
Real-time updates for session highs/lows and today’s evolving levels.
Traders use this to watch for breakouts above or below the opening range (ORB strategy), to fade false moves when price returns inside the range, or to participate in trending moves after volatility begins. A common setup is entering long on closes above the range high, or short on closes below the range low, with stops and targets based on the range’s width or the opposite boundary.
Risk management approaches include placing stop losses at the midpoint or at the opposite end of the range, and adjusting targets for measured moves. Volume confirmation can help filter valid breakouts, while adapting times for specific assets and trading styles maximizes flexibility.
The second range allows traders to repeat similar strategies later in the session for evolving momentum windows, making this indicator useful for multiple intraday setups.
Automatic Candle Date - BVKAutomatic Candle Date
It is related to automatic Date indicator , so you can fetch it
NY 14:30 High/Low - 1mThis indicator automatically draws horizontal lines for the High (green) and Low (red) of the 14:30 (Lisbon) candle on the 1-minute chart.
It is designed for traders who want to quickly identify the New York open levels (NY Open), allowing you to:
Visualize the NY market opening zone.
Use these levels as intraday support or resistance.
Plan entries and exits based on breakouts or pullbacks.
Features:
Works on any 1-minute chart.
Lines are drawn immediately after the 14:30 candle closes.
Lines extend automatically to the right.
Simple and lightweight, no complex variables or external dependencies.
Daily reset, always showing the current day’s levels.
Recommended Use:
Combine with support/resistance zones, order blocks, or fair value gaps.
Monitor price behavior during the NY open to identify breakout or rejection patterns.
BR Cross Swing - MACD HistRawThis strategy looks at the MACD Relationship through the same logic but mainly focuses on breaking things down and the application on raw values.
Daily ATR TrackerThis indicator calculates the daily ATR of the past 14 days. The ATR% indicates the range completed for the day. The ATR indicates the average daily range. The 20% ATR indicates the value of 20% of the daily ATR for retracement purposes.
Continuation Index [DCAUT]█ Continuation Index
📊 OVERVIEW
Continuation Index (CI) is an advanced trend analysis indicator developed by John F. Ehlers. This indicator provides early warning signals for trend onset, continuation, and exhaustion, with values oscillating between -1 and +1 to offer clear trend state identification for traders.
Based on the article TASC 2025.09 "Trend Onset And Trend Exhaustion - The Continuation Index" by John F. Ehlers.
💡 CORE VALUE
Unlike traditional trend indicators, the Continuation Index provides:
- Advanced dual-filter architecture (Ultimate Smoother + Laguerre Filter)
- Inverse Fisher Transform for enhanced signal-to-noise ratio
- Adaptive gamma parameter allowing market-specific tuning
- Binary state output (+1/-1) eliminating interpretation ambiguity
🎯 CONCEPTS
Signal Interpretation
CI > 0.5 : Strong bullish trend continuation - consider holding/adding long positions
CI = +1 : Maximum bullish signal - strong uptrend in progress
CI < -0.5 : Strong bearish trend continuation - consider holding/adding short positions
CI = -1 : Maximum bearish signal - strong downtrend in progress
CI near 0 : Neutral zone - trend uncertain, wait for clear signals
Brief pullbacks from extreme states : Potential reentry opportunities in trend direction
Primary Applications
Trend Onset Detection : Early warning signals for trend initiation
Trend Exhaustion Signals : Identify potential trend reversals
Position Management : Clear binary states for entry/exit decisions
Market Timing : Adaptive filtering reduces false signals
📋 PARAMETER SETUP
Source : Data source for calculation (default: close)
Length : The calculation length for the filters (default: 40, min: 1)
Gamma : Controls the phase response of the Laguerre filter. Smaller values increase responsiveness (default: 0.8, range: 0.0-1.0)
Laguerre Order : The order of the Laguerre filter, which directly affects its lag (default: 8, range: 1-10)
📊 COLOR CODING
Green : CI > 0.5 - Bullish trend continuation
Red : CI < -0.5 - Bearish trend continuation
Gray : Neutral zone - Trend unclear
Volume weighted Forex Overwiew True Strenght IndexAdding volume weighting to the FOTSI strategy improves its effectiveness by making the indicator more sensitive to periods of high market activity. Here’s how:
Market Relevance: Futures volume reflects institutional and large trader participation. When volume is high, price moves are more likely to be meaningful and less likely to be noise.
Dynamic Weighting: By multiplying each currency’s momentum by its normalized futures volume, the indicator gives more weight to currencies that are actively traded at that moment, making signals more robust.
Filtering Out Noise: Low-volume periods are down-weighted, reducing the impact of illiquid or less relevant price changes.
Better Timing: Signals generated during high-volume periods are more likely to coincide with real market moves, improving entry and exit timing.
RSI: alternative derivationMost traders accept the Relative Strength Index (RSI) as a standard tool for measuring momentum. But what if RSI is actually a position indicator?
This script introduces an alternative derivation of RSI, offering a fresh perspective on its true nature. Instead of relying on the traditional calculation of average gains and losses, this approach directly considers the price's position relative to its equilibrium (moving average), adjusted for volatility.
While the final value remains identical to the standard RSI, this alternative derivation offers a completely new understanding of the indicator.
Key components:
Price (Close)
Utilizes the closing price, consistent with the original RSI formula.
normalization factor
Transforms raw calculations into a fixed range between -1 and +1.
normalization_factor = 1 / (Length - 1)
EMA of Price
Applies Wilder’s Exponential Moving Average (EMA) to the price, serving as the anchor point for measuring price position, similar to the traditional RSI formula.
myEMA = ta.rma(close,Length)
EMA of close-to-close absolute changes (unit of volatility)
Adjusts for market differences by applying a Wilder’s EMA to absolute price changes (volatility), ensuring consistency across various assets.
CC_vol = ta.rma(math.abs(close - close ),Length)
Calculation Breakdown
DISTANCE:
Calculate the difference between the closing price and its Wilder's EMA. A positive value indicates the price is above the EMA; a negative value indicates it is below.
distance = close - myEMA
STANDARDIZED DISTANCE
Divide the distance by the unit of volatility to standardize the measurement across different markets.
S_distance = distance / CC_vol
NORMALIZED DISTANCE
Normalize the standardized distance using the normalization factor (n-1) to adjust for the lookback period.
N_distance = S_distance * normalization_factor
RSI
Finally, scale the normalized distance to fit within the standard RSI range of 0 to 100.
myRSI = 50 * (1 + N_distance)
The final equation:
RSI = 50 ×
What This Means for RSI
Same RSI Values, Different Interpretation
The standard RSI formula may obscure its true measurement, whereas this approach offers clarity.
RSI primarily indicates the price's position relative to its equilibrium, rather than directly measuring momentum.
RSI can still be used to analyze momentum, but in a more intuitive and well-informed way.
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)