Indicator

RSI Divergence Indicator RSI Divergence Indicator — Enhanced
An enhanced RSI indicator combining traditional RSI divergence detection with flexible smoothing and a dynamic trend-color system.
This indicator is designed to give traders a cleaner view of momentum, trend direction, and divergence in one RSI pane.
Key Features
Dynamic RSI Trend Coloring
The RSI can automatically change color based on the relationship between a fast and slow RSI:
🟢 Green — Fast RSI is above Slow RSI, indicating bullish momentum.
🔴 Red — Fast RSI is below Slow RSI, indicating bearish momentum.
The feature can be turned on or off from the Divergence settings.
The Fast RSI and Slow RSI lengths are fully adjustable, with defaults of 5 and 14.
RSI Smoothing
Choose from several smoothing methods for the RSI:
None
SMA
SMA + Bollinger Bands
EMA
SMMA (RMA)
WMA
VWMA
The smoothing length is fully adjustable.
RSI Bollinger Bands
When SMA + Bollinger Bands is selected, Bollinger Bands are automatically displayed around the smoothed RSI.
The BB Standard Deviation is adjustable, allowing traders to customize the band width.
Multiple RSI Levels
The indicator includes five important RSI reference levels:
70 — Overbought
60 — Bullish momentum zone
50 — Midline / neutral
40 — Bearish momentum zone
30 — Oversold
The 40 and 60 levels provide additional context for identifying momentum shifts before RSI reaches traditional overbought or oversold levels.
Regular Divergence
Detects traditional divergence between price and RSI:
Bullish Divergence
Price makes a Lower Low
RSI makes a Higher Low
Bearish Divergence
Price makes a Higher High
RSI makes a Lower High
Hidden Divergence
Also identifies hidden divergence:
Hidden Bullish
Price makes a Higher Low
RSI makes a Lower Low
Hidden Bearish
Price makes a Lower High
RSI makes a Higher High
Customizable Divergence Detection
The pivot lookback and divergence range settings allow traders to adjust how sensitive the divergence detection is.
Alerts
Alert conditions are included for:
Regular Bullish Divergence
Hidden Bullish Divergence
Regular Bearish Divergence
Hidden Bearish Divergence
Why Use This Indicator?
The goal of this indicator is to combine several useful RSI tools into one clean and customizable package.
Instead of relying on RSI alone, traders can use:
RSI + Dynamic Momentum Color + Smoothing + Bollinger Bands + 40/60 Momentum Levels + Regular Divergence + Hidden Divergence
This provides multiple ways to assess momentum and potential trend changes without requiring several separate indicators.
Suggested Starting Settings
For a balanced starting point:
RSI Period: 14
Smoothing: None
Fast RSI: 5
Slow RSI: 14
Overbought: 70
Bullish momentum: 60
Midline: 50
Bearish momentum: 40
Oversold: 30
These are simply starting points and can be adjusted depending on the market, timeframe, and trading style.
Important
This indicator is intended as a technical analysis tool and should not be considered financial advice. Divergences and momentum signals can fail, particularly during strong trends or volatile market conditions. Always combine indicator signals with your own analysis and risk management. Indicator

Indicator

Indicator

TRADLEWARE-Gaussian Channel + StochRSI BTC
TRADLEWARE - Gaussian Channel + Stochastic RSI
This strategy combines a Gaussian Channel with a Stochastic RSI filter to capture momentum continuation in trending markets on the daily timeframe.
How it works
The Gaussian Channel is a smoothed price envelope built with an IIR (infinite impulse response) filter — a mathematically elegant alternative to a simple moving average. Instead of weighting recent bars linearly, the Gaussian filter applies a bell-curve weighting that produces very smooth, low-lag output. The channel is formed by adding and subtracting a filtered measure of true range (volatility) around the central filter line.
The channel turns green when the filter is rising (uptrend) and red when it is falling (downtrend).
Entry
A long position is opened when all three conditions are true simultaneously:
The channel is green (filter rising — uptrend confirmed)
Price closes above the upper band (breakout above the channel)
Stochastic RSI %K is either above 80 (strong momentum confirming the breakout) or below 15 (oversold dip within the uptrend)
The dual Stochastic RSI threshold captures two different entry scenarios: a momentum breakout and a pullback-and-recover within an ongoing trend.
Exit
The position is closed when either:
Price closes back below the upper band (breakout has failed or the trend is cooling), or
The channel reverses from green to red (trend direction has flipped)
An optional stop-loss (on by default) is placed at the lower band and trails as the channel moves, providing a floor on losses if price drops sharply through both the upper and lower bands in the same move.
Parameters
Poles: 4 (filter smoothness — higher = smoother but more lag)
Sampling Period: 144 (slow channel, suited to daily trends)
True Range Multiplier: 1.414 (controls channel width)
Stochastic RSI overbought threshold: 80
Stochastic RSI oversold threshold: 15
Stop-loss at lower band: on by default, can be disabled
Start/End date range inputs let you restrict the backtest window without editing code
Costs modelled
0.1% commission per side, 3 ticks slippage, fills at next bar's open.
Intended assets and timeframe
Daily bars. Designed and validated on BTC/USDT. Likely applicable to other trending crypto assets; not validated on equities .
Known limitations
Underperforms in choppy or ranging markets — the upper band breakout condition generates whipsaws when price oscillates without directional conviction. The filter requires several hundred bars of history to fully converge; results on very short histories may differ from the validated backtest. The strategy trades infrequently (around 30 trades from 2018 to present on BTC/USDT), so treat any single backtest run as a small sample rather than a statistically strong result.
Credit
The Gaussian Channel filter is from the open-source "Gaussian Channel (DW)" indicator by DonovanWall. This script reuses that filter and adds the Stochastic RSI entry filter, exit rules, stop-loss, and full strategy order management on top of it.
Strategy

ATK/DEF HTF Analysis Combo# ATK/DEF HTF Analysis Combo
ATK/DEF HTF Analysis Combo is a Higher Timeframe market environment analysis framework designed to observe the broader market structure from a use-selected timeframe.
Instead of focusing only on the active chart, this indicator uses a selected Higher Timeframe as the primary reference environment and organizes several independent market measurements into one structured dashboard.
The objective is to provide a clearer view of the **broader market direction, trend condition, momentum condition, and volatility environment** through a Higher Timeframe perspective.
The indicator is designed as an analytical observation framework rather than a conventional single-condition indicator.
## 📊 Higher Timeframe Market Environment
The core of this indicator is the use of a use-selected Higher Timeframe.
The selected timeframe becomes the reference environment for the dashboard.
For example, the user may select:
* 4 Hour
* Daily
* Weekly
* Other supported timeframes
The indicator retrieves market data from the selected timeframe and evaluates the corresponding market conditions.
This allows the active chart to be viewed in the contet of a broader market environment.
A smaller chart can contain many local price movements while the selected Higher Timeframe may still maintin a different overall structure.
The purpose of this framework is to make that broader structure visible in a compact analytical format.
# 🧭 Four-Dimensional HTF Observation
ATK/DEF HTF Analysis Combo separates the Higher Timeframe environment into four primary dimensions:
**Direction**
**Trend**
**Momentum**
**Volatility**
These dimensions are intentionally treated as independent analytical modules.
They do not represent the same characteristic of the market.
A market can have a clear directional position while momentum is neutral.
A market can have strong trend strength while volatility is relatively low.
A market can experience elevated volatility while directional structure remains mixed.
By keeping these measurements separated, the dashboard preserves more information about the current Higher Timeframe environment.
# 🎯 1. HTF Direction
The HTF Direction module evaluates the directional position of the selected Higher Timeframe.
The calculation examines the relationship between:
* HTF closing price
* EMA 8
* EMA 21
* EMA 50
* +DI
* -DI
The relationship between price and multiple EMA levels provides the primary structural classification.
The +DI and -DI relationship is then used as an additional directional component.
The module classifies the environment into several states:
* 📈 Strong Bull
* 📈 Bullish
* ↗️ Mixed Bull
* ➡️ Neutral
* ↘️ Mixed Bear
* 📉 Bearish
* 📉 Strong Bear
A Direction Score ranging from **-100 to +100** is also displayed.
The score provides a normalized representation of the directional classification used by the module.
The Direction module is not intended to represent the entire market by itself.
It describes the directional position of the selected Higher Timeframe environment.
# 📈 2. HTF Trend
The HTF Trend module examines the strength and orientation of the broader trend structure.
It uses:
* ADX
* +DI
* -DI
ADX is used to describe the strength of the prevailing directional structure, while +DI and -DI provide the directional component.
The module produces several classifications:
* 🔥 Strong Bull
* 🔥 Strong Bear
* ⚡ Bull Trend
* ⚡ Bear Trend
* 🌊 Weak Trend
* 🌀 Range
This creates a distinction between **directional position** and **trend strength**.
The Direction module asks where the market is positioned.
The Trend module asks how strongly the directional structure is expressed.
These two measurements can therefore display different conditions at the same time.
# ⚡ 3. HTF Momentum
The HTF Momentum module uses RSI to describe the current momentum condition of the selected Higher Timeframe.
The RSI range is divided into multiple states:
* 🚀 Strong Up
* ⬆️ Accelerating
* ↗️ Bullish
* ➡️ Neutral
* ↘️ Bearish
* ⬇️ Declining
* 💀 Strong Down
The purpose of this classification is to provide a more detailed view of momentum rather than reducing the entire momentum condition to a simple positive or negative value.
The module also generates a normalized Momentum Score between **-100 and +100**.
Momentum is kept independent from Direction and Trend because these characteristics can behave differently within the same market environment.
# 📊 4. HTF Volatility
The HTF Volatility module measures the relative movement environment of the selected Higher Timeframe using ATR.
The current ATR is compared with its 50-period average:
**ATR Ratio = Current ATR / Average ATR**
The result is classified into:
* 🔥 Extreme
* ⚠️ High
* 📊 Elevated
* 📊 Normal
* 😴 Low
Volatility is treated as a **non-directional measurement**.
A high volatility condition does not represent an upward or downward direction.
It describes the relative magnitude of market movement compared with its reference volatility.
This distinction allows the dashboard to separate market activity from market direction.
# 🏆 5. HTF Composite Environment
The final HTF score combines the independent Direction, Trend and Momentum scores.
The three directional components are averaged into a normalized composite value.
The Volatility condition can then modify the composite value when volatility reaches elevated levels.
The resulting score is constrained to a range between:
**-100 and +100**
The composite value is intended to provide a compact representation of the broader Higher Timeframe environment.
It does not replace the individual modules.
Instead, it provides another layer of information that can be compared with the separate Direction, Trend, Momentum and Volatility readings.
# 🔬 Independent Module Architecture
One of the main characteristics of ATK/DEF HTF Analysis Combo is its independent-module architecture.
Rather than forcing all market conditions into one calculation from the beginning, each component is evaluated separately.
### Direction
Describes the broader directional position.
### Trend
Describes the strength and orientation of the trend structure.
### Momentum
Describes the current momentum condition.
### Volatility
Describes the relative magnitude of market movement.
### Composite Environment
Provides a consolidated numerical representation of the directional modules.
This architecture allows different market characteristics to remain visible instead of hing them inside one simplified reading.
# 🌐 Broader Market Observation
The indicator is designed specifically around the idea of observing the market from a broader timeframe perspective.
The active chart represents the immediate chart environment.
The selected Higher Timeframe represents the broader reference environment.
The dashboard connects these two perspectives by displaying the selected HTF conditions directly on the active chart.
This makes it possible to examine how the current chart exists within a larger market structure.
The indicator therefore focuses on **environmental context rather than individual candle interpretation**.
# 📐 Why Higher Timeframe Data Is Used
Higher Timeframe data can provide a different structural perspective from the active chart.
For example, price movement that appears highly directional on a smaller chart may exist inside a much broader range when viewed from a larger timeframe.
Likewise, a period of relatively quiet movement on the ative chart may occur while the broader timeframe maintns a clearly defined directional structure.
The purpose of the HTF framework is to expose this broader context through a consistent set of measurements.
# 🧩 Multiple Conditions Can Coexist
The dashboard does not require every module to produce the same classification.
Different combinations are possible.
For example:
**Bullish Direction + Weak Trend + Neutral Momentum + Low Volatility**
or:
**Mixed Direction + Strong Trend + Strong Momentum + High Volatility**
or:
**Neutral Direction + Range + Neutral Momentum + Normal Volatility**
These combinations represent different market environments.
The dashboard preserves these differences instead of reducing every situation to one basic directional label.
# 📊 Scoring System
Direction, Trend and Momentum use normalized scores to represent their respective classifications.
Directional scores use a range from **-100 to +100**.
The Volatility module uses a separate non-directional scale because volatility does not inherently describe upward or downward movement.
The Composite HTF Score is normalized to remain within **-100 to +100**.
The scores are mathematical representations of the conditions defined in the script.
They should be interpreted as descriptive measurements of the selected Higher Timeframe environment.
# ⚙️ User-Defined Timeframe Configuration
The Higher Timeframe reference is **user-configurable**.
Users are expected to select and configure the timeframe that they want the dashboard to analyze.
The indicator does not assume that one particular timeframe is appropriate for every chart or every market.
Changing the HTF Resolution changes the reference environment used by the dashboard.
This is an important part of the design because the indicator is intended to allow the user to determine which broader market context should be observed.
The selected timeframe should therefore be considered part of the user's analytical configuration.
# 🖥️ Dashboard
The dashboard provides a compact display of the five main analytical sections:
### 🎯 HTF Direction
Directional classification and normalized Direction Score.
### 📈 HTF Trend
Trend classification and ADX measurement.
### ⚡ HTF Momentum
Momentum classification and RSI measurement.
### 📊 HTF Volatility
Volatility classification and ATR Ratio.
### 🏆 HTF Final Environment
Composite Higher Timeframe score and overall environmental classification.
The selected HTF resolution is also displayed in the dashboard header.
The table can be positioned on either side of the chart according to the user's preference.
# 📏 Technical Components
The indicator uses established market-data calculations including:
* EMA 8
* EMA 21
* EMA 50
* RSI 14
* ADX 14
* +DI
* -DI
* ATR 14
* 50-period average ATR
These components are processed independently before being combined into the Higher Timeframe dashboard.
The purpose of the framework is not to introduce a single new mathematical measurement, but to organize several market characteristics into a unified Higher Timeframe observation structure.
# 🧠 Analytical Concept
ATK/DEF HTF Analysis Combo approaches market observation from a broader environmental perspective.
Instead of asking only whether price is moving upward or downward, the framework separates the market into several observable characteristics:
**Where is the market positioned?**
**How strong is the directional structure?**
**What is the current momentum condition?**
**How active is the market environment?**
**How do these independent conditions relate to one another?**
This creates a multi-dimensional representation of the selected Higher Timeframe environment.
---
# ⚠️ Important Information
ATK/DEF HTF Analysis Combo is an analytical and visualization tool based on market data and mattical calculations.
The classifications and scores are generated from the relationships defined in the scrt between price, EMA, DMI, ADX, RSI and ATR.
The displayed values represent the calculated state of the selected Higher Timeframe environment at the time of observation.
They are not intended to represent certainty, probability, guarantees, or future market outcomes.
The indicator does not provide finl advice, tre instructions, or recommendations, or capital-management guidance.
The purpose of this script is to provide a structured framework for observing the broader market environment through use-selected Higher Timeframe data.
User are responsible for selecting and configuring the timeframe parameters appropriate to their own analytical requirements.
Indicator

Price Action Squeeze Pro📊 Script Overview: PrAc Squeeze Pro (//@version=6)
⚙️ Core Inputs & MACD
🔢 Length Settings: 🎛️ 12 fast, 26 slow, 9 signal inputs
📈 Moving Averages: 🔄 Configurable between EMA and SMA types for both oscillator and signal lines
📉 Squeeze Pro & Volatility Channels
📊 Bollinger Bands: 📐 Length 20 with a standard deviation multiplier of 2.0
📉 Keltner Channels: 📏 Multiple levels (1.0, 1.5, 2.0 multipliers) providing high, mid, and low compression zones
🔴 Compression States:
🟢 No Squeeze: Volatility bands outside channels
⚫ Low Compression: First trigger tier
🔴 Mid Compression: Original squeeze tier
🟠 High Compression: Toughest compression tier
🌊 Momentum & Volume Delta MACD
📉 Price Action Oscillator: 📊 Linear regression momentum calculation plotted as columns (green/red)
🔊 Volume Delta MACD: 🔀 Multi-timeframe calculation utilizing buying vs. selling volume differentials
📐 Dynamic OB/OS: 📊 Automatically adjusts overbought/oversold boundaries via standard deviation lookbacks (100 length, 2.0 multiplier)
🚨 Alerts & Visual Plots
🔔 Triggers: Automated alerts for when a squeeze starts or fires, plus histogram directional shifts
📈 Visual Elements: 🎨 Columns for price action, circle markers for squeeze status, custom lines for MACD/Signal, and dynamic threshold lines Indicator

Indicator

Indicator

Indicator

Indicator

Advanced Trend Scanner & Screener by SPPATLEThe Advanced Trend Scanner & Screener by SPPATLE is a comprehensive PulseWire Pine Script v6 indicator engineered for swing traders, positional traders, and index analysts. It merges multi-timeframe forecasting, dynamic index/stock screening, volume-surge analytics, and an intelligent recommendation engine into a single clean layout.
Here is a detailed breakdown of its core components and architecture:
1. Dynamic Asset Detection (Stocks vs. Indices)
Smart Context Switching: The indicator automatically detects whether the active chart is an equity stock or an index (such as NIFTY, BANKNIFTY, or FINNIFTY) using symbol and type parsing.
Stock Screener Mode: When applied to a stock, the left-hand panel runs a pre-configured multi-symbol screener, sorting assets based on relative momentum and percentage change.
Index Mode: When applied to indices like Nifty or BankNifty, the left-hand panel seamlessly transitions into an Index Diagnostic View, displaying the active timeframe bias, structural status, and trend direction.
2. Multi-Timeframe Forecasting & POC Engine
Automated Trend Projections: It evaluates underlying momentum, buying/selling power, and volume expansion across multiple timeframes (15m, 1h, 4h, Daily, and Weekly) in the background.
Developing Volume POCs (Point of Control): It plots institutional liquidity and value areas across multiple lookback windows (1M, 3M, 6M, 1H, 4H, Daily, and Weekly) in a clean stepline visual format. Users can customize lookback length bars and individual toggle visibility directly from the settings menu.
3. Volume Surge & Volatility Confluence
ATR & Volume Integration: It tracks Average True Range expansion alongside a 50-day moving average volume baseline. When volume surges above historical norms while ATR expands, it triggers a high-conviction institutional participation alert.
Custom Visual Highlights: Automatically highlights exceptional volume candles with customizable vertical projection lines and distinct momentum candle body colors.
4. Intelligent Recommendation Engine
The master dashboard evaluates dozens of concurrent technical factors—including VWAP positioning, SuperTrend alignment, RSI momentum states, MACD crossovers, and volume expansions—to output a clear verdict at the base of the dashboard:
BUY: Strong bullish confluence across volume surge, institutional buying power, and structural indicators.
SELL: Dominant selling pressure, breakdown below key volume zones, and bearish momentum.
WAIT: Price consolidation phases characterized by low volume ranges awaiting breakout validation.
CAUTIOUS: Conflicting market signals requiring strict risk management parameters.
यह Advanced Trend Scanner & Screener by SPPATLE एक ऑल-इन-वन (All-in-One) प्रोफेशनल ट्रेडिंग इंडिकेटर है, जिसे विशेष रूप से स्विंग ट्रेडर्स, पोजीशनल ट्रेडर्स और इंडेक्स ट्रेडर्स की ज़रूरतों को ध्यान में रखकर डिज़ाइन किया गया है।
इस इंडिकेटर की मुख्य विशेषताएँ और कार्यप्रणाली निम्नलिखित हैं:
1. मुख्य विशेषताएँ और कंपोनेंट्स (Key Features)
मास्टर डैशबोर्ड (Master Dashboard): चार्ट के दाईं ओर नीचे (Bottom Right) एक विस्तृत डैशबोर्ड मिलता है जो वर्तमान टाइमफ़्रेम के आधार पर लाइव टेक्निकल पैरामीटर्स का विश्लेषण करता है। इसमें 200 EMA, RSI, MACD, VWAP, SuperTrend और 1M, 3M, 6M Developing Volume POCs शामिल हैं।
मल्टी-टाइमफ़्रेम फॉरकास्ट (Multi-Timeframe Forecast): 15m, 1h, 4h, Daily (1D) और Weekly (1W) टाइमफ़्रेम का ऑटोमैटिक ट्रेंड प्रेडिक्शन और उसके पीछे का कारण (Reason) दिखाता है।
डायनेमिक इंडेक्स & स्टॉक सपोर्ट: यदि आप चार्ट पर NIFTY या BANKNIFTY खोलते हैं, तो यह ऑटोमैटिक इंडेक्स मोड में आ जाता है; और यदि आप किसी स्टॉक (जैसे ABFRL) पर हैं, तो यह उसके अनुसार काम करता है।
वॉल्यूम और ATR आधारित 'Volume Surge': पिछले 50 दिनों के एवरेज वॉल्यूम/गतिविधि और ATR (Average True Range) के विस्तार के आधार पर यह पहचानता है कि ब्रेकआउट असली है या नहीं।
स्मार्ट रिकमेंडेशन (BUY / SELL / WAIT / CAUTIOUS): सभी टेक्निकल और वॉल्यूम संकेतकों का मिलान करके यह सबसे नीचे स्पष्ट सलाह देता है कि अभी ट्रेड में क्या करना चाहिए।
2. कस्टमाइज़ेशन सेटिंग्स (Customization Settings)
Show/Hide विकल्प: आप सेटिंग्स से स्क्रीनर टेबल, मास्टर डैशबोर्ड, मोमेंटम कैंडल्स और वॉल्यूम हाइलाइट लाइन्स को अपनी पसंद के अनुसार ऑन/ऑफ कर सकते हैं।
डेवलपिंग POCs (Developing POCs): 1H, 4H, Daily, Weekly और Monthly POCs को अलग-अलग शो/हाइड करने के साथ-साथ POC Lookback Candles के ज़रिए यह तय करने की सुविधा है कि पीछे की कितनी कैंडल्स से इसे ड्रा करना है।
लाइन थिकनेस और टेबल स्टाइल: हाई वॉल्यूम हाइलाइट लाइन्स की मोटाई (Thickness) बदलने और टेबल के टेक्स्ट साइज़ (Small, Normal, Large) को मैनेज करने का विकल्प भी उपलब्ध है। Indicator

OminousLine EMAs (13/21/55/200)
OminousLine EMAs (13/21/55/200)
OminousLine EMAs is a clean and customizable trend-following indicator that combines four Exponential Moving Averages — EMA 13, 21, 55, and 200 — in a single chart overlay.
The indicator is designed to provide a clear visual overview of short-, medium-, and long-term market trends while keeping the chart simple and easy to read.
EMA Structure
The four default moving averages represent different layers of market momentum:
EMA 13 — Fast-moving EMA for short-term price action and momentum.
EMA 21 — Short-term trend reference that provides a slightly smoother view of price movement.
EMA 55 — Intermediate trend indicator that helps filter short-term market noise.
EMA 200 — Long-term trend reference commonly used to evaluate the broader market direction.
Trend Alignment
The relationship between the four EMAs can help visualize the current market structure.
A bullish EMA alignment may occur when:
EMA 13 > EMA 21 > EMA 55 > EMA 200
When the averages are aligned and separating upward, it can indicate increasing bullish momentum.
A bearish EMA alignment may occur when:
EMA 13 < EMA 21 < EMA 55 < EMA 200
When the averages are aligned and separating downward, it can indicate increasing bearish momentum.
When the EMAs begin moving closer together, it may indicate consolidation or weakening directional momentum.
Dynamic Support & Resistance
Moving averages can also act as dynamic reference areas during trending markets.
Price reactions around the EMA 13, 21, 55, or 200 can provide additional context when analyzing pullbacks, trend continuation, or changes in market structure.
These areas should not be considered fixed support or resistance levels.
Customization
OminousLine EMAs is fully customizable.
For each EMA, users can independently adjust:
EMA length
Visibility
Line color
Line width
Default configuration:
EMA 13 — Orange
EMA 21 — Cyan
EMA 55 — Amber
EMA 200 — Purple
The default colors are designed to provide clear visual separation, particularly on dark chart backgrounds.
How to Use
OminousLine EMAs can be used to help analyze:
Short-, medium-, and long-term trend direction
Bullish and bearish EMA alignment
Changes in momentum
EMA crossovers
EMA compression and expansion
Price interaction with moving averages
Potential dynamic support and resistance areas
The indicator can be used across different markets and timeframes. Traders can customize the EMA periods and appearance to suit their own analysis and trading methodology.
Important Notice
OminousLine EMAs is a visual trend-analysis tool and does not automatically generate buy or sell signals.
EMA alignment, crossovers, and price interactions should not be interpreted as guaranteed trading opportunities. The indicator is intended to complement other forms of technical analysis, market structure analysis, and appropriate risk management.
For informational and educational purposes only. Not financial advice. Indicator

TT-Lorentzian## TT-Lorentzian — The Stock Lorentzian Classifier, Made Executable and Honest
Machine Learning: Lorentzian Classification by jdehorty is one of the most
popular indicators on PulseWire — and it is exactly that: an indicator.
It paints signals, but it can't hold a position, size an order, bracket a
trade, or fire a single alert that a bot can actually execute.
TT-Lorentzian is that classifier turned into a complete, automatable
strategy — with one strict rule we imposed on ourselves: DON'T TOUCH THE
BRAIN. The k-nearest-neighbors core with Lorentzian distance, the five
feature slots (RSI / WT / CCI / ADX), the kernel regression filter, the
volatility / regime / ADX filters, the published v2 defaults, even the
original oldest-bars neighbor pool — all of it runs verbatim through
jdehorty's own MLExtensions and KernelFunctions libraries (used under
MPL-2.0, full credit to the original author). If you know the original,
every input here will look familiar, because it is the original.
### Why publish an unmodified classifier?
Because this script has a second job: it is the CONTROL ARM of TensorTrader's
live A/B experiment. Our optimized fork, TT-Autotune, trades machine-evolved,
regime-switched parameters; TT-Lorentzian trades the stock defaults on the
same markets under the same execution shell. When we claim the optimizer adds
edge, this script is the baseline that claim is measured against — publicly,
not in a private spreadsheet. The companion indicator TT Backtest Compare
runs both engines side by side on any chart and shows you the equity curves,
Sortino, drawdown, and per-regime attribution of one against the other.
A control you can't trade isn't a control. So this one trades.
### What the strategy shell adds (the brain stays stock)
1 — REAL ORDERS, ONE ALERT
strategy.entry / strategy.close with machine-readable order comments
(open_long, open_short, close_long, close_short), fixed-USD position sizing
with your choice of base currency (USDT / USDC / USD), pyramiding locked to
1, and orders processed on bar close. One alert on this strategy carries
every entry and exit — no juggling four separate alert conditions.
2 — ATR RISK BRACKETS
Optional ATR-based stop-loss and take-profit (defaults: 14-period ATR,
2.0x SL / 3.0x TP), re-issued every bar against the live position's average
price. The original indicator has no concept of a stop; this shell does.
3 — REGIME AWARENESS (DISPLAY-ONLY, BY DESIGN)
The same six-state market-regime classifier that runs in TensorTrader's
Python engine and in TT-Autotune (ADX + linear-regression slope + ATR%, with
confirmation-bar and minimum-hold hysteresis) is embedded and shown as an
on-chart chip panel: which regime is live and how long it has held. But
every row reads CTRL — the control arm deliberately trades the same default
parameters in every regime. That is the whole point: when TT-Autotune swaps
champions per regime and this script doesn't, the difference you measure is
the optimization, nothing else.
4 — EVERYTHING YOU ALREADY LIKE
The original visuals are intact: bar-prediction labels with gradient
coloring, kernel regression estimate plot, buy/sell arrows, and jdehorty's
own trade-stats table. Table positions are pre-arranged so this script and
TT-Autotune can share one chart without overlapping panels.
### Automation via TensorTrader
The alert payload this strategy emits is understood natively by the
TensorTrader webhook bridge: create a free account at
tensortrader.agent-swarm.net, install the TensorTrader browser extension,
and it will create and manage the PulseWire alert for you — wiring the
webhook, keeping it enrolled and heartbeat-fresh, and routing the signals
to paper or live execution on your own exchange keys across the venues the
platform supports. Every venue starts in paper mode; going live is an
explicit opt-in.
And if the A/B data convinces you the evolved parameters earn their keep,
the same extension arms TT-Autotune with your market's Regime Sync Code —
the upgrade path is one click, and the receipts are on the chart first.
### Honesty section
This strategy trades the published stock defaults — the same defaults that
scored a NEGATIVE median walk-forward Sortino (−0.15, net of 5 bps fees +
2 bps slippage) across our 50-symbol × 3-timeframe optimizer sweep. We
publish it anyway, because that's what a baseline is. If it beats the
optimized arm on your market, you'll see that too — TT Backtest Compare
doesn't take sides. Backtests are not live results; past performance never
guarantees future returns. Trade small, trade paper first.
### Credits and license
Original Lorentzian Classification logic, feature engineering, kernel
functions, and default parameters © jdehorty, used under the Mozilla Public
License 2.0 — imported directly via his MLExtensions/2 and KernelFunctions/2
libraries. Strategy shell, ATR brackets, alert plumbing, regime chip panel,
and A/B instrumentation by TensorTrader.
---
## Categories and tags (publication notes, not part of the description)
PulseWire's publish dialog allows up to two categories plus free-form tags.
- Primary category: **Trend Analysis** — the Lorentzian k-NN + kernel
regression engine is a trend classifier, and it's the category where the
jdehorty original lives and its audience browses.
- Secondary category: **Statistics** — keeps all three scripts of the series
discoverable together and reflects the k-NN / control-arm framing.
Suggested tags: `machinelearning`, `lorentzian`, `knn`, `strategy`,
`automation`, `webhooks`, `atr`, `riskmanagement`, `regime`, `tensortrader`.
Other notes:
- Publish as a STRATEGY (it is `strategy()`), so the Strategy Tester tab
appears — expected, unlike the Compare indicator.
- House Rules: open-source fork of an open-source script must credit the
original and describe meaningful changes. The description credits jdehorty
explicitly and frames the changes accurately: execution shell added,
classifier core unmodified. Emphasizing "the brain is untouched" is both
the marketing hook and the compliance statement.
- The −0.15 median default Sortino figure is the same one verified 2026-08-07
for the TT-Autotune description (148 runs, admin-646…admin-793 sweep,
asof 2026-07-31). Keep the two descriptions in sync if that number is
regenerated.
- Cross-link the three publications in each description's comments after all
are live: Autotune (the optimized arm) ↔ TT-Lorentzian (the control) ↔
TT Backtest Compare (the referee).
Strategy

Indicator

FD Volume Intelligence v1.8FD Volume Intelligence is a compact volume-confirmation tool designed to help traders judge whether a price move is supported by meaningful market participation.
Instead of duplicating PulseWire’s native volume histogram, this indicator works as an intelligence layer alongside PulseWire’s built-in Volume indicator. It focuses on Relative Volume (RVOL), participation strength, candle-body quality, directional context, and confirmed alerts while keeping the price chart clean.
Core Features
Relative Volume (RVOL)
Compares current volume with its moving-average baseline:
RVOL = Current Volume ÷ Volume MA
Volume MA Length
Default: 20
Participation Classification
Dry: below 0.70×
Average: 0.70× – 1.19×
Confirm: 1.20× – 1.49×
Strong: 1.50× – 1.99×
Extreme: 2.00×+
Candle Body Quality
Measures the candle body as a percentage of its total high-low range. This helps distinguish strong directional participation from high-volume indecision.
Default minimum body quality: 55%
Directional Volume Context
Displays whether current participation is associated with bullish or bearish price action.
Compact 2-Column Dashboard
Shows:
Volume status
RVOL
Strength
Direction
Body Quality
Current Volume vs MA20
Threshold settings status
Color-Coded Interpretation
Green = confirmed / positive participation
Orange = caution / weak candle quality
Red = bearish context
= informational metrics
White = neutral/static information
Threshold Protection
The script automatically maintains the correct logical hierarchy:
Dry < Confirmation < Strong < Extreme
If a user enters conflicting threshold values, they are automatically normalized internally.
No-Volume Handling
Symbols without usable volume data are clearly identified instead of generating misleading RVOL readings.
Confirmed Alerts
Alerts default to confirmation on candle close to reduce intrabar signal changes. The dashboard itself remains realtime.
How to Use
FD Volume Intelligence is intended as a confirmation tool, not a standalone buy/sell system.
For example:
RVOL < 0.70× → weak participation
RVOL ≥ 1.20× → meaningful participation begins
RVOL ≥ 1.50× → strong participation
RVOL ≥ 2.00× → unusually high activity; evaluate for expansion, breakout, absorption, or climax
A high RVOL reading becomes more useful when it is accompanied by good candle-body quality and relevant price structure.
For example:
RVOL 1.60× + Strong Body + Bull Direction
provides stronger confirmation than:
RVOL 1.60× + Weak Body
because the second condition may indicate absorption, rejection, or indecision despite elevated volume.
Recommended Setup
Use this indicator together with PulseWire’s built-in Volume indicator.
Recommended built-in Volume settings:
MA Length: 20
Color based on previous close: ON
FD Volume Intelligence intentionally does not draw its own synthetic volume histogram. This keeps the indicator lightweight and avoids creating an additional pane or interfering with the price scale.
Alerts
Available alert conditions include:
Bullish Volume Confirmation
Bearish Volume Confirmation
Strong Bullish Participation
Strong Bearish Participation
Extreme Bullish Volume
Extreme Bearish Volume
By default, alert signals are confirmed at candle close.
Important
RVOL in this indicator uses a rolling Volume MA baseline. It is not a session-normalized or time-of-day Relative Volume calculation.
Volume should always be interpreted together with price action, market structure, liquidity, support/resistance, and the broader market context.
FD Volume Intelligence is a confirmation and analytical tool. It does not predict future price movement and should not be used as a standalone trading system. Indicator

Indicator

Indicator

Indicator

V6 ORB Retest NY Session// ORB Retest — NY Session (MNQ)
// Live companion to the walk-forward-validated strategy in orb_retest.py.
//
// Draws and alerts only. It never places an order.
//
// DESIGNED FOR A 5-MINUTE CHART. The strategy was validated on 5-minute bars;
// on any other timeframe the breakout/retest granularity differs from what was
// tested, so the panel shows a warning.
//
// Session times are pinned to America/New_York, so the 9:30 ET open is located
// correctly no matter what timezone your chart displays, and DST is handled
// automatically. No chart timezone change needed.
//
// Install: PulseWire -> Pine Editor -> paste -> Save -> Add to chart.
//@version=6
indicator("ORB Retest — NY Session", "ORB Retest", overlay = true,
max_boxes_count = 500, max_lines_count = 500, max_labels_count = 500)
// ───────────────────────── Inputs ─────────────────────────
grpS = "Session (always New York time)"
orSessionInput = input.session("0930-0945", "Opening range window", group = grpS, display = display.none)
tradeSessionInput = input.session("0930-1555", "Trading session (flat at end)", group = grpS, display = display.none)
cutoffInput = input.session("0930-1200", "Breakout must occur before", group = grpS, display = display.none)
grpR = "Trade rules"
targetR = input.float(2.5, "Target (multiple of risk)", minval = 0.5, step = 0.5, group = grpR,
tooltip = "2.5R tested best across both 2019-2026 and 2023-onward: target is hit on 48% of trades vs 38% at 3R, win rate 58% vs 52%, slightly more total profit and a smaller drawdown.",
display = display.none)
stopBufTicks = input.int(4, "Stop buffer beyond retest extreme (ticks)", minval = 0, group = grpR, display = display.none)
touchTolTicks = input.int(2, "Retest touch tolerance (ticks)", minval = 0, group = grpR, display = display.none)
invalTicks = input.int(4, "Invalidation buffer past level (ticks)", minval = 0, group = grpR, display = display.none)
retestDeadlineM = input.int(60, "Cancel if no retest within (minutes)", minval = 5, group = grpR, display = display.none)
maxRiskPts = input.float(0, "Skip if risk exceeds (points, 0 = no limit)", minval = 0, group = grpR,
tooltip = "Off by default. On a 5-minute chart a 40-point cap improved results (+0.72R to +0.80R, drawdown roughly halved). On a 15-minute chart stops are naturally wider and the same cap removes too many good trades, so leave it at 0 there.",
display = display.none)
grpF = "Day filter"
useRangeFilter = input.bool(true, "Skip days with unusual opening-range width", group = grpF, display = display.none)
rangeLookback = input.int(20, "Lookback (days)", minval = 5, group = grpF, display = display.none)
rangeMinMult = input.float(0.5, "Minimum multiple of average", step = 0.1, group = grpF, display = display.none)
rangeMaxMult = input.float(2.0, "Maximum multiple of average", step = 0.1, group = grpF, display = display.none)
grpV = "Display"
drawSessionInput = input.session("0930-1230", "Extend drawings during (NY time)", group = grpV,
tooltip = "Boxes and lines grow only inside this window, then freeze. Default = first 3 hours of the NY session, so old days stay compact.",
display = display.none)
keepDays = input.int(120, "Keep drawings for last N days", minval = 1, maxval = 250, group = grpV,
tooltip = "PulseWire caps an indicator at 500 drawings per type; at 4 lines per traded day that is roughly 125 days of full markup. Beyond the cap the oldest drawings drop off automatically.",
display = display.none)
pointValue = input.float(2.0, "Contract $ per point (MNQ = 2)", minval = 0.01, group = grpV, display = display.none)
showPanel = input.bool(true, "Show status panel", group = grpV, display = display.none)
showBox = input.bool(true, "Opening range box", group = grpV, display = display.none)
showLevels = input.bool(true, "Entry / stop / target lines", group = grpV, display = display.none)
showMarkers = input.bool(true, "Signal markers", group = grpV, display = display.none)
showLabels = input.bool(true, "Outcome labels", group = grpV, display = display.none)
showLegend = input.bool(true, "Show symbol legend (bottom-left)", group = grpV, display = display.none)
TZ = "America/New_York"
// ───────────────────── Session detection ─────────────────────
inOR = not na(time(timeframe.period, orSessionInput, TZ))
inTrade = not na(time(timeframe.period, tradeSessionInput, TZ))
beforeCut = not na(time(timeframe.period, cutoffInput, TZ))
inDraw = not na(time(timeframe.period, drawSessionInput, TZ))
orStart = inOR and not inOR
orEnd = not inOR and inOR
tradeEnd = not inTrade and inTrade
tick = syminfo.mintick
isFiveMin = timeframe.isminutes and timeframe.multiplier == 5
// Live-chart safety: every decision waits for the bar to CLOSE, exactly like
// the backtest. On the streaming realtime bar nothing updates until it
// confirms, so signals never appear and then vanish mid-bar (no repainting).
confirmed = barstate.isconfirmed
// ───────────────────────── State ─────────────────────────
// 0 = waiting for breakout, 1 = waiting for retest, 2 = in trade, 3 = done today
var int state = 0
var int armedDir = 0
var int armTime = na
var float orH = na
var float orL = na
var float orRange = na
var bool orReady = false
var bool dayEligible = false
var float retestExtreme = na
var float entryPrice = na
var float stopPrice = na
var float targetPrice = na
var float riskPts = na
var string outcome = "—"
var array orHistory = array.new_float()
// Drawing handles for the current day
var box orBox = na
var line levelLine = na
var line entryLine = na
var line stopLine = na
var line targetLine = na
// Rolling registry so old days' drawings get cleaned up instead of piling up.
var array boxReg = array.new()
var array lineReg = array.new()
var array labelReg = array.new()
// Signal flags at global scope so plotshape / alertcondition can read them.
bool sigBreakout = false
bool sigEntry = false
bool sigInvalidated = false
bool sigExpired = false
bool sigTargetHit = false
bool sigStopHit = false
// ───────────── Build the opening range, reset for a new day ─────────────
if orStart and confirmed
orH := high
orL := low
orReady := false
state := 0
armedDir := 0
dayEligible := false
retestExtreme := na
entryPrice := na
stopPrice := na
targetPrice := na
riskPts := na
outcome := "—"
levelLine := na
entryLine := na
stopLine := na
targetLine := na
else if inOR and confirmed
orH := math.max(orH, high)
orL := math.min(orL, low)
if orEnd and confirmed
orRange := orH - orL
orReady := true
// Compare today's range against the trailing average BEFORE adding it.
// Starts judging after 5 days of history (averaging what it has, up to the
// full lookback) — demanding all 20 up front left short-history charts,
// like 5-minute ones, permanently stuck in "filtered out".
int warmup = math.min(rangeLookback, 5)
float avgRange = array.size(orHistory) >= warmup ? array.avg(orHistory) : na
dayEligible := not useRangeFilter or (not na(avgRange)
and orRange >= avgRange * rangeMinMult
and orRange <= avgRange * rangeMaxMult)
array.push(orHistory, orRange)
if array.size(orHistory) > rangeLookback
array.shift(orHistory)
if not dayEligible
outcome := na(avgRange) and useRangeFilter ? "warming up — collecting history" : "day filtered out"
if showBox
orBox := box.new(bar_index - 1, orH, bar_index, orL,
border_color = dayEligible ? color.new(color.orange, 20) : color.new(color.gray, 65),
border_style = line.style_dashed, border_width = 1,
bgcolor = dayEligible ? color.new(color.orange, 90) : color.new(color.gray, 96))
array.push(boxReg, orBox)
if array.size(boxReg) > keepDays
box.delete(array.shift(boxReg))
// Stretch the box only inside the drawing window, then freeze it.
if showBox and inDraw and orReady and not na(orBox)
box.set_right(orBox, bar_index)
// ───────────────────── State machine ─────────────────────
if orReady and inTrade and dayEligible and confirmed
// ---- Waiting for a breakout CLOSE (wicks do not count) ----
if state == 0 and beforeCut
if close > orH
armedDir := 1
state := 1
armTime := time
retestExtreme := low
sigBreakout := true
outcome := "armed long — waiting for retest"
else if close < orL
armedDir := -1
state := 1
armTime := time
retestExtreme := high
sigBreakout := true
outcome := "armed short — waiting for retest"
if sigBreakout and showLevels
float lvl = armedDir == 1 ? orH : orL
levelLine := line.new(bar_index, lvl, bar_index, lvl,
color = color.orange, width = 2)
array.push(lineReg, levelLine)
// ---- Armed: waiting for price to come back and retest the level ----
else if state == 1
bool isLong = armedDir == 1
float lvl = isLong ? orH : orL
float invalLevel = isLong ? lvl - invalTicks * tick : lvl + invalTicks * tick
bool invalidated = isLong ? close < invalLevel : close > invalLevel
bool expired = (time - armTime) / 60000 > retestDeadlineM or not beforeCut
if invalidated
state := 3
sigInvalidated := true
outcome := "invalidated — closed back inside"
if not na(levelLine)
line.set_color(levelLine, color.new(color.gray, 40))
else if expired
state := 3
sigExpired := true
outcome := "no retest — expired"
if not na(levelLine)
line.set_color(levelLine, color.new(color.gray, 40))
else
// Track how far the pullback has run — this defines the stop.
retestExtreme := isLong ? math.min(retestExtreme, low) : math.max(retestExtreme, high)
float tol = touchTolTicks * tick
bool touched = isLong ? low <= lvl + tol : high >= lvl - tol
bool pierced = isLong ? low <= lvl - tick : high >= lvl + tick
if touched and pierced
float eP = lvl
float sP = isLong ? retestExtreme - stopBufTicks * tick
: retestExtreme + stopBufTicks * tick
float rk = isLong ? eP - sP : sP - eP
if rk > 0 and (maxRiskPts == 0 or rk <= maxRiskPts)
entryPrice := eP
stopPrice := sP
riskPts := rk
targetPrice := isLong ? eP + targetR * rk : eP - targetR * rk
state := 2
sigEntry := true
outcome := (isLong ? "LONG live" : "SHORT live")
if showLevels
entryLine := line.new(bar_index, entryPrice, bar_index, entryPrice,
color = color.blue, width = 2)
stopLine := line.new(bar_index, stopPrice, bar_index, stopPrice,
color = color.red, width = 1, style = line.style_dashed)
targetLine := line.new(bar_index, targetPrice, bar_index, targetPrice,
color = color.green, width = 1, style = line.style_dashed)
array.push(lineReg, entryLine)
array.push(lineReg, stopLine)
array.push(lineReg, targetLine)
if showLabels
label lb = label.new(bar_index, isLong ? low : high,
(isLong ? "LONG " : "SHORT ")
+ str.tostring(rk, format.mintick) + " pts ($"
+ str.tostring(rk * pointValue, "#.##") + ")",
yloc = isLong ? yloc.belowbar : yloc.abovebar,
style = isLong ? label.style_label_up : label.style_label_down,
size = size.small,
color = isLong ? color.new(color.green, 20) : color.new(color.red, 20),
textcolor = color.white)
array.push(labelReg, lb)
else
state := 3
outcome := rk <= 0 ? "skipped — no risk defined" : "skipped — risk too wide"
// ---- In the trade: stop or target first? ----
else if state == 2
bool isLong = armedDir == 1
bool hitStop = isLong ? low <= stopPrice : high >= stopPrice
bool hitTarget = isLong ? high >= targetPrice : low <= targetPrice
// If one bar spans both, assume the stop filled first (matches the backtest).
if hitStop
state := 3
sigStopHit := true
outcome := "stopped out (−1R)"
else if hitTarget
state := 3
sigTargetHit := true
outcome := "target hit (+" + str.tostring(targetR, "#.#") + "R)"
// Grow active lines only inside the drawing window (no infinite extend,
// and old days stay frozen at their 3-hour width).
if inDraw
if state == 1 and not na(levelLine)
line.set_x2(levelLine, bar_index)
if state == 2
if not na(entryLine)
line.set_x2(entryLine, bar_index)
if not na(stopLine)
line.set_x2(stopLine, bar_index)
if not na(targetLine)
line.set_x2(targetLine, bar_index)
// ---- Session over: anything still open is flattened ----
if tradeEnd and state == 2 and confirmed
state := 3
outcome := "flat — session end"
if showLabels
label lb2 = label.new(bar_index, close, "flat — session end", yloc = yloc.abovebar,
style = label.style_label_down, size = size.tiny,
color = color.new(color.gray, 35), textcolor = color.white)
array.push(labelReg, lb2)
// ---- Prune old drawings so the chart doesn't fill up ----
if array.size(lineReg) > keepDays * 4
line.delete(array.shift(lineReg))
if array.size(labelReg) > keepDays * 2
label.delete(array.shift(labelReg))
// ───────────────────────── Plots ─────────────────────────
plotshape(showMarkers and sigBreakout, "Breakout close", shape.triangleup,
location.belowbar, color.new(color.orange, 0), size = size.tiny, display = display.pane)
plotshape(showMarkers and sigEntry and armedDir == 1, "Long entry", shape.labelup,
location.belowbar, color.new(color.green, 0), text = "E", textcolor = color.white,
size = size.small, display = display.pane)
plotshape(showMarkers and sigEntry and armedDir == -1, "Short entry", shape.labeldown,
location.abovebar, color.new(color.red, 0), text = "E", textcolor = color.white,
size = size.small, display = display.pane)
plotshape(showMarkers and sigTargetHit, "Target hit", shape.xcross,
location.abovebar, color.new(color.green, 0), size = size.tiny, display = display.pane)
plotshape(showMarkers and sigStopHit, "Stop hit", shape.xcross,
location.belowbar, color.new(color.red, 0), size = size.tiny, display = display.pane)
plotshape(showMarkers and sigInvalidated, "Setup invalidated", shape.circle,
location.abovebar, color.new(color.gray, 25), size = size.tiny, display = display.pane)
plotshape(showMarkers and sigExpired, "No retest — expired", shape.square,
location.abovebar, color.new(color.gray, 25), size = size.tiny, display = display.pane)
// ───────────────────────── Status panel ─────────────────────────
var table panel = table.new(position.top_right, 2, 7,
border_width = 1, border_color = color.new(color.gray, 60),
frame_width = 1, frame_color = color.new(color.gray, 60))
if showPanel and barstate.islast
color hdrBg = color.new(color.gray, 85)
color cellBg = color.new(color.gray, 92)
table.cell(panel, 0, 0, "ORB Retest", text_size = size.small, text_color = color.gray,
bgcolor = hdrBg, text_halign = text.align_left)
table.cell(panel, 1, 0, isFiveMin ? "5m ✓" : "⚠ tested on 5m",
text_size = size.small, bgcolor = hdrBg,
text_color = isFiveMin ? color.green : color.orange, text_halign = text.align_right)
table.cell(panel, 0, 1, "Status", text_size = size.small, text_color = color.gray,
bgcolor = cellBg, text_halign = text.align_left)
table.cell(panel, 1, 1, outcome, text_size = size.small, bgcolor = cellBg,
text_color = state == 2 ? color.blue : color.gray, text_halign = text.align_right)
table.cell(panel, 0, 2, "Range high", text_size = size.small, text_color = color.gray,
bgcolor = cellBg, text_halign = text.align_left)
table.cell(panel, 1, 2, na(orH) ? "—" : str.tostring(orH, format.mintick),
text_size = size.small, bgcolor = cellBg, text_color = color.orange,
text_halign = text.align_right)
table.cell(panel, 0, 3, "Range low", text_size = size.small, text_color = color.gray,
bgcolor = cellBg, text_halign = text.align_left)
table.cell(panel, 1, 3, na(orL) ? "—" : str.tostring(orL, format.mintick),
text_size = size.small, bgcolor = cellBg, text_color = color.orange,
text_halign = text.align_right)
table.cell(panel, 0, 4, "Range width", text_size = size.small, text_color = color.gray,
bgcolor = cellBg, text_halign = text.align_left)
table.cell(panel, 1, 4, na(orRange) ? "—" : str.tostring(orRange, "#.##") + " pts",
text_size = size.small, bgcolor = cellBg, text_color = color.gray,
text_halign = text.align_right)
table.cell(panel, 0, 5, "Entry / Stop", text_size = size.small, text_color = color.gray,
bgcolor = cellBg, text_halign = text.align_left)
table.cell(panel, 1, 5, na(entryPrice) ? "—"
: str.tostring(entryPrice, format.mintick) + " / " + str.tostring(stopPrice, format.mintick),
text_size = size.small, bgcolor = cellBg, text_color = color.gray,
text_halign = text.align_right)
table.cell(panel, 0, 6, "Risk", text_size = size.small, text_color = color.gray,
bgcolor = cellBg, text_halign = text.align_left)
table.cell(panel, 1, 6, na(riskPts) ? "—"
: str.tostring(riskPts, "#.##") + " pts $" + str.tostring(riskPts * pointValue, "#.##"),
text_size = size.small, bgcolor = cellBg, text_color = color.red,
text_halign = text.align_right)
// ───────────────────────── Symbol legend ─────────────────────────
var table legend = table.new(position.bottom_left, 4, 7,
border_width = 1, border_color = color.new(color.gray, 70),
frame_width = 1, frame_color = color.new(color.gray, 70))
if showLegend and barstate.islast
color lgBg = color.new(color.gray, 94)
color lgTxt = color.new(color.gray, 15)
table.cell(legend, 0, 0, "SYMBOL GUIDE", text_size = size.tiny, text_color = color.gray,
bgcolor = color.new(color.gray, 88), text_halign = text.align_left)
table.merge_cells(legend, 0, 0, 3, 0)
// column 0-1: setup phase column 2-3: trade phase
table.cell(legend, 0, 1, "▭", text_size = size.small, text_color = color.orange, bgcolor = lgBg)
table.cell(legend, 1, 1, "opening range 9:30–9:45", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
table.cell(legend, 2, 1, "▬", text_size = size.small, text_color = color.blue, bgcolor = lgBg)
table.cell(legend, 3, 1, "entry price", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
table.cell(legend, 0, 2, "▭", text_size = size.small, text_color = color.gray, bgcolor = lgBg)
table.cell(legend, 1, 2, "day skipped (range filter)", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
table.cell(legend, 2, 2, "╌", text_size = size.small, text_color = color.red, bgcolor = lgBg)
table.cell(legend, 3, 2, "stop loss", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
table.cell(legend, 0, 3, "▲", text_size = size.small, text_color = color.orange, bgcolor = lgBg)
table.cell(legend, 1, 3, "breakout close — wait for retest", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
table.cell(legend, 2, 3, "╌", text_size = size.small, text_color = color.green, bgcolor = lgBg)
table.cell(legend, 3, 3, "take profit (3R)", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
table.cell(legend, 0, 4, "▬", text_size = size.small, text_color = color.orange, bgcolor = lgBg)
table.cell(legend, 1, 4, "retest level = your entry", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
table.cell(legend, 2, 4, "✕", text_size = size.small, text_color = color.green, bgcolor = lgBg)
table.cell(legend, 3, 4, "target hit (win)", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
table.cell(legend, 0, 5, "E", text_size = size.small, text_color = color.green, bgcolor = lgBg)
table.cell(legend, 1, 5, "long entry filled", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
table.cell(legend, 2, 5, "✕", text_size = size.small, text_color = color.red, bgcolor = lgBg)
table.cell(legend, 3, 5, "stop hit (−1R)", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
table.cell(legend, 0, 6, "E", text_size = size.small, text_color = color.red, bgcolor = lgBg)
table.cell(legend, 1, 6, "short entry filled", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
table.cell(legend, 2, 6, "● ■", text_size = size.small, text_color = color.gray, bgcolor = lgBg)
table.cell(legend, 3, 6, "invalidated / no retest — no trade", text_size = size.tiny, text_color = lgTxt, bgcolor = lgBg, text_halign = text.align_left)
// ───────────────────────── Alerts ─────────────────────────
alertcondition(sigBreakout, "ORB: breakout close", "Opening range broken on the close — watch for a retest")
alertcondition(sigEntry, "ORB: retest entry", "Retest reached — entry level touched")
alertcondition(sigTargetHit, "ORB: target hit", "Target reached")
alertcondition(sigStopHit, "ORB: stop hit", "Stop hit")
alertcondition(sigInvalidated, "ORB: setup invalid", "Price closed back inside the range — setup dead")
alertcondition(sigExpired, "ORB: no retest", "Retest window expired — no trade today") Indicator

Northern Algo - Stacked B/S VolumeOverview
Northern Algo - Stacked Buy/Sell Volume Estimate is a volume-panel indicator that divides each chart bar’s reported volume into estimated buy and sell portions. Both portions are displayed together as one stacked column, allowing total volume, estimated directional composition, and relative buy-volume intensity to be viewed in the same panel.
How the volume split is calculated
The indicator estimates the division of volume from the closing price’s position within each candle’s high-low range:
Close position = (close - low) / (high - low)
Estimated buy volume = total volume x close position
Estimated sell volume = total volume - estimated buy volume
The close-position value is constrained between zero and one. Within this model, a candle closing near its high receives a larger estimated buy-volume portion, while a candle closing near its low receives a larger estimated sell-volume portion. A close near the middle of the range produces a more balanced division.
This is a candle-based estimate. It is not a measurement of exchange-level bid/ask volume, trade aggressor volume, order flow, or the actual number of transactions initiated by buyers and sellers.
Stacked-volume display
Each column contains two segments:
* The lower teal segment represents estimated buy volume.
* The upper red segment represents estimated sell volume.
* The combined height of both segments equals the bar’s total reported volume.
An optional moving average is plotted across the stacked columns. Its default length is 20 bars and it is calculated from total volume rather than either estimated segment. This provides a reference for comparing the current bar’s overall activity with its recent average.
Seller-adjusted buy-volume scale
The optional volume-intensity color scale evaluates estimated buy volume relative to its recent history.
First, the current estimated buy volume is divided by the average estimated buy volume from previous bars. The script performs a separate relative-volume calculation for estimated sell volume. A configurable portion of that sell-volume measurement is then subtracted from the buy-volume measurement:
Adjusted buy relative volume = buy relative volume - (sell relative volume x counter-pressure weight)
The result cannot fall below zero. It is mapped through 18 intensity levels, with progressively darker teal shades representing greater estimated buy-volume expansion after accounting for elevated estimated sell volume.
This seller-adjusted scale is the indicator’s distinguishing feature. It helps separate bars where the buy-volume estimate is expanding with limited opposing pressure from bars where both estimated portions are elevated because total volume has increased.
Using the indicator
The indicator can be used to examine three related characteristics:
* Total activity: Compare the complete column height with surrounding bars and the total-volume average.
* Estimated composition: Compare the relative size of the teal and red portions within each column.
* Relative intensity: When the color scale is enabled, compare the teal shading across bars to identify changes in seller-adjusted estimated buy-volume intensity.
The calculations are performed independently on the active chart timeframe. Shorter lookbacks respond more quickly to recent volume changes, while longer lookbacks provide a smoother comparison. Increasing the counter-pressure weight causes elevated estimated sell volume to have a greater effect on the buy-volume color scale. Setting the weight to zero disables this adjustment.
Settings
* Use V Color Scale: Enables or disables the seller-adjusted buy-volume intensity scale.
* Buy RVOL Lookback Bars: Sets the number of previous bars used to calculate average estimated buy volume.
* Sell Counter-Pressure Lookback Bars: Sets the number of previous bars used to calculate average estimated sell volume.
* Sell Counter-Pressure Weight: Controls how strongly estimated sell relative volume reduces the buy-volume intensity measurement.
* Show Total Volume Average: Shows or hides the moving average of total volume.
* Total Volume Average Length: Controls the moving-average period.
* Buy, Sell, and Volume Average Colors: Customize the panel’s standard display colors.
Important limitations
The displayed buy and sell portions are estimates derived entirely from OHLCV candle data. A larger estimated buy portion does not prove that buyers initiated that proportion of the bar’s transactions, and a larger estimated sell portion does not prove that sellers initiated that proportion.
The model is less informative on candles with very small ranges. On a zero-range candle, the current calculation assigns the displayed volume to the estimated sell segment.
Results depend on the volume data supplied for the selected symbol, exchange, data feed, and chart timeframe. The script does not request lower-timeframe trade data or use future data. Values on an open realtime candle will continue changing as its high, low, close, and volume develop.
This indicator does not generate trade signals, predict future price movement, or provide a complete trading system. It is intended as a contextual volume-visualization and educational tool.
Indicator

Indicator

2.0- Killzones EUR/GBP - Manuel De Jesus Leiva// This source code is subject to the terms of the Mozilla Public License 2.0 at mozilla.org
// © tradeforopp
//@version=6
indicator("Killzones EUR/GBP - Manuel De Jesus Leiva", "Killzones EUR/GBP - Manuel De Jesus Leiva", true, max_labels_count = 500, max_lines_count = 500, max_boxes_count = 500)
// ---------------------------------------- Constant Functions --------------------------------------------------
get_line_type(_style) =>
switch _style
"Solid" => line.style_solid
"Dotted" => line.style_dotted
"Dashed" => line.style_dashed
get_size(x) =>
switch x
"Auto" => size.auto
"Tiny" => size.tiny
"Small" => size.small
"Normal" => size.normal
"Large" => size.large
"Huge" => size.huge
get_table_pos(pos) =>
switch pos
"Bottom Center" => position.bottom_center
"Bottom Left" => position.bottom_left
"Bottom Right" => position.bottom_right
"Middle Center" => position.middle_center
"Middle Left" => position.middle_left
"Middle Right" => position.middle_right
"Top Center" => position.top_center
"Top Left" => position.top_left
"Top Right" => position.top_right
// ---------------------------------------- Constant Functions --------------------------------------------------
// ---------------------------------------- Inputs --------------------------------------------------
var g_SETTINGS = "Settings"
max_days = input.int(1000, "Session Drawing Limit", 1, tooltip = "Only this many drawings will be kept on the chart, for each selected drawing type (killzone boxes, pivot lines, open lines, etc.). Set to 200 for ~6 months of sessions.", group = g_SETTINGS)
tf_limit = input.timeframe("60", "Timeframe Limit", tooltip = "Drawings will not appear on timeframes greater than or equal to this", group = g_SETTINGS)
gmt_tz = input.string('America/New_York', "Timezone", options = , tooltip = "Note GMT is not adjusted to reflect Daylight Saving Time changes", group = g_SETTINGS)
lbl_size = get_size(input.string('Normal', "Label Size", options = , tooltip = "The size of all labels", group = g_SETTINGS))
txt_color = input.color(color.black, "Text Color", tooltip = "The color of all label and table text", group = g_SETTINGS)
use_cutoff = input.bool(false, "Drawing Cutoff Time", inline = "CO", tooltip = "When enabled, all pivots and open price lines will stop extending at this time", group = g_SETTINGS)
cutoff = input.session("1800-1801", "", inline = "CO", group = g_SETTINGS)
var tf_limit_is_equal_or_more_chart_tf = timeframe.in_seconds('') <= timeframe.in_seconds(tf_limit)
var g_KZ = "Killzones"
// General Killzone Settings
show_kz = input.bool(true, "Show Killzone Boxes", inline = "KZ", group = g_KZ)
show_kz_text = input.bool(false, "Display Text", inline = "KZ", group = g_KZ)
box_transparency = input.int(70, "Box Transparency", 0, 100, group = g_KZ)
text_transparency = input.int(50, "Text Transparency", 0, 100, group = g_KZ)
// ==================== KILLZONE 01 ====================
use_kz01 = input.bool(true, "00:00-01:00", inline = "KZ01", group = g_KZ)
kz01_txt = input.string("00-01", "", inline = "KZ01", group = g_KZ)
kz01 = input.session("0000-0100", "", inline = "KZ01", group = g_KZ)
kz01_color = input.color(color.blue, "", inline = "KZ01", group = g_KZ)
// ==================== KILLZONE 02 ====================
use_kz02 = input.bool(true, "01:00-02:00", inline = "KZ02", group = g_KZ)
kz02_txt = input.string("01-02", "", inline = "KZ02", group = g_KZ)
kz02 = input.session("0100-0200", "", inline = "KZ02", group = g_KZ)
kz02_color = input.color(color.blue, "", inline = "KZ02", group = g_KZ)
// ==================== KILLZONE 03 ====================
use_kz03 = input.bool(true, "02:00-03:00", inline = "KZ03", group = g_KZ)
kz03_txt = input.string("02-03", "", inline = "KZ03", group = g_KZ)
kz03 = input.session("0200-0300", "", inline = "KZ03", group = g_KZ)
kz03_color = input.color(color.blue, "", inline = "KZ03", group = g_KZ)
// ==================== KILLZONE 04 ====================
use_kz04 = input.bool(true, "03:00-04:00", inline = "KZ04", group = g_KZ)
kz04_txt = input.string("03-04", "", inline = "KZ04", group = g_KZ)
kz04 = input.session("0300-0400", "", inline = "KZ04", group = g_KZ)
kz04_color = input.color(color.blue, "", inline = "KZ04", group = g_KZ)
// ==================== KILLZONE 05 ====================
use_kz05 = input.bool(true, "04:00-05:00", inline = "KZ05", group = g_KZ)
kz05_txt = input.string("04-05", "", inline = "KZ05", group = g_KZ)
kz05 = input.session("0400-0500", "", inline = "KZ05", group = g_KZ)
kz05_color = input.color(color.blue, "", inline = "KZ05", group = g_KZ)
// ==================== KILLZONE 06 ====================
use_kz06 = input.bool(true, "05:00-06:00", inline = "KZ06", group = g_KZ)
kz06_txt = input.string("05-06", "", inline = "KZ06", group = g_KZ)
kz06 = input.session("0500-0600", "", inline = "KZ06", group = g_KZ)
kz06_color = input.color(color.blue, "", inline = "KZ06", group = g_KZ)
// ==================== KILLZONE 07 ====================
use_kz07 = input.bool(true, "06:00-07:00", inline = "KZ07", group = g_KZ)
kz07_txt = input.string("06-07", "", inline = "KZ07", group = g_KZ)
kz07 = input.session("0600-0700", "", inline = "KZ07", group = g_KZ)
kz07_color = input.color(color.blue, "", inline = "KZ07", group = g_KZ)
// ==================== KILLZONE 08 ====================
use_kz08 = input.bool(true, "07:00-08:00", inline = "KZ08", group = g_KZ)
kz08_txt = input.string("07-08", "", inline = "KZ08", group = g_KZ)
kz08 = input.session("0700-0800", "", inline = "KZ08", group = g_KZ)
kz08_color = input.color(color.blue, "", inline = "KZ08", group = g_KZ)
// ==================== KILLZONE 09 ====================
use_kz09 = input.bool(true, "08:00-09:00", inline = "KZ09", group = g_KZ)
kz09_txt = input.string("08-09", "", inline = "KZ09", group = g_KZ)
kz09 = input.session("0800-0900", "", inline = "KZ09", group = g_KZ)
kz09_color = input.color(color.blue, "", inline = "KZ09", group = g_KZ)
// ==================== KILLZONE 10 ====================
use_kz10 = input.bool(true, "09:00-10:00", inline = "KZ10", group = g_KZ)
kz10_txt = input.string("09-10", "", inline = "KZ10", group = g_KZ)
kz10 = input.session("0900-1000", "", inline = "KZ10", group = g_KZ)
kz10_color = input.color(color.blue, "", inline = "KZ10", group = g_KZ)
// ==================== KILLZONE 11 ====================
use_kz11 = input.bool(true, "10:00-11:00", inline = "KZ11", group = g_KZ)
kz11_txt = input.string("10-11", "", inline = "KZ11", group = g_KZ)
kz11 = input.session("1000-1100", "", inline = "KZ11", group = g_KZ)
kz11_color = input.color(color.blue, "", inline = "KZ11", group = g_KZ)
// ==================== KILLZONE 12 ====================
use_kz12 = input.bool(true, "11:00-12:00", inline = "KZ12", group = g_KZ)
kz12_txt = input.string("11-12", "", inline = "KZ12", group = g_KZ)
kz12 = input.session("1100-1200", "", inline = "KZ12", group = g_KZ)
kz12_color = input.color(color.blue, "", inline = "KZ12", group = g_KZ)
// ==================== KILLZONE 13 ====================
use_kz13 = input.bool(true, "12:00-13:00", inline = "KZ13", group = g_KZ)
kz13_txt = input.string("12-13", "", inline = "KZ13", group = g_KZ)
kz13 = input.session("1200-1300", "", inline = "KZ13", group = g_KZ)
kz13_color = input.color(color.blue, "", inline = "KZ13", group = g_KZ)
// ==================== KILLZONE 14 ====================
use_kz14 = input.bool(true, "13:00-14:00", inline = "KZ14", group = g_KZ)
kz14_txt = input.string("13-14", "", inline = "KZ14", group = g_KZ)
kz14 = input.session("1300-1400", "", inline = "KZ14", group = g_KZ)
kz14_color = input.color(color.blue, "", inline = "KZ14", group = g_KZ)
// ==================== KILLZONE 15 ====================
use_kz15 = input.bool(true, "14:00-15:00", inline = "KZ15", group = g_KZ)
kz15_txt = input.string("14-15", "", inline = "KZ15", group = g_KZ)
kz15 = input.session("1400-1500", "", inline = "KZ15", group = g_KZ)
kz15_color = input.color(color.blue, "", inline = "KZ15", group = g_KZ)
// ==================== KILLZONE 16 ====================
use_kz16 = input.bool(true, "15:00-16:00", inline = "KZ16", group = g_KZ)
kz16_txt = input.string("15-16", "", inline = "KZ16", group = g_KZ)
kz16 = input.session("1500-1600", "", inline = "KZ16", group = g_KZ)
kz16_color = input.color(color.blue, "", inline = "KZ16", group = g_KZ)
// ==================== KILLZONE 17 ====================
use_kz17 = input.bool(true, "16:00-17:00", inline = "KZ17", group = g_KZ)
kz17_txt = input.string("16-17", "", inline = "KZ17", group = g_KZ)
kz17 = input.session("1600-1700", "", inline = "KZ17", group = g_KZ)
kz17_color = input.color(color.blue, "", inline = "KZ17", group = g_KZ)
// ==================== KILLZONE 18 ====================
use_kz18 = input.bool(true, "17:00-18:00", inline = "KZ18", group = g_KZ)
kz18_txt = input.string("17-18", "", inline = "KZ18", group = g_KZ)
kz18 = input.session("1700-1800", "", inline = "KZ18", group = g_KZ)
kz18_color = input.color(color.blue, "", inline = "KZ18", group = g_KZ)
// ==================== KILLZONE 19 ====================
use_kz19 = input.bool(true, "18:00-19:00", inline = "KZ19", group = g_KZ)
kz19_txt = input.string("18-19", "", inline = "KZ19", group = g_KZ)
kz19 = input.session("1800-1900", "", inline = "KZ19", group = g_KZ)
kz19_color = input.color(color.blue, "", inline = "KZ19", group = g_KZ)
// ==================== KILLZONE 20 ====================
use_kz20 = input.bool(true, "19:00-20:00", inline = "KZ20", group = g_KZ)
kz20_txt = input.string("19-20", "", inline = "KZ20", group = g_KZ)
kz20 = input.session("1900-2000", "", inline = "KZ20", group = g_KZ)
kz20_color = input.color(color.blue, "", inline = "KZ20", group = g_KZ)
// ==================== KILLZONE 21 ====================
use_kz21 = input.bool(true, "20:00-21:00", inline = "KZ21", group = g_KZ)
kz21_txt = input.string("20-21", "", inline = "KZ21", group = g_KZ)
kz21 = input.session("2000-2100", "", inline = "KZ21", group = g_KZ)
kz21_color = input.color(color.blue, "", inline = "KZ21", group = g_KZ)
// ==================== KILLZONE 22 ====================
use_kz22 = input.bool(true, "21:00-22:00", inline = "KZ22", group = g_KZ)
kz22_txt = input.string("21-22", "", inline = "KZ22", group = g_KZ)
kz22 = input.session("2100-2200", "", inline = "KZ22", group = g_KZ)
kz22_color = input.color(color.blue, "", inline = "KZ22", group = g_KZ)
// ==================== KILLZONE 23 ====================
use_kz23 = input.bool(true, "22:00-23:00", inline = "KZ23", group = g_KZ)
kz23_txt = input.string("22-23", "", inline = "KZ23", group = g_KZ)
kz23 = input.session("2200-2300", "", inline = "KZ23", group = g_KZ)
kz23_color = input.color(color.blue, "", inline = "KZ23", group = g_KZ)
// ==================== KILLZONE 24 ====================
use_kz24 = input.bool(true, "23:00-00:00", inline = "KZ24", group = g_KZ)
kz24_txt = input.string("23-00", "", inline = "KZ24", group = g_KZ)
kz24 = input.session("2300-0000", "", inline = "KZ24", group = g_KZ)
kz24_color = input.color(color.blue, "", inline = "KZ24", group = g_KZ)
// ==================== KILLZONE 25 ====================
use_kz25 = input.bool(true, "17:00-21:00", inline = "KZ25", group = g_KZ)
kz25_txt = input.string("H4", "", inline = "KZ25", group = g_KZ)
kz25 = input.session("1700-2100", "", inline = "KZ25", group = g_KZ)
kz25_color = input.color(color.orange, "", inline = "KZ25", group = g_KZ)
// ==================== KILLZONE 26 ====================
use_kz26 = input.bool(true, "21:00-01:00", inline = "KZ26", group = g_KZ)
kz26_txt = input.string("H4", "", inline = "KZ26", group = g_KZ)
kz26 = input.session("2100-0100", "", inline = "KZ26", group = g_KZ)
kz26_color = input.color(color.aqua, "", inline = "KZ26", group = g_KZ)
// ==================== KILLZONE 27 ====================
use_kz27 = input.bool(true, "01:00-05:00", inline = "KZ27", group = g_KZ)
kz27_txt = input.string("H4", "", inline = "KZ27", group = g_KZ)
kz27 = input.session("0100-0500", "", inline = "KZ27", group = g_KZ)
kz27_color = input.color(color.green, "", inline = "KZ27", group = g_KZ)
// ==================== KILLZONE 28 ====================
use_kz28 = input.bool(true, "05:00-09:00", inline = "KZ28", group = g_KZ)
kz28_txt = input.string("H4", "", inline = "KZ28", group = g_KZ)
kz28 = input.session("0500-0900", "", inline = "KZ28", group = g_KZ)
kz28_color = input.color(color.yellow, "", inline = "KZ28", group = g_KZ)
// ==================== KILLZONE 29 ====================
use_kz29 = input.bool(true, "09:00-13:00", inline = "KZ29", group = g_KZ)
kz29_txt = input.string("H4", "", inline = "KZ29", group = g_KZ)
kz29 = input.session("0900-1300", "", inline = "KZ29", group = g_KZ)
kz29_color = input.color(color.red, "", inline = "KZ29", group = g_KZ)
// ==================== KILLZONE 30 ====================
use_kz30 = input.bool(true, "13:00-17:00", inline = "KZ30", group = g_KZ)
kz30_txt = input.string("H4", "", inline = "KZ30", group = g_KZ)
kz30 = input.session("1300-1700", "", inline = "KZ30", group = g_KZ)
kz30_color = input.color(color.purple, "", inline = "KZ30", group = g_KZ)
// ==================== KILLZONE 31 ====================
use_kz31 = input.bool(false, "05:00-17:00", inline = "KZ31", group = g_KZ)
kz31_txt = input.string("H12", "", inline = "KZ31", group = g_KZ)
kz31 = input.session("0500-1700", "", inline = "KZ31", group = g_KZ)
kz31_color = input.color(color.purple, "", inline = "KZ31", group = g_KZ)
// ==================== KILLZONE 32 ====================
use_kz32 = input.bool(false, "17:00-05:00", inline = "KZ32", group = g_KZ)
kz32_txt = input.string("H12", "", inline = "KZ32", group = g_KZ)
kz32 = input.session("1700-0500", "", inline = "KZ32", group = g_KZ)
kz32_color = input.color(color.purple, "", inline = "KZ32", group = g_KZ)
// ==================== KILLZONE 33 ====================
use_kz33 = input.bool(false, "17:00-01:00", inline = "KZ33", group = g_KZ)
kz33_txt = input.string("H8", "", inline = "KZ33", group = g_KZ)
kz33 = input.session("1700-0100", "", inline = "KZ33", group = g_KZ)
kz33_color = input.color(color.purple, "", inline = "KZ33", group = g_KZ)
// ==================== KILLZONE 34 ====================
use_kz34 = input.bool(false, "01:00-09:00", inline = "KZ34", group = g_KZ)
kz34_txt = input.string("H8", "", inline = "KZ34", group = g_KZ)
kz34 = input.session("0100-0900", "", inline = "KZ34", group = g_KZ)
kz34_color = input.color(color.purple, "", inline = "KZ34", group = g_KZ)
// ==================== KILLZONE 35 ====================
use_kz35 = input.bool(false, "09:00-17:00", inline = "KZ35", group = g_KZ)
kz35_txt = input.string("H8", "", inline = "KZ35", group = g_KZ)
kz35 = input.session("0900-1700", "", inline = "KZ35", group = g_KZ)
kz35_color = input.color(color.purple, "", inline = "KZ35", group = g_KZ)
// ==================== KILLZONE 36 ====================
use_kz36 = input.bool(false, "17:00-23:00", inline = "KZ36", group = g_KZ)
kz36_txt = input.string("H6", "", inline = "KZ36", group = g_KZ)
kz36 = input.session("1700-2300", "", inline = "KZ36", group = g_KZ)
kz36_color = input.color(color.purple, "", inline = "KZ36", group = g_KZ)
// ==================== KILLZONE 37 ====================
use_kz37 = input.bool(false, "23:00-05:00", inline = "KZ37", group = g_KZ)
kz37_txt = input.string("H6", "", inline = "KZ37", group = g_KZ)
kz37 = input.session("2300-0500", "", inline = "KZ37", group = g_KZ)
kz37_color = input.color(color.purple, "", inline = "KZ37", group = g_KZ)
// ==================== KILLZONE 38 ====================
use_kz38 = input.bool(false, "05:00-11:00", inline = "KZ38", group = g_KZ)
kz38_txt = input.string("H6", "", inline = "KZ38", group = g_KZ)
kz38 = input.session("0500-1100", "", inline = "KZ38", group = g_KZ)
kz38_color = input.color(color.purple, "", inline = "KZ38", group = g_KZ)
// ==================== KILLZONE 39 ====================
use_kz39 = input.bool(false, "11:00-17:00", inline = "KZ39", group = g_KZ)
kz39_txt = input.string("H6", "", inline = "KZ39", group = g_KZ)
kz39 = input.session("1100-1700", "", inline = "KZ39", group = g_KZ)
kz39_color = input.color(color.purple, "", inline = "KZ39", group = g_KZ)
var g_LABELS = "Killzone Pivots"
show_pivots = input.bool(false, "Show Pivots", inline = "PV", group = g_LABELS)
use_alerts = input.bool(false, "Alert Broken Pivots", inline = "PV", tooltip = "The desired killzones must be enabled at the time that an alert is created, along with the show pivots option, in order for alerts to work", group = g_LABELS)
show_midpoints = input.bool(false, "Show Pivot Midpoints", inline = "mp", group = g_LABELS)
stop_midpoints = input.bool(false, "Stop Once Mitigated", inline = "mp", group = g_LABELS)
show_labels = input.bool(false, "Show Pivot Labels", inline = "LB", tooltip = "Show labels denoting each killzone's high and low. Optionally choose to show the price of each level. Right side will show labels on the right-hand side of the chart until they are reached", group = g_LABELS)
label_price = input.bool(false, "Display Price", inline = "LB", group = g_LABELS)
label_right = input.bool(false, "Right Side", inline = "LB", group = g_LABELS)
ext_pivots = input.string("Until Mitigated", "Extend Pivots...", options = , group = g_LABELS)
ext_which = input.string("All", "...From Which Sessions", options = , group = g_LABELS)
ash_str = input.string("AS.H", "Killzone 1 Labels", inline = "L_AS", group = g_LABELS)
asl_str = input.string("AS.L", "", inline = "L_AS", group = g_LABELS)
loh_str = input.string("LO.H", "Killzone 2 Labels", inline = "L_LO", group = g_LABELS)
lol_str = input.string("LO.L", "", inline = "L_LO", group = g_LABELS)
nah_str = input.string("NYAM.H", "Killzone 3 Labels", inline = "L_NA", group = g_LABELS)
nal_str = input.string("NYAM.L", "", inline = "L_NA", group = g_LABELS)
nlh_str = input.string("NYL.H", "Killzone 4 Labels", inline = "L_NL", group = g_LABELS)
nll_str = input.string("NYL.L", "", inline = "L_NL", group = g_LABELS)
nph_str = input.string("NYPM.H", "Killzone 5 Labels", inline = "L_NP", group = g_LABELS)
npl_str = input.string("NYPM.L", "", inline = "L_NP", group = g_LABELS)
kzp_style = get_line_type(input.string(defval = 'Solid', title = "Pivot Style", options = , inline = "KZP", group = g_LABELS))
kzp_width = input.int(1, "", inline = "KZP", group = g_LABELS)
kzm_style = get_line_type(input.string(defval = 'Dotted', title = "Midpoint Style", options = , inline = "KZM", group = g_LABELS))
kzm_width = input.int(1, "", inline = "KZM", group = g_LABELS)
var g_RNG = "Killzone Range"
show_range = input.bool(false, "Show Killzone Range", tooltip = "Show the most recent ranges of each selected killzone, from high to low", group = g_RNG)
show_range_avg = input.bool(false, "Show Average", tooltip = "Show the average range of each selected killzone", group = g_RNG)
range_avg = input.int(5, "Average Length", 0, tooltip = "This many previous sessions will be used to calculate the average. If there isn't enough data on the current chart, it will use as many sessions as possible", group = g_RNG)
range_pos = get_table_pos(input.string('Top Right', "Table Position", options = , group = g_RNG))
range_size = get_size(input.string('Normal', "Table Size", options = , group = g_RNG))
var g_DWM = "Day - Week - Month"
sep_unlimited = input.bool(false, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_DWM)
alert_HL = input.bool(false, "Alert High/Low Break", tooltip = "Alert when any selected highs and lows are traded through. The desired timeframe's high/low option must be enabled at the time that an alert is created", group = g_DWM)
show_d_open = input.bool(false, "D Open", inline = "DO", group = g_DWM)
dhl = input.bool(false, "High/Low", inline = "DO", tooltip = "", group = g_DWM)
ds = input.bool(false, "Separators", inline = "DO", tooltip = "Mark where a new day begins", group = g_DWM)
d_color = input.color(color.blue, "", inline = "DO", group = g_DWM)
show_w_open = input.bool(false, "W Open", inline = "WO", group = g_DWM)
whl = input.bool(false, "High/Low", inline = "WO", tooltip = "", group = g_DWM)
ws = input.bool(false, "Separators", inline = "WO", tooltip = "Mark where a new week begins", group = g_DWM)
w_color = input.color(#089981, "", inline = "WO", group = g_DWM)
show_m_open = input.bool(false, "M Open", inline = "MO", group = g_DWM)
mhl = input.bool(false, "High/Low", inline = "MO", tooltip = "", group = g_DWM)
ms = input.bool(false, "Separators", inline = "MO", tooltip = "Mark where a new month begins", group = g_DWM)
m_color = input.color(color.red, "", inline = "MO", group = g_DWM)
htf_style = get_line_type(input.string(defval = 'Solid', title = "Style", options = , inline = "D0", group = g_DWM))
htf_width = input.int(1, "", inline = "D0", group = g_DWM)
dow_labels = input.bool(false, "Day of Week Labels", inline = "DOW", group = g_DWM)
dow_yloc = input.string('Bottom', "", options = , inline = "DOW", group = g_DWM)
dow_xloc = input.string('Midnight', "", options = , inline = "DOW", group = g_DWM)
dow_hide_wknd = input.bool(false, "Hide Weekend Labels", group = g_DWM)
var g_OPEN = "Opening Prices"
open_unlimited = input.bool(false, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_OPEN)
use_h1 = input.bool(false, "", inline = "H1", group = g_OPEN)
h1_text = input.string("17:00 H12/H8/H6/H4", "", inline = "H1", group = g_OPEN)
h1 = input.session("1700-1701", "", inline = "H1", group = g_OPEN)
h1_color = input.color(color.black, "", inline = "H1", group = g_OPEN)
use_h2 = input.bool(false, "", inline = "H2", group = g_OPEN)
h2_text = input.string("05:00 H12/H6/H4", "", inline = "H2", group = g_OPEN)
h2 = input.session("0500-0501", "", inline = "H2", group = g_OPEN)
h2_color = input.color(color.black, "", inline = "H2", group = g_OPEN)
use_h3 = input.bool(false, "", inline = "H3", group = g_OPEN)
h3_text = input.string("01:00 H8/H4", "", inline = "H3", group = g_OPEN)
h3 = input.session("0100-0101", "", inline = "H3", group = g_OPEN)
h3_color = input.color(color.black, "", inline = "H3", group = g_OPEN)
use_h4 = input.bool(false, "", inline = "H4", group = g_OPEN)
h4_text = input.string("09:00 H8/H4", "", inline = "H4", group = g_OPEN)
h4 = input.session("0900-0901", "", inline = "H4", group = g_OPEN)
h4_color = input.color(color.black, "", inline = "H4", group = g_OPEN)
use_h5 = input.bool(false, "", inline = "H5", group = g_OPEN)
h5_text = input.string("23:00 H6", "", inline = "H5", group = g_OPEN)
h5 = input.session("2300-2301", "", inline = "H5", group = g_OPEN)
h5_color = input.color(color.black, "", inline = "H5", group = g_OPEN)
use_h6 = input.bool(false, "", inline = "H6", group = g_OPEN)
h6_text = input.string("11:00 H6", "", inline = "H6", group = g_OPEN)
h6 = input.session("1100-1101", "", inline = "H6", group = g_OPEN)
h6_color = input.color(color.black, "", inline = "H6", group = g_OPEN)
use_h7 = input.bool(false, "", inline = "H7", group = g_OPEN)
h7_text = input.string("21:00 H4", "", inline = "H7", group = g_OPEN)
h7 = input.session("2100-2101", "", inline = "H7", group = g_OPEN)
h7_color = input.color(color.black, "", inline = "H7", group = g_OPEN)
use_h8 = input.bool(false, "", inline = "H8", group = g_OPEN)
h8_text = input.string("13:00 H4", "", inline = "H8", group = g_OPEN)
h8 = input.session("1300-1301", "", inline = "H8", group = g_OPEN)
h8_color = input.color(color.black, "", inline = "H8", group = g_OPEN)
hz_style = get_line_type(input.string(defval = 'Dotted', title = "Style", options = , inline = "H0", group = g_OPEN))
hz_width = input.int(1, "", inline = "H0", group = g_OPEN)
var g_VERTICAL = "Timestamps"
v_unlimited = input.bool(false, "Unlimited", tooltip = "Unlimited will show as many of the selected lines as possible. Otherwise, the session drawing limit will be used", group = g_VERTICAL)
use_v1 = input.bool(false, "", inline = "V1", group = g_VERTICAL)
v1 = input.session("0000-0001", "", inline = "V1", group = g_VERTICAL)
v1_color = input.color(color.black, "", inline = "V1", group = g_VERTICAL)
use_v2 = input.bool(false, "", inline = "V2", group = g_VERTICAL)
v2 = input.session("0800-0801", "", inline = "V2", group = g_VERTICAL)
v2_color = input.color(color.black, "", inline = "V2", group = g_VERTICAL)
use_v3 = input.bool(false, "", inline = "V3", group = g_VERTICAL)
v3 = input.session("1000-1001", "", inline = "V3", group = g_VERTICAL)
v3_color = input.color(color.black, "", inline = "V3", group = g_VERTICAL)
use_v4 = input.bool(false, "", inline = "V4", group = g_VERTICAL)
v4 = input.session("1200-1201", "", inline = "V4", group = g_VERTICAL)
v4_color = input.color(color.black, "", inline = "V4", group = g_VERTICAL)
vl_style = get_line_type(input.string(defval = 'Dotted', title = "Style", options = , inline = "V0", group = g_VERTICAL))
vl_width = input.int(1, "", inline = "V0", group = g_VERTICAL)
// ---------------------------------------- Inputs --------------------------------------------------
// ---------------------------------------- Variables & Constants --------------------------------------------------
type kz
string _title
array _box
array _hi_line
array _md_line
array _lo_line
array _hi_label
array _lo_label
array _hi_valid
array _md_valid
array _lo_valid
array _range_store
float _range_current
type hz
array LN
array LB
array CO
type dwm_hl
array hi_line
array lo_line
array hi_label
array lo_label
bool hit_high = false
bool hit_low = false
type dwm_info
string tf
float o = na
float h = na
float l = na
float ph = na
float pl = na
type lines_helper
hz _hz
string h
string h_text
color h_color
initLines() =>
array res = array.new()
if use_h1
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h1, h1_text, h1_color))
if use_h2
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h2, h2_text, h2_color))
if use_h3
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h3, h3_text, h3_color))
if use_h4
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h4, h4_text, h4_color))
if use_h5
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h5, h5_text, h5_color))
if use_h6
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h6, h6_text, h6_color))
if use_h7
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h7, h7_text, h7_color))
if use_h8
res.push(lines_helper.new(hz.new(array.new_line(), array.new_label(), array.new_bool()), h8, h8_text, h8_color))
res
var array lines = initLines()
type kz_helper
kz _kz
string session
color c
string box_txt
string hi_txt
string lo_txt
initKZ() =>
array res = array.new()
if use_kz01
res.push(kz_helper.new(
kz.new(kz01_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz01, kz01_color, kz01_txt, "KZ01.H", "KZ01.L"
))
if use_kz02
res.push(kz_helper.new(
kz.new(kz02_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz02, kz02_color, kz02_txt, "KZ02.H", "KZ02.L"
))
if use_kz03
res.push(kz_helper.new(
kz.new(kz03_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz03, kz03_color, kz03_txt, "KZ03.H", "KZ03.L"
))
if use_kz04
res.push(kz_helper.new(
kz.new(kz04_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz04, kz04_color, kz04_txt, "KZ04.H", "KZ04.L"
))
if use_kz05
res.push(kz_helper.new(
kz.new(kz05_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz05, kz05_color, kz05_txt, "KZ05.H", "KZ05.L"
))
if use_kz06
res.push(kz_helper.new(
kz.new(kz06_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz06, kz06_color, kz06_txt, "KZ06.H", "KZ06.L"
))
if use_kz07
res.push(kz_helper.new(
kz.new(kz07_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz07, kz07_color, kz07_txt, "KZ07.H", "KZ07.L"
))
if use_kz08
res.push(kz_helper.new(
kz.new(kz08_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz08, kz08_color, kz08_txt, "KZ08.H", "KZ08.L"
))
if use_kz09
res.push(kz_helper.new(
kz.new(kz09_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz09, kz09_color, kz09_txt, "KZ09.H", "KZ09.L"
))
if use_kz10
res.push(kz_helper.new(
kz.new(kz10_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz10, kz10_color, kz10_txt, "KZ10.H", "KZ10.L"
))
if use_kz11
res.push(kz_helper.new(
kz.new(kz11_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz11, kz11_color, kz11_txt, "KZ11.H", "KZ11.L"
))
if use_kz12
res.push(kz_helper.new(
kz.new(kz12_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz12, kz12_color, kz12_txt, "KZ12.H", "KZ12.L"
))
if use_kz13
res.push(kz_helper.new(
kz.new(kz13_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz13, kz13_color, kz13_txt, "KZ13.H", "KZ13.L"
))
if use_kz14
res.push(kz_helper.new(
kz.new(kz14_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz14, kz14_color, kz14_txt, "KZ14.H", "KZ14.L"
))
if use_kz15
res.push(kz_helper.new(
kz.new(kz15_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz15, kz15_color, kz15_txt, "KZ15.H", "KZ15.L"
))
if use_kz16
res.push(kz_helper.new(
kz.new(kz16_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz16, kz16_color, kz16_txt, "KZ16.H", "KZ16.L"
))
if use_kz17
res.push(kz_helper.new(
kz.new(kz17_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz17, kz17_color, kz17_txt, "KZ17.H", "KZ17.L"
))
if use_kz18
res.push(kz_helper.new(
kz.new(kz18_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz18, kz18_color, kz18_txt, "KZ18.H", "KZ18.L"
))
if use_kz19
res.push(kz_helper.new(
kz.new(kz19_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz19, kz19_color, kz19_txt, "KZ19.H", "KZ19.L"
))
if use_kz20
res.push(kz_helper.new(
kz.new(kz20_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz20, kz20_color, kz20_txt, "KZ20.H", "KZ20.L"
))
if use_kz21
res.push(kz_helper.new(
kz.new(kz21_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz21, kz21_color, kz21_txt, "KZ21.H", "KZ21.L"
))
if use_kz22
res.push(kz_helper.new(
kz.new(kz22_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz22, kz22_color, kz22_txt, "KZ22.H", "KZ22.L"
))
if use_kz23
res.push(kz_helper.new(
kz.new(kz23_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz23, kz23_color, kz23_txt, "KZ23.H", "KZ23.L"
))
if use_kz24
res.push(kz_helper.new(
kz.new(kz24_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz24, kz24_color, kz24_txt, "KZ24.H", "KZ24.L"
))
if use_kz25
res.push(kz_helper.new(
kz.new(kz25_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz25, kz25_color, kz25_txt, "KZ25.H", "KZ25.L"
))
if use_kz26
res.push(kz_helper.new(
kz.new(kz26_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz26, kz26_color, kz26_txt, "KZ26.H", "KZ26.L"
))
if use_kz27
res.push(kz_helper.new(
kz.new(kz27_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz27, kz27_color, kz27_txt, "KZ27.H", "KZ27.L"
))
if use_kz28
res.push(kz_helper.new(
kz.new(kz28_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz28, kz28_color, kz28_txt, "KZ28.H", "KZ28.L"
))
if use_kz29
res.push(kz_helper.new(
kz.new(kz29_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz29, kz29_color, kz29_txt, "KZ29.H", "KZ29.L"
))
if use_kz30
res.push(kz_helper.new(
kz.new(kz30_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz30, kz30_color, kz30_txt, "KZ30.H", "KZ30.L"
))
if use_kz31
res.push(kz_helper.new(
kz.new(kz31_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz31, kz31_color, kz31_txt, "KZ31.H", "KZ31.L"
))
if use_kz32
res.push(kz_helper.new(
kz.new(kz32_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz32, kz32_color, kz32_txt, "KZ32.H", "KZ32.L"
))
if use_kz33
res.push(kz_helper.new(
kz.new(kz33_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz33, kz33_color, kz33_txt, "KZ33.H", "KZ33.L"
))
if use_kz34
res.push(kz_helper.new(
kz.new(kz34_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz34, kz34_color, kz34_txt, "KZ34.H", "KZ34.L"
))
if use_kz35
res.push(kz_helper.new(
kz.new(kz35_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz35, kz35_color, kz35_txt, "KZ35.H", "KZ35.L"
))
if use_kz36
res.push(kz_helper.new(
kz.new(kz36_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz36, kz36_color, kz36_txt, "KZ36.H", "KZ36.L"
))
if use_kz37
res.push(kz_helper.new(
kz.new(kz37_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz37, kz37_color, kz37_txt, "KZ37.H", "KZ37.L"
))
if use_kz38
res.push(kz_helper.new(
kz.new(kz38_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz38, kz38_color, kz38_txt, "KZ38.H", "KZ38.L"
))
if use_kz39
res.push(kz_helper.new(
kz.new(kz39_txt, array.new_box(), array.new_line(), array.new_line(), array.new_line(), array.new_label(), array.new_label(), array.new_bool(), array.new_bool(), array.new_bool(), array.new_float()),
kz39, kz39_color, kz39_txt, "KZ39.H", "KZ39.L"
))
res
var array _kz = initKZ()
var d_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var w_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var m_hl = dwm_hl.new(array.new_line(), array.new_line(), array.new_label(), array.new_label())
var d_info = dwm_info.new("D")
var w_info = dwm_info.new("W")
var m_info = dwm_info.new("M")
t_co = not na(time("", cutoff, gmt_tz))
type ts_helper
string session
array lines
color c
initTS() =>
array res = array.new()
if use_v1
res.push(ts_helper.new(v1, array.new_line(), v1_color))
if use_v2
res.push(ts_helper.new(v2, array.new_line(), v2_color))
if use_v3
res.push(ts_helper.new(v3, array.new_line(), v3_color))
if use_v4
res.push(ts_helper.new(v4, array.new_line(), v4_color))
res
var array ts_data = initTS()
var d_sep_line = array.new_line()
var w_sep_line = array.new_line()
var m_sep_line = array.new_line()
var d_line = array.new_line()
var w_line = array.new_line()
var m_line = array.new_line()
var d_label = array.new_label()
var w_label = array.new_label()
var m_label = array.new_label()
var transparent = #ffffff00
var ext_current = ext_which == 'Most Recent'
var ext_past = ext_pivots == 'Past Mitigation'
update_dwm_info(dwm_info n) =>
if timeframe.change(n.tf)
n.ph := n.h
n.pl := n.l
n.o := open
n.h := high
n.l := low
else
n.h := math.max(high, n.h)
n.l := math.min(low, n.l)
if dhl or show_d_open
update_dwm_info(d_info)
if whl or show_w_open
update_dwm_info(w_info)
if mhl or show_m_open
update_dwm_info(m_info)
// ---------------------------------------- Variables & Constants --------------------------------------------------
// ---------------------------------------- Functions --------------------------------------------------
get_box_color(color c) =>
color.new(c, box_transparency)
get_text_color(color c) =>
color.new(c, text_transparency)
// ---------------------------------------- Functions --------------------------------------------------
// ---------------------------------------- Core Logic --------------------------------------------------
dwm_sep(string tf, bool use, array arr, color col) =>
if use
if timeframe.change(tf)
arr.unshift(line.new(bar_index, high * 1.0001, bar_index, low, style = htf_style, width = htf_width, extend = extend.both, color = col))
if not sep_unlimited and arr.size() > max_days
arr.pop().delete()
dwm_open(string tf, bool use, array lns, array lbls, dwm_info n, color col) =>
if use
if lns.size() > 0
lns.get(0).set_x2(time)
lbls.get(0).set_x(time)
if timeframe.change(tf)
lns.unshift(line.new(time, n.o, time, n.o, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
lbls.unshift(label.new(time, n.o, tf + " OPEN", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
if not sep_unlimited and lns.size() > max_days
lns.pop().delete()
lbls.pop().delete()
dwm_hl(string tf, bool use, dwm_hl hl, dwm_info n, color col) =>
if use
if hl.hi_line.size() > 0
hl.hi_line.get(0).set_x2(time)
hl.lo_line.get(0).set_x2(time)
hl.hi_label.get(0).set_x(time)
hl.lo_label.get(0).set_x(time)
if timeframe.change(tf)
hl.hi_line.unshift(line.new(time, n.ph, time, n.ph, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
hl.lo_line.unshift(line.new(time, n.pl, time, n.pl, xloc = xloc.bar_time, style = htf_style, width = htf_width, color = col))
hl.hi_label.unshift(label.new(time, n.ph, "P" + tf + "H", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
hl.lo_label.unshift(label.new(time, n.pl, "P" + tf + "L", xloc = xloc.bar_time, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
hl.hit_high := false
hl.hit_low := false
if not sep_unlimited and hl.hi_line.size() > max_days
hl.hi_line.pop().delete()
hl.lo_line.pop().delete()
hl.hi_label.pop().delete()
hl.lo_label.pop().delete()
if hl.hi_line.size() > 0 and alert_HL
if not hl.hit_high and high > hl.hi_line.get(0).get_y1()
hl.hit_high := true
alert(str.format("Hit P{0}H", tf))
if not hl.hit_low and low < hl.lo_line.get(0).get_y1()
hl.hit_low := true
alert(str.format("Hit P{0}L", tf))
dwm() =>
if tf_limit_is_equal_or_more_chart_tf
// DWM - Separators
dwm_sep("D", ds, d_sep_line, d_color)
dwm_sep("W", ws, w_sep_line, w_color)
dwm_sep("M", ms, m_sep_line, m_color)
// DWM - Open Lines
dwm_open("D", show_d_open, d_line, d_label, d_info, d_color)
dwm_open("W", show_w_open, w_line, w_label, w_info, w_color)
dwm_open("M", show_m_open, m_line, m_label, m_info, m_color)
// DWM - Highs and Lows
dwm_hl("D", dhl, d_hl, d_info, d_color)
dwm_hl("W", whl, w_hl, w_info, w_color)
dwm_hl("M", mhl, m_hl, m_info, m_color)
method vline(ts_helper this) =>
bool t = not na(time("", this.session, gmt_tz))
bool t_prev = not na(time("", this.session, gmt_tz, bars_back = 1))
array arr = this.lines
color col = this.c
if t and not t_prev
arr.unshift(line.new(bar_index, high * 1.0001, bar_index, low, style = vl_style, width = vl_width, extend = extend.both, color = col))
if not v_unlimited
if arr.size() > max_days
arr.pop().delete()
vlines() =>
if tf_limit_is_equal_or_more_chart_tf
for in ts_data
vline(value)
method hz_line(lines_helper this) =>
bool t = not na(time("", this.h, gmt_tz))
bool t_prev = not na(time("", this.h, gmt_tz, bars_back = 1))
hz hz = this._hz
string txt = this.h_text
color col = this.h_color
if t and not t_prev
hz.LN.unshift(line.new(bar_index, open, bar_index, open, style = hz_style, width = hz_width, color = col))
hz.LB.unshift(label.new(bar_index, open, txt, style = label.style_label_left, color = transparent, textcolor = txt_color, size = lbl_size))
array.unshift(hz.CO, false)
if not open_unlimited and hz.LN.size() > max_days
hz.LN.pop().delete()
hz.LB.pop().delete()
hz.CO.pop()
if not t and hz.CO.size() > 0
if not hz.CO.get(0)
hz.LN.get(0).set_x2(bar_index)
hz.LB.get(0).set_x(bar_index)
if (use_cutoff ? t_co : false)
hz.CO.set(0, true)
hz_lines() =>
if tf_limit_is_equal_or_more_chart_tf
for in lines
hz_line(value)
del_kz(kz k) =>
if k._box.size() > max_days
k._box.pop().delete()
if k._hi_line.size() > max_days
k._hi_line.pop().delete()
k._lo_line.pop().delete()
k._hi_valid.pop()
k._lo_valid.pop()
if show_midpoints
k._md_line.pop().delete()
k._md_valid.pop()
if k._hi_label.size() > max_days
k._hi_label.pop().delete()
k._lo_label.pop().delete()
update_price_string(label L, float P) =>
S = L.get_text()
pre = str.substring(S, 0, str.pos(S, " "))
str.trim(pre)
L.set_text(str.format("{0} ({1})", pre, P))
adjust_in_kz(kz kz, bool t) =>
if t
kzBox0 = kz._box.get(0)
kzBox0.set_right(time)
newTop = math.max(kzBox0.get_top(), high)
kzBox0.set_top(newTop)
newBottom = math.min(kzBox0.get_bottom(), low)
kzBox0.set_bottom(newBottom)
kz._range_current := newTop - newBottom
if show_pivots and kz._hi_line.size() > 0
kzHiLine0 = kz._hi_line.get(0)
kzHiLine0.set_x2(time)
if high > kzHiLine0.get_y1()
kzHiLine0.set_xy1(time, high)
kzHiLine0.set_xy2(time, high)
kzLoLine0 = kz._lo_line.get(0)
kzLoLine0.set_x2(time)
if low < kzLoLine0.get_y1()
kzLoLine0.set_xy1(time, low)
kzLoLine0.set_xy2(time, low)
if show_midpoints
kzMidLine0 = kz._md_line.get(0)
kzMidLine0.set_x2(time)
kzMidLine0.set_xy1(time, math.avg(kzHiLine0.get_y2(), kzLoLine0.get_y2()))
kzMidLine0.set_xy2(time, math.avg(kzHiLine0.get_y2(), kzLoLine0.get_y2()))
if show_labels and kz._hi_label.size() > 0
if label_right
kz._hi_label.get(0).set_x(time)
kz._lo_label.get(0).set_x(time)
if high > kz._hi_label.get(0).get_y()
kz._hi_label.get(0).set_xy(time, high)
if label_price
update_price_string(kz._hi_label.get(0), high)
if low < kz._lo_label.get(0).get_y()
kz._lo_label.get(0).set_xy(time, low)
if label_price
update_price_string(kz._lo_label.get(0), low)
adjust_out_kz(kz kz, bool t, bool t_prev) =>
boxCount = kz._box.size()
if not t and boxCount > 0
if t_prev
array.unshift(kz._range_store, kz._range_current)
if kz._range_store.size() > range_avg
kz._range_store.pop()
if show_pivots and boxCount > 0
for i = 0 to boxCount - 1 by 1
if not ext_current or i == 0
kzHiValid = kz._hi_valid.get(i)
if ext_past or kzHiValid
kz._hi_line.get(i).set_x2(time)
if show_labels and label_right
kz._hi_label.get(i).set_x(time)
if kzHiValid and high > kz._hi_line.get(i).get_y1()
if use_alerts and i == 0
alert('Broke ' + kz._title + ' High', alert.freq_once_per_bar)
kz._hi_valid.set(i, false)
if show_labels and label_right
kz._hi_label.get(i).set_style(label.style_label_down)
else if use_cutoff ? t_co : false
kz._hi_valid.set(i, false)
kzLoValid = kz._lo_valid.get(i)
if ext_past or kzLoValid
kz._lo_line.get(i).set_x2(time)
if show_labels and label_right
kz._lo_label.get(i).set_x(time)
if kzLoValid and low < kz._lo_line.get(i).get_y1()
if use_alerts and i == 0
alert("Broke " + kz._title + " Low", alert.freq_once_per_bar)
kz._lo_valid.set(i, false)
if show_labels and label_right
kz._lo_label.get(i).set_style(label.style_label_up)
else if use_cutoff ? t_co : false
kz._lo_valid.set(i, false)
if show_midpoints and not t
if stop_midpoints ? kz._md_valid.get(i) : true
kz._md_line.get(i).set_x2(time)
if kz._md_valid.get(i) and low <= kz._md_line.get(i).get_y1() and high >= kz._md_line.get(i).get_y1()
kz._md_valid.set(i, false)
else
break
method manage_kz(kz_helper this) =>
kz kz = this._kz
c = this.c
string box_txt = this.box_txt
string hi_txt = this.hi_txt
string lo_txt = this.lo_txt
if tf_limit_is_equal_or_more_chart_tf
t = not na(time("", this.session, gmt_tz))
t_prev = not na(time("", this.session, gmt_tz, bars_back = 1))
if t and not t_prev
_c = get_box_color(c)
_t = get_text_color(c)
kz._box.unshift(box.new(time, high, time, low, xloc = xloc.bar_time, border_color = show_kz ? _c : na, bgcolor = show_kz ? _c : na, text = show_kz and show_kz_text ? box_txt : na, text_color = _t))
if show_pivots
kz._hi_line.unshift(line.new(time, high, time, high, xloc = xloc.bar_time, style = kzp_style, color = c, width = kzp_width))
kz._lo_line.unshift(line.new(time, low, time, low, xloc = xloc.bar_time, style = kzp_style, color = c, width = kzp_width))
if show_midpoints
kz._md_line.unshift(line.new(time, math.avg(high, low), time, math.avg(high, low), xloc = xloc.bar_time, style = kzm_style, color = c, width = kzm_width))
array.unshift(kz._md_valid, true)
array.unshift(kz._hi_valid, true)
array.unshift(kz._lo_valid, true)
if show_labels
_hi_txt = label_price ? str.format('{0} ({1})', hi_txt, high) : hi_txt
_lo_txt = label_price ? str.format('{0} ({1})', lo_txt, low) : lo_txt
if label_right
kz._hi_label.unshift(label.new(time, high, _hi_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_left, size = lbl_size))
kz._lo_label.unshift(label.new(time, low, _lo_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_left, size = lbl_size))
else
kz._hi_label.unshift(label.new(time, high, _hi_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_down, size = lbl_size))
kz._lo_label.unshift(label.new(time, low, _lo_txt, xloc = xloc.bar_time, color = transparent, textcolor = txt_color, style = label.style_label_up, size = lbl_size))
del_kz(kz)
adjust_in_kz(kz, t)
adjust_out_kz(kz, t, t_prev)
for in _kz
manage_kz(value)
dwm()
vlines()
hz_lines()
new_dow_time = dow_xloc == 'Midday' ? time - timeframe.in_seconds("D") / 2 * 1000 : time
new_day = dayofweek(new_dow_time, gmt_tz) != dayofweek(new_dow_time, gmt_tz)
var dow_top = dow_yloc == 'Top'
var saturday = "SATURDAY"
var sunday = "SUNDAY"
var monday = "MONDAY"
var tuesday = "TUESDAY"
var wednesday = "WEDNESDAY"
var thursday = "THURSDAY"
var friday = "FRIDAY"
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 1 and new_day and not dow_hide_wknd, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = sunday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 2 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = monday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 3 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = tuesday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 4 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = wednesday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 5 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = thursday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 6 and new_day, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = friday)
plotchar(dow_labels and timeframe.isintraday and dayofweek(new_dow_time, gmt_tz) == 7 and new_day and not dow_hide_wknd, location = dow_top ? location.top : location.bottom, char = '', textcolor = txt_color, text = saturday)
get_min_days_stored() =>
store = array.new_int()
for in _kz
int tmpStoreSize = value._kz._range_store.size()
if tmpStoreSize > 0
store.push(tmpStoreSize)
store.min()
method set_table(table tbl, kz kz, int row, string txt, bool t, color col) =>
table.cell(tbl, 0, row, txt, text_size = range_size, bgcolor = get_box_color(col), text_color = txt_color)
table.cell(tbl, 1, row, str.tostring(kz._range_current), text_size = range_size, bgcolor = t ? get_box_color(col) : na, text_color = txt_color)
if show_range_avg
table.cell(tbl, 2, row, str.tostring(kz._range_store.avg()), text_size = range_size, text_color = txt_color)
if show_range and barstate.islast
var tbl = table.new(range_pos, 10, 10, chart.bg_color, chart.fg_color, 2, chart.fg_color, 1)
table.cell(tbl, 0, 0, "Killzone", text_size = range_size, text_color = txt_color)
table.cell(tbl, 1, 0, "Range", text_size = range_size, text_color = txt_color)
if show_range_avg
table.cell(tbl, 2, 0, "Avg (" + str.tostring(get_min_days_stored()) + ")", text_size = range_size, text_color = txt_color)
for in _kz
set_table(tbl, value._kz, index + 1, value.box_txt, not na(time("", value.session, gmt_tz)), value.c)
// ---------------------------------------- Core Logic --------------------------------------------------
Indicator
