IU Three Line Strike Candlestick PatternIU Three Line Strike Candlestick Pattern
This indicator identifies the Three Line Strike candlestick pattern — a rare yet powerful 4-bar reversal setup that captures exhaustion and momentum shifts at the end of strong trends.
Pattern Logic:
The Three Line Strike is a 4-candle pattern that typically signals a sharp reversal after a sustained directional move. This script detects both bullish and bearish variations using strict criteria to ensure accuracy.
Bullish Three Line Strike:
* Previous three candles must be bearish (red)
* Each of these candles must close progressively lower (indicating a strong downtrend)
* The current candle must:
* Be bullish (green)
* Open below the prior close
* Completely engulf the previous three candles by closing above the first candle's open
* And make a higher high than the last 3 bars — confirming a strong reversal
* Once confirmed, a green shaded box is drawn around the 4-bar zone to highlight the pattern
Bearish Three Line Strike:
* Previous three candles must be bullish (green)
* Each must close progressively higher (indicating a strong uptrend)
* The current candle must:
* Be bearish (red)
* Open above the prior close
* Completely engulf the prior three candles by closing below the first candle's open
* And make a lower low than the last 3 bars — confirming downside strength
* A red shaded box is plotted around the 4-bar formation to emphasize the reversal zone
Why this is unique:
Most candlestick tools focus on 1–2 bar patterns. The Three Line Strike goes a step further by combining trend exhaustion (3 same-colored candles) with a full reversal engulfing candle. This pattern is both rare and highly expressive of sentiment shift, making it a standout signal for discretionary and algorithmic traders alike.
How users can benefit:
* High-probability setups: Filters out weak signals using multi-bar confirmation logic
* Clear visual cues: Dynamic shaded boxes and labels make spotting reversals effortless
* Cross-timeframe compatible: Works on intraday and higher timeframes across all markets
* Real-time alerts: Get notified instantly when a bullish or bearish setup forms
This indicator is a valuable addition for traders who want to capture key reversals backed by strong multi-bar price action logic. Whether you are a price action purist or a pattern-based strategist, the IU Three Line Strike gives you a reliable edge.
Disclaimer:
This script is for educational purposes only and does not constitute financial advice. Trading involves risk, and past performance is not indicative of future results. Always do your own research and consult with a licensed financial advisor before making trading decisions.
Candlestick analysis
Liquidity + OB + FVG + Market StructureSmart Money Techniques using Liquidity sweep, FVG, OB, CHOCH/ BOS while aligning with BB, RSI. Support and Resistance key levels marked
Enigma Sniper 369The "Enigma Sniper 369" is a custom-built Pine Script indicator designed for TradingView, tailored specifically for forex traders seeking high-probability entries during high-volatility market sessions.
Unlike generic trend-following or scalping tools, this indicator uniquely combines session-based "kill zones" (London and US sessions), momentum-based candle analysis, and an optional EMA trend filter to pinpoint liquidity grabs and reversal opportunities.
Its originality lies in its focus on liquidity hunting—identifying levels where stop losses are likely clustered (around swing highs/lows and wick midpoints)—and providing visual entry zones that are dynamically removed once price breaches them, reducing clutter and focusing on actionable signals.
The name "369" reflects the structured approach of three key components (session timing, candle logic, and trend filter) working in harmony to snipe precise entries.
What It Does
"Enigma Sniper 369" identifies potential buy and sell opportunities by drawing two types of horizontal lines on the chart during user-defined London and US
session kill zones:
Solid Lines: Mark the swing low (for buys) or swing high (for sells) of a trigger candle, indicating a potential entry point where stop losses might be clustered.
Dotted Lines: Mark the 50% level of the candle’s wick (lower wick for buys, upper wick for sells), serving as a secondary confirmation zone for entries or tighter stop-loss placement.
These lines are plotted only when specific candle conditions are met within the kill zones, and they are automatically deleted once the price crosses them, signaling that the liquidity at that level has likely been grabbed. The indicator also includes an optional EMA filter to ensure trades align with the broader trend, reducing false signals in choppy markets.
How It Works
The indicator’s logic is built on a multi-layered approach:
Kill Zone Timing: Trades are only considered during user-defined London and US session hours (e.g., London from 02:00 to 12:00 UTC, as seen in the screenshots). These sessions are known for high volatility and liquidity, making them ideal for capturing institutional moves.
Candle-Based Momentum Logic:
Buy Signal: A candle must close above its midpoint (indicating bullish momentum) and have a lower low than the previous candle (suggesting a potential liquidity grab below the previous swing low). This is expressed as close > (high + low) / 2 and low < low .
Sell Signal: A candle must close below its midpoint (bearish momentum) and have a higher high than the previous candle (indicating a potential liquidity grab above the previous swing high), expressed as close < (high + low) / 2 and high > high .
These conditions ensure the indicator targets candles that break recent structure to hunt stop losses while showing directional momentum.
Optional EMA Filter: A 50-period EMA (customizable) can be enabled to filter signals based on trend direction.
Buy signals are only generated if the EMA is trending upward (ema_value > ema_value ), and sell signals require a downward EMA trend (ema_value < ema_value ). This reduces noise by aligning entries with the broader market trend.
Liquidity Levels and Deletion Logic:
For a buy signal, a solid green line is drawn at the candle’s low, and a dotted green line at the 50% level of the lower wick (from the candle body’s bottom to the low).
For a sell signal, a solid red line is drawn at the candle’s high, and a dotted red line at the 50% level of the upper wick (from the body’s top to the high).
These lines extend to the right until the price crosses them, at which point they are deleted, indicating the liquidity at that level has been taken (e.g., stop losses triggered).
Alerts: The indicator includes alert conditions for buy and sell signals, notifying traders when a new setup is identified.
Underlying Concepts
The indicator is grounded in the concept of liquidity hunting, a strategy often employed by institutional traders. Markets frequently move to levels where stop losses are clustered—typically just beyond swing highs or lows—before reversing in the opposite direction. The "Enigma Sniper 369" targets these moves by identifying candles that break structure (e.g., a lower low or higher high) during high-volatility sessions, suggesting a potential sweep of stop losses. The 50% wick level acts as a secondary confirmation, as this midpoint often represents a zone where tighter stop losses are placed by retail traders. The optional EMA filter adds a trend-following element, ensuring entries are taken in the direction of the broader market momentum, which is particularly useful on lower timeframes like the 15-minute chart shown in the screenshots.
How to Use It
Here’s a step-by-step guide based on the provided usage example on the GBP/USD 15-minute chart:
Setup the Indicator: Add "Enigma Sniper 369" to your TradingView chart. Adjust the London and US session hours to match your timezone (e.g., London from 02:00 to 12:00 UTC, US from 13:00 to 22:00 UTC). Customize the EMA period (default 50) and line styles/colors if desired.
Identify Kill Zones: The indicator highlights the London session in light green and the US session in light purple, as seen in the screenshots. Focus on these periods for signals, as they are the most volatile and likely to produce liquidity grabs.
Wait for a Signal: Look for solid and dotted lines to appear during the kill zones:
Buy Setup: A solid green line at the swing low and a dotted green line at the 50% lower wick level indicate a potential buy. This suggests the market may have grabbed liquidity below the swing low and is now poised to move higher.
Sell Setup: A solid red line at the swing high and a dotted red line at the 50% upper wick level indicate a potential sell, suggesting liquidity was taken above the swing high.
Place Your Trade:
For a buy, set a buy limit order at the dotted green line (50% wick level), as this is a more conservative entry point. Place your stop loss just below the solid green line (swing low) to cover the full swing. For example, in the screenshots, the market retraces to the dotted line at 1.32980 after a liquidity grab below the swing low, triggering a buy limit order.
For a sell, set a sell limit order at the dotted red line, with a stop loss just above the solid red line.
Monitor Price Action: Once the price crosses a line, it is deleted, indicating the liquidity at that level has been taken. In the screenshots, after the buy limit is triggered, the market moves higher, confirming the setup. The caption notes, “The market returns and tags us in long with a buy limit,” highlighting this retracement strategy.
Additional Context: Use the indicator to identify liquidity levels that may be targeted later. For example, the screenshot notes, “If a new session is about to open I will wait for the grab liquidity to go long,” showing how the indicator can be used to anticipate future moves at session opens (e.g., London open at 1.32980).
Risk Management: Always set a stop loss below the swing low (for buys) or above the swing high (for sells) to protect against adverse moves. The 50% wick level helps tighten entries, improving the risk-reward ratio.
Practical Example
On the GBP/USD 15-minute chart, during the London session (02:00 UTC), the indicator identifies a buy setup with a solid green line at 1.32901 (swing low) and a dotted green line at 1.32980 (50% wick level). The market initially dips below the swing low, grabbing liquidity, then retraces to the dotted line, triggering a buy limit order. The price subsequently rises to 1.33404, yielding a profitable trade. The user notes, “The logic is in the last candle it provides new level to go long,” emphasizing the indicator’s ability to identify fresh levels after a liquidity sweep.
Customization Tips
Adjust the EMA period to suit your timeframe (e.g., a shorter period like 20 for faster signals on lower timeframes).
Modify the session hours to align with your broker’s timezone or specific market conditions.
Use the alert feature to get notified of new setups without constantly monitoring the chart.
Why It’s Useful for Traders
The "Enigma Sniper 369" stands out by combining session timing, momentum-based candle analysis, and liquidity hunting into a single tool. It provides clear, actionable levels for entries and stop losses, removes invalid signals dynamically, and aligns trades with high-probability market conditions. Whether you’re a scalper looking for quick moves during London open or a swing trader targeting session-based reversals, this indicator offers a structured, data-driven approach to trading.
Custom Green Candle Signalbuying candle indicates...................................................................................................
Liquidity + OB + FVG + Market Structure [v2]Coach Tae's Confirmations by detecting liquidity sweeps along with FVG+ OB + Bos/Choch. See the best entry repeatedly as much as possible.
Liquidity + OB + FVG + Market Structure [v3]Liquidity sweep, FVG, and OB confirmation with BB, RSI, and 9/200 SMA assisting the fundmentals.
Sunday OpenThis indicator shows the opening price of the daily candle on Sunday .
This price range is a good confirmation for the price reversal. Also, this level is a strong range from which the price gives a good reaction .
This Sunday open line can be used as an additional confirmation to the trading strategy to have a clearer entry point.
Sideways + Buy + Sell Detection (Customizable)Yes, beyond the **methodology**, several additional professional aspects of your script can be highlighted, especially for documentation, presentations, or integrating into a proprietary toolkit. Here’s a breakdown of additional elements worth noting:
---
### **1. Indicator Design Philosophy**
The script reflects a **multi-factor confirmation model**, combining momentum, trend strength, and directional movement for higher confidence in signal accuracy. This reduces the likelihood of false signals caused by reliance on a single indicator.
---
### **2. Signal Filtering via Confluence**
By requiring alignment across **RSI**, **ADX/DI**, and **MACD**, the system enforces **signal confluence**, a best practice in professional technical analysis. This ensures that entries are only suggested when multiple independent tools agree on market direction, enhancing robustness.
---
### **3. Parameter Flexibility for Optimization**
All core variables—RSI length, ADX period, MACD settings, and thresholds—are exposed via inputs, allowing for:
* **Strategy optimization** through backtesting.
* **Market-specific adaptation**, adjusting sensitivity for equities, forex, commodities, or crypto.
This makes the script versatile across asset classes and trading environments.
---
### **4. Timeframe Decoupling**
By separating the signal generation timeframe from the chart timeframe, the script supports **top-down analysis**. For example:
* Signals can be generated on a 5-minute chart while trading on a 1-minute chart.
* A 1-hour signal can be monitored within a 15-minute execution chart.
This enhances decision-making by contextualizing intraday moves within higher-timeframe trends.
---
### **5. User Experience & Interface Integration**
* **Clear chart visuals**: The color-coded labels (green for buy, red for sell, purple for sideways) provide instant recognition.
* **Non-intrusive design**: Signals are plotted below bars to maintain a clean view of price action.
* **Title and inputs** are well-labeled for ease of use, aligning with best practices in indicator UI/UX design.
---
### **6. Use Cases & Applications**
* **Trend Traders**: Identify momentum-driven opportunities in the direction of strength.
* **Range Traders**: Detect periods of consolidation to apply mean-reversion strategies.
* **Algorithmic Signal Filters**: Serve as a filter layer within automated systems, only allowing trades when all criteria align.
* **Discretionary Traders**: Use as a secondary confirmation tool to validate setups seen through manual chart analysis.
---
### **7. Extensibility & Integration Potential**
This script can serve as a foundational module for:
* **Strategy scripts** (with backtesting logic),
* **Alerts** for real-time notifications (with minor modification),
* Or **integrated dashboards** in custom trading interfaces.
UT Bot + Hull MA Confirmed Signal DelayThis strategy identifies key momentum shifts by combining the UT Bot’s ATR-based trailing stop signals with confirmation from a Hull Moving Average (HMA) or its variants. It’s designed to filter signals and reduce false entries by requiring price action to cross the Hull MA in the direction of the UT Bot signal.
The indicator works especially well when used on Heikin Ashi charts and in alignment with the MACD trend, helping traders capture more reliable entry and exit points. By blending momentum detection with trend confirmation, this strategy aims to provide clearer buy and sell signals in trending markets.
Its not recommended to always buy or sell the signal it should be used in conjunction with technical analysis and price action.
Fosheezy BB 20emaMajor close (>50% of candle) outside bollinger band 2nd dev with next candle reversing back towards 20ema.
Sticky Candlestick Quarter Divider (Dynamic Update)This indicator divides the most recent candlestick into four equal parts and dynamically plots horizontal lines that move along with the latest candle.
Features:
Dynamic Sticky Lines:
The lines remain visually attached to the current candle, moving seamlessly as the chart updates, zooms, or pans.
Price Level Calculation:
Divides the candlestick into four distinct levels:
High Line (Red): Marks the highest point of the candle.
Low Line (Red): Marks the lowest point of the candle.
Midpoint Line (Blue): Marks the midpoint between high and low.
Upper Quarter Line (Green): Marks the 25% level between low and high.
Lower Quarter Line (Green): Marks the 75% level between low and high.
Real-Time Update:
The lines automatically adjust to the latest candle, maintaining accurate positioning.
Ideal for Candle Analysis:
Quickly identify key price levels and candle structure.
Suitable for analyzing trend strength and potential price reversals.
Liquidity + OB + FVG + Market Structure [v2]BB, RSI, and 9 and/ 200 SMA. Alongside with confirmations showing Liquidity sweep + OB + FVG + Bos/Choch. Smart Money traders perceptions!
NIFTY Option Chain Table with Custom CE/PE Price FiltersThis Pine Script creates a powerful and visually organized option chain dashboard for NIFTY Index Options, showing 10 Call Options (CE) and 10 Put Options (PE), with real-time prices updated on a 5-minute chart.
You can filter and view only the most relevant option contracts based on your preferred price ranges, helping you make quick decisions for scalping, intraday, or positional trades.
🔍 How It Works:
You manually select up to 10 Call Option symbols and 10 Put Option symbols from NSE (e.g., NIFTY240530C18000, NIFTY240530P18000, etc.).
Keep that time options this are old options in defalt so there will be a error
The script fetches the real-time close price of each option using the request.security() function.
You define the minimum and maximum price range separately for Calls and Puts.
The script filters out any options that fall outside of your desired price range.
Only a limited number of matching options (as set by you) are displayed in the table for both Calls and Puts.
The table is shown at your preferred location on the chart (Bottom Right, Top Left, etc.).
✅ Features:
🔟 Supports exactly 10 CE and 10 PE options for tracking.
📈 Live price updates pulled directly from the chart timeframe (5-min).
🎯 Custom price filters for CE and PE (separate inputs).
📊 Show only the top X number of contracts that meet your filter criteria.
🧱 Vertical layout with clear headers and color-coded sections (green for Calls, red for Puts).
🎛️ Position the table wherever it's most convenient on your chart.
⚡ Helps you quickly spot low premium or range-bound options during the day.
📌 Use Case:
Ideal for:
Option scalpers and day traders who want to focus only on options within a specific price zone.
Traders who want to monitor multiple strikes simultaneously without clutter.
Users building custom NIFTY strategies based on option premiums.
Any Divergence for Many Indicators v6The community-based modification of the Divergence for Many Indicators v4 version has been upgraded to Pine Script v6, with the addition of 3 integrated alert signals. These alerts can simultaneously trigger notifications for both top and bottom divergences, fully utilizing the alert conditions of the watchlist.
Sonic Simple Long & Short BiasHi Guys
This is one simple indicator help us find the Long (Buy) Bias or Short (Sell) Bias.
GOVIND// This source code is subject to the terms of the Mozilla Public License 2.0 at mozilla.org
// © iamsachinughade
//@version=5
indicator(title='GOVIND', overlay=true)
src = close
prd = input.int(defval=10, title='Pivot Period', minval=4, maxval=30, group='Setup')
ppsrc = input.string(defval='High/Low', title='Source', options= , group='Setup')
maxnumpp = input.int(defval=20, title=' Max Pivot', minval=5, maxval=100, group='Setup')
ChannelW = input.int(defval=10, title='Max Channel Width %', minval=1, group='Setup')
maxnumsr = input.int(defval=5, title=' Number of S&R', minval=1, maxval=10, group='Setup')
min_strength = input.int(defval=2, title=' Minimum Strength', minval=1, maxval=10, group='Setup')
labelloc = input.int(defval=20, title='Label Location', group='Colors', tooltip='Positive numbers reference future bars, negative numbers reference histical bars')
linestyle = input.string(defval='Dotted', title='Line Style', options= , group='Colors')
linewidth = input.int(defval=2, title='Line Width', minval=1, maxval=4, group='Colors')
resistancecolor = input.color(defval=color.red, title='Resistance Color', group='Colors')
supportcolor = input.color(defval=color.lime, title='Support Color', group='Colors')
showpp = input(false, title='Show High Low Points')
float src1 = ppsrc == 'High/Low' ? high : math.max(close, open)
float src2 = ppsrc == 'High/Low' ? low : math.min(close, open)
float ph = ta.pivothigh(src1, prd, prd)
float pl = ta.pivotlow(src2, prd, prd)
plotshape(ph and showpp, text='H', style=shape.labeldown, color=na, textcolor=color.new(color.red, 0), location=location.abovebar, offset=-prd)
plotshape(pl and showpp, text='L', style=shape.labelup, color=na, textcolor=color.new(color.lime, 0), location=location.belowbar, offset=-prd)
Lstyle = linestyle == 'Dashed' ? line.style_dashed : linestyle == 'Solid' ? line.style_solid : line.style_dotted
//calculate maximum S/R channel zone width
prdhighest = ta.highest(300)
prdlowest = ta.lowest(300)
cwidth = (prdhighest - prdlowest) * ChannelW / 100
var pivotvals = array.new_float(0)
if ph or pl
array.unshift(pivotvals, ph ? ph : pl)
if array.size(pivotvals) > maxnumpp // limit the array size
array.pop(pivotvals)
get_sr_vals(ind) =>
float lo = array.get(pivotvals, ind)
float hi = lo
int numpp = 0
for y = 0 to array.size(pivotvals) - 1 by 1
float cpp = array.get(pivotvals, y)
float wdth = cpp <= lo ? hi - cpp : cpp - lo
if wdth <= cwidth // fits the max channel width?
lo := cpp <= lo ? cpp : lo
hi := cpp > lo ? cpp : hi
numpp += 1
numpp
var sr_up_level = array.new_float(0)
var sr_dn_level = array.new_float(0)
sr_strength = array.new_float(0)
find_loc(strength) =>
ret = array.size(sr_strength)
for i = ret > 0 ? array.size(sr_strength) - 1 : na to 0 by 1
if strength <= array.get(sr_strength, i)
break
ret := i
ret
ret
check_sr(hi, lo, strength) =>
ret = true
for i = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
//included?
if array.get(sr_up_level, i) >= lo and array.get(sr_up_level, i) <= hi or array.get(sr_dn_level, i) >= lo and array.get(sr_dn_level, i) <= hi
if strength >= array.get(sr_strength, i)
array.remove(sr_strength, i)
array.remove(sr_up_level, i)
array.remove(sr_dn_level, i)
ret
else
ret := false
ret
break
ret
var sr_lines = array.new_line(11, na)
var sr_labels = array.new_label(11, na)
for x = 1 to 10 by 1
rate = 100 * (label.get_y(array.get(sr_labels, x)) - close) / close
label.set_text(array.get(sr_labels, x), text=str.tostring(label.get_y(array.get(sr_labels, x))) + '(' + str.tostring(rate, '#.##') + '%)')
label.set_x(array.get(sr_labels, x), x=bar_index + labelloc)
label.set_color(array.get(sr_labels, x), color=label.get_y(array.get(sr_labels, x)) >= close ? color.red : color.lime)
label.set_textcolor(array.get(sr_labels, x), textcolor=label.get_y(array.get(sr_labels, x)) >= close ? color.white : color.black)
label.set_style(array.get(sr_labels, x), style=label.get_y(array.get(sr_labels, x)) >= close ? label.style_label_down : label.style_label_up)
line.set_color(array.get(sr_lines, x), color=line.get_y1(array.get(sr_lines, x)) >= close ? resistancecolor : supportcolor)
if ph or pl
//because of new calculation, remove old S/R levels
array.clear(sr_up_level)
array.clear(sr_dn_level)
array.clear(sr_strength)
//find S/R zones
for x = 0 to array.size(pivotvals) - 1 by 1
= get_sr_vals(x)
if check_sr(hi, lo, strength)
loc = find_loc(strength)
// if strength is in first maxnumsr sr then insert it to the arrays
if loc < maxnumsr and strength >= min_strength
array.insert(sr_strength, loc, strength)
array.insert(sr_up_level, loc, hi)
array.insert(sr_dn_level, loc, lo)
// keep size of the arrays = 5
if array.size(sr_strength) > maxnumsr
array.pop(sr_strength)
array.pop(sr_up_level)
array.pop(sr_dn_level)
for x = 1 to 10 by 1
line.delete(array.get(sr_lines, x))
label.delete(array.get(sr_labels, x))
for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
rate = 100 * (mid - close) / close
array.set(sr_labels, x + 1, label.new(x=bar_index + labelloc, y=mid, text=str.tostring(mid) + '(' + str.tostring(rate, '#.##') + '%)', color=mid >= close ? color.red : color.lime, textcolor=mid >= close ? color.white : color.black, style=mid >= close ? label.style_label_down : label.style_label_up))
array.set(sr_lines, x + 1, line.new(x1=bar_index, y1=mid, x2=bar_index - 1, y2=mid, extend=extend.both, color=mid >= close ? resistancecolor : supportcolor, style=Lstyle, width=linewidth))
f_crossed_over() =>
ret = false
for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
if close <= mid and close > mid
ret := true
ret
ret
f_crossed_under() =>
ret = false
for x = 0 to array.size(sr_up_level) > 0 ? array.size(sr_up_level) - 1 : na by 1
float mid = math.round_to_mintick((array.get(sr_up_level, x) + array.get(sr_dn_level, x)) / 2)
if close >= mid and close < mid
ret := true
ret
ret
alertcondition(f_crossed_over(), title='Resistance Broken', message='Resistance Broken')
alertcondition(f_crossed_under(), title='Support Broken', message='Support Broken')
length = input.int(10, step=5, minval=5)
showZigzag = input(false)
showPivots = input(true)
showStats = input(true)
bullishColor = input(color.green)
bullTrapColor = input(color.orange)
bearishColor = input(color.red)
bearTrapColor = input(color.lime)
textColor = input(color.black)
MaxRiskPerReward = input.int(30, step=5, minval=5, maxval=100)
DisplayRiskPerReward = input(true)
var zigzagvalues = array.new_float(0)
var zigzagindexes = array.new_int(0)
var zigzagdir = array.new_int(0)
var doubleTopBottomValues = array.new_float(3)
var doubleTopBottomIndexes = array.new_int(3)
var doubleTopBottomDir = array.new_int(3)
int max_array_size = 10
max_bars_back(high, 1000)
max_bars_back(low, 1000)
var lineArray = array.new_line(0)
var labelArray = array.new_label(0)
pivots(length) =>
float ph = ta.highestbars(high, length) == 0 ? high : na
float pl = ta.lowestbars(low, length) == 0 ? low : na
dir = 0
iff_1 = pl and na(ph) ? -1 : dir
dir := ph and na(pl) ? 1 : iff_1
add_to_array(value, index, dir) =>
mult = array.size(zigzagvalues) < 2 ? 1 : dir * value > dir * array.get(zigzagvalues, 1) ? 2 : 1
array.unshift(zigzagindexes, index)
array.unshift(zigzagvalues, value)
array.unshift(zigzagdir, dir * mult)
if array.size(zigzagindexes) > max_array_size
array.pop(zigzagindexes)
array.pop(zigzagvalues)
array.pop(zigzagdir)
add_to_zigzag(dir, dirchanged, ph, pl, index) =>
value = dir == 1 ? ph : pl
if array.size(zigzagvalues) == 0 or dirchanged
add_to_array(value, index, dir)
else if dir == 1 and value > array.get(zigzagvalues, 0) or dir == -1 and value < array.get(zigzagvalues, 0)
array.shift(zigzagvalues)
array.shift(zigzagindexes)
array.shift(zigzagdir)
add_to_array(value, index, dir)
zigzag(length) =>
= pivots(length)
dirchanged = ta.change(dir)
if ph or pl
add_to_zigzag(dir, dirchanged, ph, pl, bar_index)
calculate_double_pattern() =>
doubleTop = false
doubleTopConfirmation = 0
doubleBottom = false
doubleBottomConfirmation = 0
if array.size(zigzagvalues) >= 4
index = array.get(zigzagindexes, 1)
value = array.get(zigzagvalues, 1)
highLow = array.get(zigzagdir, 1)
lindex = array.get(zigzagindexes, 2)
lvalue = array.get(zigzagvalues, 2)
lhighLow = array.get(zigzagdir, 2)
llindex = array.get(zigzagindexes, 3)
llvalue = array.get(zigzagvalues, 3)
llhighLow = array.get(zigzagdir, 3)
risk = math.abs(value - llvalue)
reward = math.abs(value - lvalue)
riskPerReward = risk * 100 / (risk + reward)
if highLow == 1 and llhighLow == 2 and lhighLow < 0 and riskPerReward < MaxRiskPerReward
doubleTop := true
doubleTop
if highLow == -1 and llhighLow == -2 and lhighLow > 0 and riskPerReward < MaxRiskPerReward
doubleBottom := true
doubleBottom
if doubleTop or doubleBottom
array.set(doubleTopBottomValues, 0, value)
array.set(doubleTopBottomValues, 1, lvalue)
array.set(doubleTopBottomValues, 2, llvalue)
array.set(doubleTopBottomIndexes, 0, index)
array.set(doubleTopBottomIndexes, 1, lindex)
array.set(doubleTopBottomIndexes, 2, llindex)
array.set(doubleTopBottomDir, 0, highLow)
array.set(doubleTopBottomDir, 1, lhighLow)
array.set(doubleTopBottomDir, 2, llhighLow)
get_crossover_info(doubleTop, doubleBottom) =>
index = array.get(doubleTopBottomIndexes, 0)
value = array.get(doubleTopBottomValues, 0)
highLow = array.get(doubleTopBottomDir, 0)
lindex = array.get(doubleTopBottomIndexes, 1)
lvalue = array.get(doubleTopBottomValues, 1)
lhighLow = array.get(doubleTopBottomDir, 1)
llindex = array.get(doubleTopBottomIndexes, 2)
llvalue = array.get(doubleTopBottomValues, 2)
llhighLow = array.get(doubleTopBottomDir, 2)
latestDoubleTop = false
latestDoubleBottom = false
latestDoubleTop := doubleTop ? true : doubleBottom ? false : latestDoubleTop
latestDoubleBottom := doubleBottom ? true : doubleTop ? false : latestDoubleBottom
doubleTopConfirmation = 0
doubleBottomConfirmation = 0
doubleTopConfirmation := latestDoubleTop ? ta.crossunder(low, lvalue) ? 1 : ta.crossover(high, llvalue) ? -1 : 0 : 0
doubleBottomConfirmation := latestDoubleBottom ? ta.crossover(high, lvalue) ? 1 : ta.crossunder(low, llvalue) ? -1 : 0 : 0
draw_double_pattern(doubleTop, doubleBottom, doubleTopConfirmation, doubleBottomConfirmation) =>
index = array.get(doubleTopBottomIndexes, 0)
value = array.get(doubleTopBottomValues, 0)
highLow = array.get(doubleTopBottomDir, 0)
lindex = array.get(doubleTopBottomIndexes, 1)
lvalue = array.get(doubleTopBottomValues, 1)
lhighLow = array.get(doubleTopBottomDir, 1)
llindex = array.get(doubleTopBottomIndexes, 2)
llvalue = array.get(doubleTopBottomValues, 2)
llhighLow = array.get(doubleTopBottomDir, 2)
isBullish = true
isBullish := doubleTop or doubleBottom ? doubleTop : isBullish
risk = math.abs(value - llvalue)
reward = math.abs(value - lvalue)
riskPerReward = risk * 100 / (risk + reward)
base = line.new(x1=index, y1=value, x2=llindex, y2=llvalue, color=doubleTop ? bearishColor : bullishColor, width=2, style=line.style_solid)
l1 = line.new(x1=index, y1=value, x2=lindex, y2=lvalue, color=doubleTop ? bearishColor : bullishColor, width=2, style=line.style_dotted)
l2 = line.new(x1=lindex, y1=lvalue, x2=llindex, y2=llvalue, color=doubleTop ? bearishColor : bullishColor, width=2, style=line.style_dotted)
labelText = (doubleTop ? 'Double Top' : 'Double Bottom') + (DisplayRiskPerReward ? ' RR - ' + str.tostring(riskPerReward) : '')
baseLabel = label.new(x=index, y=value, text=labelText, yloc=doubleTop ? yloc.abovebar : yloc.belowbar, color=doubleTop ? bearishColor : bullishColor, style=doubleTop ? label.style_label_down : label.style_label_up, textcolor=textColor, size=size.normal)
if not(doubleTop or doubleBottom)
line.delete(base)
line.delete(l1)
line.delete(l2)
label.delete(baseLabel)
var doubleTopCount = 0
var doubleBottomCount = 0
doubleTopCount := doubleTop ? nz(doubleTopCount , 0) + 1 : nz(doubleTopCount , 0)
doubleBottomCount := doubleBottom ? nz(doubleBottomCount , 0) + 1 : nz(doubleBottomCount , 0)
if line.get_x2(base) == line.get_x2(base )
line.delete(base )
line.delete(l1 )
line.delete(l2 )
label.delete(baseLabel )
doubleTopCount := doubleTop ? doubleTopCount - 1 : doubleTopCount
doubleBottomCount := doubleBottom ? doubleBottomCount - 1 : doubleBottomCount
doubleBottomCount
if barstate.islast
lres = line.new(x1=bar_index, y1=lvalue, x2=lindex, y2=lvalue, color=isBullish ? bearishColor : bullishColor, width=2, style=line.style_dashed, extend=extend.left)
lsup = line.new(x1=bar_index, y1=llvalue, x2=llindex, y2=llvalue, color=isBullish ? bullishColor : bearishColor, width=2, style=line.style_dashed, extend=extend.left)
lsup
doubleTopConfirmationCount = doubleTopConfirmation > 0 ? 1 : 0
doubleBottomConfirmationCount = doubleBottomConfirmation > 0 ? 1 : 0
doubleTopInvalidationCount = doubleTopConfirmation < 0 ? 1 : 0
doubleBottomInvalidationCount = doubleBottomConfirmation < 0 ? 1 : 0
if doubleTopConfirmation != 0 or doubleBottomConfirmation != 0
if doubleTopConfirmation > 0 or doubleBottomConfirmation > 0
lresbreak = line.new(x1=lindex, y1=lvalue, x2=bar_index, y2=lvalue, color=isBullish ? bearishColor : bullishColor, width=2, style=line.style_dashed)
if line.get_x1(lresbreak ) == line.get_x1(lresbreak)
doubleTopConfirmationCount := 0
doubleBottomConfirmationCount := 0
doubleTopInvalidationCount := 0
doubleBottomInvalidationCount := 0
line.delete(lresbreak)
lresbreak := lresbreak
lresbreak
else if doubleTopConfirmation < 0 or doubleBottomConfirmation < 0
lsupbreak = line.new(x1=llindex, y1=llvalue, x2=bar_index, y2=llvalue, color=isBullish ? bullishColor : bearishColor, width=2, style=line.style_dashed)
if line.get_x1(lsupbreak ) == line.get_x1(lsupbreak)
doubleTopInvalidationCount := 0
doubleBottomInvalidationCount := 0
doubleTopConfirmationCount := 0
doubleBottomConfirmationCount := 0
line.delete(lsupbreak)
lsupbreak := lsupbreak
lsupbreak
doubleTopConfirmationCount := nz(doubleTopConfirmationCount , 0) + doubleTopConfirmationCount
doubleBottomConfirmationCount := nz(doubleBottomConfirmationCount , 0) + doubleBottomConfirmationCount
doubleTopInvalidationCount := nz(doubleTopInvalidationCount , 0) + doubleTopInvalidationCount
doubleBottomInvalidationCount := nz(doubleBottomInvalidationCount , 0) + doubleBottomInvalidationCount
zigzag(length)
= calculate_double_pattern()
= get_crossover_info(doubleTop, doubleBottom)
= draw_double_pattern(doubleTop, doubleBottom, doubleTopConfirmation, doubleBottomConfirmation)
var stats = table.new(position=position.top_center, columns=5, rows=5, border_width=2)
if barstate.islast and showStats
colorWorst = color.rgb(255, 153, 51)
colorBest = color.rgb(51, 204, 51)
colorBad = color.rgb(255, 204, 153)
colorGood = color.rgb(204, 255, 204)
colorNeutral = color.rgb(255, 255, 204)
dtConfirmationPercent = doubleTopConfirmationCount + doubleTopInvalidationCount == 0 ? 0.5 : doubleTopConfirmationCount / (doubleTopConfirmationCount + doubleTopInvalidationCount)
dbConfirmationPercent = doubleBottomConfirmationCount + doubleBottomInvalidationCount == 0 ? 0.5 : doubleBottomConfirmationCount / (doubleBottomConfirmationCount + doubleBottomInvalidationCount)
dtColor = dtConfirmationPercent >= 0.8 ? colorBest : dtConfirmationPercent >= 0.6 ? colorGood : dtConfirmationPercent >= 0.4 ? colorNeutral : dtConfirmationPercent >= 0.2 ? colorBad : colorWorst
dbColor = dbConfirmationPercent >= 0.8 ? colorBest : dbConfirmationPercent >= 0.6 ? colorGood : dbConfirmationPercent >= 0.4 ? colorNeutral : dbConfirmationPercent >= 0.2 ? colorBad : colorWorst
table.cell(table_id=stats, column=0, row=0, text='', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=0, row=1, text='Double Top', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=0, row=2, text='Double Bottom', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=1, row=0, text='Count', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=2, row=0, text='Confirmation', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=3, row=0, text='Invalidation', bgcolor=color.black, text_color=color.white)
table.cell(table_id=stats, column=1, row=1, text=str.tostring(doubleTopCount), bgcolor=dtColor)
table.cell(table_id=stats, column=1, row=2, text=str.tostring(doubleBottomCount), bgcolor=dbColor)
table.cell(table_id=stats, column=2, row=1, text=str.tostring(doubleTopConfirmationCount), bgcolor=dtColor)
table.cell(table_id=stats, column=3, row=1, text=str.tostring(doubleTopInvalidationCount), bgcolor=dtColor)
table.cell(table_id=stats, column=2, row=2, text=str.tostring(doubleBottomConfirmationCount), bgcolor=dbColor)
table.cell(table_id=stats, column=3, row=2, text=str.tostring(doubleBottomInvalidationCount), bgcolor=dbColor)
if barstate.islast and array.size(zigzagindexes) > 1
lastHigh = 0.0
lastLow = 0.0
for x = 0 to array.size(zigzagindexes) - 1 by 1
i = array.size(zigzagindexes) - 1 - x
index = array.get(zigzagindexes, i)
value = array.get(zigzagvalues, i)
highLow = array.get(zigzagdir, i)
index_offset = bar_index - index
labelText = highLow == 2 ? 'HH' : highLow == 1 ? 'LH' : highLow == -1 ? 'HL' : 'LL'
labelColor = highLow == 2 ? bullishColor : highLow == 1 ? bullTrapColor : highLow == -1 ? bearTrapColor : bearishColor
labelStyle = highLow > 0 ? label.style_label_down : label.style_label_up
// labelLocation = highLow > 0? yloc.abovebar : yloc.belowbar
labelLocation = yloc.price
if showPivots
l = label.new(x=index, y=value, text=labelText, xloc=xloc.bar_index, yloc=labelLocation, style=labelStyle, size=size.tiny, color=labelColor, textcolor=textColor)
array.unshift(labelArray, l)
if array.size(labelArray) > 100
label.delete(array.pop(labelArray))
if i < array.size(zigzagindexes) - 1 and showZigzag
indexLast = array.get(zigzagindexes, i + 1)
valueLast = array.get(zigzagvalues, i + 1)
l = line.new(x1=index, y1=value, x2=indexLast, y2=valueLast, color=labelColor, width=2, style=line.style_solid)
array.unshift(lineArray, l)
if array.size(lineArray) > 100
line.delete(array.pop(lineArray))
alertcondition(doubleBottom, 'Double Bottom', 'Probable double bottom observed for {{ticker}} on {{interval}} timeframe')
alertcondition(doubleBottomConfirmation > 0, 'Double Bottom Confirmation', 'Double bottom confirmation observed for {{ticker}} on {{interval}} timeframe')
alertcondition(doubleBottomConfirmation < 0, 'Double Bottom Invalidation', 'Double bottom invalidation observed for {{ticker}} on {{interval}} timeframe')
alertcondition(doubleTop, 'Double Top', 'Probable double top observed for {{ticker}} on {{interval}} timeframe')
alertcondition(doubleTopConfirmation > 0, 'Double Top Confirmation', 'Double top confirmation observed for {{ticker}} on {{interval}} timeframe')
alertcondition(doubleTopConfirmation < 0, 'Double Top Invalidation', 'Double top invalidation observed for {{ticker}} on {{interval}} timeframe')
per = input.int(defval=100, minval=1, title='Sampling Period')
// Range Multiplier
mult = input.float(defval=2.0, minval=0.1, title='Range Multiplier')
// Smooth Average Range
smoothrng(x, t, m) =>
wper = t * 2 - 1
avrng = ta.ema(math.abs(x - x ), t)
smoothrng = ta.ema(avrng, wper) * m
smoothrng
smrng = smoothrng(src, per, mult)
// Range Filter
rngfilt(x, r) =>
rngfilt = x
rngfilt := x > nz(rngfilt ) ? x - r < nz(rngfilt ) ? nz(rngfilt ) : x - r : x + r > nz(rngfilt ) ? nz(rngfilt ) : x + r
rngfilt
filt = rngfilt(src, smrng)
// Filter Direction
upward = 0.0
upward := filt > filt ? nz(upward ) + 1 : filt < filt ? 0 : nz(upward )
downward = 0.0
downward := filt < filt ? nz(downward ) + 1 : filt > filt ? 0 : nz(downward )
// Target Bands
hband = filt + smrng
lband = filt - smrng
// Colors
filtcolor = upward > 0 ? color.lime : downward > 0 ? color.red : color.orange
barcolor = src > filt and src > src and upward > 0 ? color.lime : src > filt and src < src and upward > 0 ? color.green : src < filt and src < src and downward > 0 ? color.red : src < filt and src > src and downward > 0 ? color.maroon : color.orange
filtplot = plot(filt, color=filtcolor, linewidth=3, title='Range Filter')
// Target
hbandplot = plot(hband, color=color.new(color.aqua, 100), title='High Target')
lbandplot = plot(lband, color=color.new(color.fuchsia, 100), title='Low Target')
// Fills
fill(hbandplot, filtplot, color=color.new(color.aqua, 90), title='High Target Range')
fill(lbandplot, filtplot, color=color.new(color.fuchsia, 90), title='Low Target Range')
// Bar Color
barcolor(barcolor)
// Break Outs
longCond = bool(na)
shortCond = bool(na)
longCond := src > filt and src > src and upward > 0 or src > filt and src < src and upward > 0
shortCond := src < filt and src < src and downward > 0 or src < filt and src > src and downward > 0
CondIni = 0
CondIni := longCond ? 1 : shortCond ? -1 : CondIni
longCondition = longCond and CondIni == -1
shortCondition = shortCond and CondIni == 1
//Alerts
plotshape(longCondition, title='Buy Signal', text='BUY', textcolor=color.new(color.white, 0), style=shape.labelup, size=size.normal, location=location.belowbar, color=color.new(color.green, 0))
plotshape(shortCondition, title='Sell Signal', text='SELL', textcolor=color.new(color.white, 0), style=shape.labeldown, size=size.normal, location=location.abovebar, color=color.new(color.red, 0))
alertcondition(longCondition, title='Buy Alert', message='BUY')
alertcondition(shortCondition, title='Sell Alert', message='BUY')
Inside Bar (Body-based) Ind/AlertDescription:
This indicator detects Inside Bar patterns based strictly on the candle body (open/close range) of the mother candle, rather than the traditional high/low wick method. An inside bar is highlighted when the current candle’s entire body is contained within the body of the previous candle.
It can be useful for traders who want a more conservative and reliable definition of inside bars, focusing on true consolidation periods and filtering out signals caused by extended wicks.
Features:
Body-based Inside Bar detection:
The indicator colors and marks candles where the current bar’s body is fully within the previous bar’s body.
Bullish/Bearish identification:
Bullish inside bars are marked in green, bearish in red.
Double Inside Bar Detection:
An optional feature marks when two consecutive candles’ bodies are inside the same mother bar body—potentially indicating stronger consolidation.
Alerts:
Set alerts for single or double inside bars for automated monitoring.
How to Use:
Add the indicator to your chart.
Look for colored bars or plotted shapes for inside bar signals based on candle bodies.
Use alerts to get notified in real time when inside bar patterns appear.
Note:
This script uses only the candle body (open and close) for inside bar calculations, which may help filter out less reliable signals found with wick-based approaches.
Full Rejection Alerts (Bullish & Bearish)- Bearish Engulfing
- Bearish Pin Bar
- Bullish Engulfing
- Bullish Pin Bar
📊 Portfolio TrackerPortfolio Tracker
🧠 How This Script Works
This Pine Script generates a dynamic portfolio table in the upper-right corner of your chart. It:
Monitors your positions in: BTC, SOL, ADA, XRP, and XAU (Gold).
Calculates for each asset:
Current value,
Profit/Loss in your currency ,
Percentage change.
Color-coded output:
🟢 Green = Profit
🔴 Red = Loss
Automatically updates every few candles.
Tracks total portfolio value, PnL, and % return.
Triggers custom alerts when:
Total portfolio profit exceeds +5% or +10%.
🛠️ How to Customize It for Your Own Portfolio
🔹 1. Update your personal asset data
Inside the // === INPUTS === section of the code, modify these lines:
btc1_qty = 0.0013
btc1_entry = 72831.80
Repeat for each asset you own:
Replace xxx_qty with your amount.
Replace xxx_entry with your buy price (in your currency).
Make sure the request.security(...) line fetches the correct symbol.
🔹 2. Add more assets (optional)
Duplicate any block like ADA and change the variable names and symbols:
new_qty = ...
new_entry = ...
new_price = request.security("BINANCE:NEWTOKENUSD", timeframe.period, close)
Also include the new asset in:
total_pnl += ...
total_value_now += ...
total_cost += ...
The table.cell(...) block to show it in the table.
Why This Tool Rocks
Tracks all your holdings in one chart panel.
Requires no API or external data feed.
Real-time updates based on TradingView chart prices.
Fully editable and extendable to any other token or asset.
5 Min ORB with ExtensionsThis Indicator marks the first RTH 5 minute high and low with the extensions levels