BoaBias: Fractals + FVG [FREE]BoaBias: Fractals + FVG is a professional market structure analysis indicator that combines advanced fractals and Fair Value Gaps (FVG) with multi-timeframe support.
✨ Key Features
🔷 Advanced Fractals
Fractal Type Detection: Automatic identification of Day/Week/Month/Day+Week fractals
Smart Break Detection: Breakouts are checked on corresponding timeframes
3 or 5 Bar Fractals: Adjustable sensitivity
Visual Support/Resistance Lines: Clear display of key levels
📈 Fair Value Gaps (FVG)
Current Timeframe FVG: Automatic detection and display of zones
HTF FVG Support: FVG analysis across multiple timeframes (1H, 4H, 12H, 1D, 3D, 1W, 1M)
Auto Removal: Filled zones are automatically removed
Color Customization: Separate colors for bullish and bearish zones
🎯 Who is this indicator for?
Traders using market structure analysis
Those working with fractals and FVG
Multi-timeframe traders
Anyone who wants to visually see key levels and zones
⚙️ Settings
Fractals
Fractal period (3 or 5 bars)
Line width
Maximum active levels
Display window (last N bars)
Break detection settings (body only or with wicks)
FVG
Enable/disable FVG
HTF timeframe configuration
Colors for bullish and bearish zones
Automatic removal of filled zones
Maximum HTF zones count
💡 Advantages
✅ Clean Visual Analysis — Only lines and zones, no clutter
✅ Multi-Timeframe Analysis — See structure across different timeframes simultaneously
✅ Smart Fractal Logic — Automatic identification of important levels
✅ Professional Tool — Used in real trading
Indicateurs Bill Williams
Multi-MA Crossover Alert by Funded RelayMulti-MA Crossover Alert is a simple yet powerful trend-following indicator that combines three moving averages to help identify trend direction and potential reversal points.
What it shows:
• Fast SMA (default 20 periods) – reacts quickly to price changes
• Medium EMA (default 50 periods) – smoother medium-term trend
• Slow SMA (default 200 periods) – long-term trend reference (often called the "death/golden cross" level)
Features:
• Dynamic coloring: Lines turn green when above the slow SMA (bullish bias) or red when below (bearish bias). The slow SMA stays gray for clear reference.
• Background tint: Light green/red background highlights the overall trend based on Fast SMA vs Slow SMA.
• Crossover alerts: Triggers notifications when the Medium EMA crosses above/below the Slow SMA (classic trend change signal).
How to interpret the signals:
• Bullish trend: Fast and Medium lines are green and above the Slow SMA → price is in an uptrend. Look for buying opportunities on pullbacks.
• Bearish trend: Fast and Medium lines are red and below the Slow SMA → price is in a downtrend. Look for selling/short opportunities on rallies.
• Bullish crossover (alert): Medium EMA crosses ABOVE Slow SMA → potential start of stronger uptrend or reversal from downtrend.
• Bearish crossover (alert): Medium EMA crosses BELOW Slow SMA → potential start of stronger downtrend or reversal from uptrend.
How to use it correctly:
1. Add the indicator to your chart via "Indicators" → Community Scripts.
2. Adjust the input lengths to match your timeframe and style:
- Shorter periods (e.g. 10/30/100) → better for intraday / scalping
- Longer periods (e.g. 50/100/200) → better for swing / position trading
3. Enable "Enable Crossover Alerts" if you want TradingView notifications (set alerts via the alert menu: condition = "alert() function calls only").
4. Use in combination with:
- Support/resistance levels
- Volume confirmation
- Other indicators (RSI for overbought/oversold, candlestick patterns)
5. Best on higher timeframes (1H, 4H, Daily) to reduce noise. On very low timeframes, false signals increase — always confirm with price action.
Important notes:
• This is NOT a standalone "buy/sell" system — no indicator is 100% accurate. Always use risk management (stop-loss, position sizing).
• Backtest on your assets/timeframes before live trading.
• Works on all markets: stocks, forex, crypto, futures, etc.
Open-source and free — feel free to modify and improve!
Happy trading!
Sonic R 89 - NY buy LionLee 079 228 1999//@version=5
indicator("Sonic R 89 - NY SL Custom Fixed", overlay=true, max_lines_count=500)
// --- 0. TÙY CHỈNH THÔNG SỐ ---
group_session = "Cài đặt Phiên Giao Dịch (Giờ New York)"
use_session = input.bool(true, "Chỉ giao dịch theo khung giờ", group=group_session)
session_time = input.session("0800-1200", "Khung giờ NY 1", group=group_session)
session_time2 = input.session("1300-1700", "Khung giờ NY 2", group=group_session)
max_trades_per_session = input.int(1, "Số lệnh tối đa/mỗi khung giờ", minval=1, group=group_session)
group_risk = "Quản lý Rủi ro (Dashboard)"
risk_usd = input.float(100.0, "Số tiền rủi ro mỗi lệnh ($)", minval=1.0, group=group_risk)
group_sl_custom = "Cấu hình Stop Loss (SL)"
sl_mode = input.string("Dragon", "Chế độ SL", options= , group=group_sl_custom)
lookback_x = input.int(5, "Số nến (X) cho Swing SL", minval=1, group=group_sl_custom)
group_htf = "Lọc Đa khung thời gian (MTF)"
htf_res = input.timeframe("30", "Chọn khung HTF", group=group_htf)
group_sonic = "Cấu hình Sonic R"
vol_mult = input.float(1.5, "Đột biến Volume", minval=1.0)
max_waves = input.int(4, "Ưu tiên n nhịp đầu", minval=1)
trade_cd = input.int(5, "Khoảng cách lệnh (nến)", minval=1)
group_tp = "Quản lý SL/TP & Dòng kẻ"
rr_tp1 = input.float(1.0, "TP1 (RR)", step=0.1)
rr_tp2 = input.float(2.0, "TP2 (RR)", step=0.1)
rr_tp3 = input.float(3.0, "TP3 (RR)", step=0.1)
rr_tp4 = input.float(4.0, "TP4 (RR)", step=0.1)
line_len = input.int(15, "Chiều dài dòng kẻ", minval=1)
// --- 1. KIỂM TRA PHIÊN & HTF ---
is_in_sess1 = not na(time(timeframe.period, session_time, "America/New_York"))
is_in_sess2 = not na(time(timeframe.period, session_time2, "America/New_York"))
is_in_session = use_session ? (is_in_sess1 or is_in_sess2) : true
var int trades_count = 0
is_new_session = is_in_session and not is_in_session
if is_new_session
trades_count := 0
htf_open = request.security(syminfo.tickerid, htf_res, open, lookahead=barmerge.lookahead_on)
htf_close = request.security(syminfo.tickerid, htf_res, close, lookahead=barmerge.lookahead_on)
is_htf_trend = htf_close >= htf_open ? 1 : -1
// --- 2. TÍNH TOÁN CHỈ BÁO ---
ema89 = ta.ema(close, 89)
ema34H = ta.ema(high, 34)
ema34L = ta.ema(low, 34)
atr = ta.atr(14)
avgVol = ta.sma(volume, 20)
slope89 = (ema89 - ema89 ) / atr
hasSlope = math.abs(slope89) > 0.12
isSqueezed = math.abs(ta.ema(close, 34) - ema89) < (atr * 0.5)
var int waveCount = 0
if not hasSlope
waveCount := 0
newWave = hasSlope and ((low <= ema34H and close > ema34H) or (high >= ema34L and close < ema34L))
if newWave and not newWave
waveCount := waveCount + 1
// --- 3. LOGIC VÀO LỆNH ---
isMarubozu = math.abs(close - open) / (high - low) > 0.8
highVol = volume > avgVol * vol_mult
buyCondition = is_in_session and (trades_count < max_trades_per_session) and waveCount <= max_waves and is_htf_trend == 1 and
(isMarubozu or highVol) and close > ema34H and low >= ema89 and
(slope89 > 0.1 or isSqueezed ) and close > open
sellCondition = is_in_session and (trades_count < max_trades_per_session) and waveCount <= max_waves and is_htf_trend == -1 and
(isMarubozu or highVol) and close < ema34L and high <= ema89 and
(slope89 < -0.1 or isSqueezed ) and close < open
// --- 4. QUẢN LÝ LỆNH ---
var float last_entry = na
var float last_sl = na
var float last_tp1 = na
var float last_tp2 = na
var float last_tp3 = na
var float last_tp4 = na
var string last_type = "NONE"
var int lastBar = 0
trigger_buy = buyCondition and (bar_index - lastBar > trade_cd)
trigger_sell = sellCondition and (bar_index - lastBar > trade_cd)
// --- 5. TÍNH TOÁN SL & LOT SIZE ---
float contract_size = 1.0
if str.contains(syminfo.ticker, "XAU") or str.contains(syminfo.ticker, "GOLD")
contract_size := 100
// Logic tính SL linh hoạt
float swing_low = ta.lowest(low, lookback_x)
float swing_high = ta.highest(high, lookback_x)
float temp_sl_calc = na
if trigger_buy
temp_sl_calc := (sl_mode == "Dragon") ? ema34L : swing_low
if trigger_sell
temp_sl_calc := (sl_mode == "Dragon") ? ema34H : swing_high
float sl_dist_calc = math.abs(close - temp_sl_calc)
float calc_lots = (sl_dist_calc > 0) ? (risk_usd / (sl_dist_calc * contract_size)) : 0
if (trigger_buy or trigger_sell)
trades_count := trades_count + 1
lastBar := bar_index
last_type := trigger_buy ? "BUY" : "SELL"
last_entry := close
last_sl := temp_sl_calc
float riskAmt = math.abs(last_entry - last_sl)
last_tp1 := trigger_buy ? last_entry + (riskAmt * rr_tp1) : last_entry - (riskAmt * rr_tp1)
last_tp2 := trigger_buy ? last_entry + (riskAmt * rr_tp2) : last_entry - (riskAmt * rr_tp2)
last_tp3 := trigger_buy ? last_entry + (riskAmt * rr_tp3) : last_entry - (riskAmt * rr_tp3)
last_tp4 := trigger_buy ? last_entry + (riskAmt * rr_tp4) : last_entry - (riskAmt * rr_tp4)
// Vẽ dòng kẻ
line.new(bar_index, last_entry, bar_index + line_len, last_entry, color=color.new(color.gray, 50), width=2)
line.new(bar_index, last_sl, bar_index + line_len, last_sl, color=color.red, width=2, style=line.style_dashed)
line.new(bar_index, last_tp1, bar_index + line_len, last_tp1, color=color.green, width=1)
line.new(bar_index, last_tp2, bar_index + line_len, last_tp2, color=color.lime, width=1)
line.new(bar_index, last_tp3, bar_index + line_len, last_tp3, color=color.aqua, width=1)
line.new(bar_index, last_tp4, bar_index + line_len, last_tp4, color=color.blue, width=2)
// KÍCH HOẠT ALERT()
string alert_msg = (trigger_buy ? "BUY " : "SELL ") + syminfo.ticker + " at " + str.tostring(close) + " | SL Mode: " + sl_mode + " | Lot: " + str.tostring(calc_lots, "#.##") + " | SL: " + str.tostring(last_sl, format.mintick)
alert(alert_msg, alert.freq_once_per_bar_close)
// --- 6. CẢNH BÁO CỐ ĐỊNH ---
alertcondition(trigger_buy, title="Sonic R BUY Alert", message="Sonic R BUY Signal Detected")
alertcondition(trigger_sell, title="Sonic R SELL Alert", message="Sonic R SELL Signal Detected")
// --- 7. DASHBOARD & PLOT ---
var table sonic_table = table.new(position.top_right, 2, 10, bgcolor=color.new(color.black, 70), border_width=1, border_color=color.gray)
if barstate.islast
table.cell(sonic_table, 0, 0, "NY SESSION", text_color=color.white), table.cell(sonic_table, 1, 0, last_type, text_color=(last_type == "BUY" ? color.lime : color.red))
table.cell(sonic_table, 0, 1, "SL Mode:", text_color=color.white), table.cell(sonic_table, 1, 1, sl_mode, text_color=color.orange)
table.cell(sonic_table, 0, 2, "Trades this Sess:", text_color=color.white), table.cell(sonic_table, 1, 2, str.tostring(trades_count) + "/" + str.tostring(max_trades_per_session), text_color=color.yellow)
table.cell(sonic_table, 0, 3, "LOT SIZE:", text_color=color.orange), table.cell(sonic_table, 1, 3, str.tostring(calc_lots, "#.##"), text_color=color.orange)
table.cell(sonic_table, 0, 4, "Entry:", text_color=color.white), table.cell(sonic_table, 1, 4, str.tostring(last_entry, format.mintick), text_color=color.yellow)
table.cell(sonic_table, 0, 5, "SL:", text_color=color.white), table.cell(sonic_table, 1, 5, str.tostring(last_sl, format.mintick), text_color=color.red)
table.cell(sonic_table, 0, 6, "TP1:", text_color=color.gray), table.cell(sonic_table, 1, 6, str.tostring(last_tp1, format.mintick), text_color=color.green)
table.cell(sonic_table, 0, 7, "TP2:", text_color=color.gray), table.cell(sonic_table, 1, 7, str.tostring(last_tp2, format.mintick), text_color=color.lime)
table.cell(sonic_table, 0, 8, "TP3:", text_color=color.gray), table.cell(sonic_table, 1, 8, str.tostring(last_tp3, format.mintick), text_color=color.aqua)
table.cell(sonic_table, 0, 9, "TP4:", text_color=color.gray), table.cell(sonic_table, 1, 9, str.tostring(last_tp4, format.mintick), text_color=color.blue)
plot(ema89, color=slope89 > 0.1 ? color.lime : slope89 < -0.1 ? color.red : color.gray, linewidth=2)
p_high = plot(ema34H, color=color.new(color.blue, 80))
p_low = plot(ema34L, color=color.new(color.blue, 80))
fill(p_high, p_low, color=color.new(color.blue, 96))
plotshape(trigger_buy, "BUY", shape.triangleup, location.belowbar, color=color.green, size=size.small)
plotshape(trigger_sell, "SELL", shape.triangledown, location.abovebar, color=color.red, size=size.small)
bgcolor(isSqueezed ? color.new(color.yellow, 92) : na)
bgcolor(not is_in_session ? color.new(color.gray, 96) : na)
Nasser kurdi | PRO PACK nasser kurdi fulllllll before
lllllllllllllllllllllllllllllllllll llllllllllllllllllllllllllll
Moving Average Exponential//@version=6
indicator(title="Moving Average Exponential", shorttitle="EMA", overlay=true, timeframe="", timeframe_gaps=true)
len = input.int(9, minval=1, title="Length")
src = input(close, title="Source")
offset = input.int(title="Offset", defval=0, minval=-500, maxval=500, display = display.data_window)
out = ta.ema(src, len)
plot(out, title="EMA", color=color.blue, offset=offset)
// Smoothing MA inputs
GRP = "Smoothing"
TT_BB = "Only applies when 'SMA + Bollinger Bands' is selected. Determines the distance between the SMA and the bands."
maTypeInput = input.string("None", "Type", options = , group = GRP, display = display.data_window)
var isBB = maTypeInput == "SMA + Bollinger Bands"
maLengthInput = input.int(14, "Length", group = GRP, display = display.data_window, active = maTypeInput != "None")
bbMultInput = input.float(2.0, "BB StdDev", minval = 0.001, maxval = 50, step = 0.5, tooltip = TT_BB, group = GRP, display = display.data_window, active = isBB)
var enableMA = maTypeInput != "None"
// Smoothing MA Calculation
ma(source, length, MAtype) =>
switch MAtype
"SMA" => ta.sma(source, length)
"SMA + Bollinger Bands" => ta.sma(source, length)
"EMA" => ta.ema(source, length)
"SMMA (RMA)" => ta.rma(source, length)
"WMA" => ta.wma(source, length)
"VWMA" => ta.vwma(source, length)
// Smoothing MA plots
smoothingMA = enableMA ? ma(out, maLengthInput, maTypeInput) : na
smoothingStDev = isBB ? ta.stdev(out, maLengthInput) * bbMultInput : na
plot(smoothingMA, "EMA-based MA", color=color.yellow, display = enableMA ? display.all : display.none, editable = enableMA)
bbUpperBand = plot(smoothingMA + smoothingStDev, title = "Upper Bollinger Band", color=color.green, display = isBB ? display.all : display.none, editable = isBB)
bbLowerBand = plot(smoothingMA - smoothingStDev, title = "Lower Bollinger Band", color=color.green, display = isBB ? display.all : display.none, editable = isBB)
fill(bbUpperBand, bbLowerBand, color= isBB ? color.new(color.green, 90) : na, title="Bollinger Bands Background Fill", display = isBB ? display.all : display.none, editable = isBB)
SessionsBuilt to display useful time sessions, mostly Frankfort and NY.
It also display the Asian range and fractal bars.
All three sub indicators are toggable separatly.
Works best for french trades as it's how it's been coded for.
If you want adapt it to your timezone, edit the "Fuseau horaire" option to match yours.
I intend to add another big indicator to make a cool package in the future.
I will soon try to make everything editable so you can chose what you can display (dont ask for when)
This is a full vibe coded script, feel free to fork it and edit it to your convenience as long as you credit me and share me yours so we can see what can be improved.
Enjoy :)
SWEEP HTF CANDLE - BY LIONLEE - 0792281999// This source code is subject to the terms of the Mozilla Public License 2.0 at mozilla.org
// © CandelaCharts
//@version=6
indicator("CandelaCharts - HTF Sweeps", shorttitle = "CandelaCharts - HTF Sweeps", overlay = true, max_lines_count = 500, max_labels_count = 500, max_boxes_count = 500, max_bars_back = 500, max_polylines_count = 100)
// # ========================================================================= #
// # | Colors |
// # ========================================================================= #
//#region
// # Core -------------------------------------------------------------------- #
colors_white = color.white
colors_black = color.black
colors_purple = color.purple
colors_red = color.red
colors_gray = color.gray
colors_blue = color.blue
colors_orange = color.orange
colors_green = color.green
color_transparent = #ffffff00
//#endregion
// # ========================================================================= #
// # | End |
// # ========================================================================= #
// # ========================================================================= #
// # | Inputs |
// # ========================================================================= #
//#region
// # General ----------------------------------------------------------------- #
general_font = input.string("Monospace", "Text ", options = , inline = "1.0", group = "General")
general_text = input.string("Tiny", "", options = , inline = "1.0", group = "General")
general_brand_show = input.bool(false, "Hide Brand", group = "General")
htf_sweeps_tf_1_show = input.bool(true, "HTF I ", inline = "1.0", group = "Timeframes")
htf_sweeps_tf_1_tf = input.timeframe("15", "", inline = "1.0", group = "Timeframes")
htf_sweeps_tf_1_number = input.int(10, "", inline = "1.0", group = "Timeframes", minval = 1, maxval = 60)
htf_sweeps_tf_1_map = input.bool(false, "M", inline = "1.0", group = "Timeframes", tooltip = "Map this HTF to LTF")
htf_sweeps_tf_2_show = input.bool(true, "HTF II ", inline = "2.0", group = "Timeframes")
htf_sweeps_tf_2_tf = input.timeframe("60", "", inline = "2.0", group = "Timeframes")
htf_sweeps_tf_2_number = input.int(8, "", inline = "2.0", group = "Timeframes", minval = 1, maxval = 60)
htf_sweeps_tf_2_map = input.bool(true, "M", inline = "2.0", group = "Timeframes")
htf_sweeps_tf_3_show = input.bool(true, "HTF III ", inline = "3.0", group = "Timeframes")
htf_sweeps_tf_3_tf = input.timeframe("240", "", inline = "3.0", group = "Timeframes")
htf_sweeps_tf_3_number = input.int(6, "", inline = "3.0", group = "Timeframes", minval = 1, maxval = 60)
htf_sweeps_tf_3_map = input.bool(false, "M", inline = "3.0", group = "Timeframes")
htf_sweeps_tf_4_show = input.bool(true, "HTF IV ", inline = "4.0", group = "Timeframes")
htf_sweeps_tf_4_tf = input.timeframe("1D", "", inline = "4.0", group = "Timeframes")
htf_sweeps_tf_4_number = input.int(4, "", inline = "4.0", group = "Timeframes", minval = 1, maxval = 60)
htf_sweeps_tf_4_map = input.bool(false, "M", inline = "4.0", group = "Timeframes")
htf_sweeps_tf_5_show = input.bool(true, "HTF V ", inline = "5.0", group = "Timeframes")
htf_sweeps_tf_5_tf = input.timeframe("1W", "", inline = "5.0", group = "Timeframes")
htf_sweeps_tf_5_number = input.int(2, "", inline = "5.0", group = "Timeframes", minval = 1, maxval = 60)
htf_sweeps_tf_5_map = input.bool(false, "M", inline = "5.0", group = "Timeframes")
htf_sweeps_tf_6_show = input.bool(false, "HTF VI ", inline = "6.0", group = "Timeframes")
htf_sweeps_tf_6_tf = input.timeframe("1M", "", inline = "6.0", group = "Timeframes")
htf_sweeps_tf_6_number = input.int(1, "", inline = "6.0", group = "Timeframes", minval = 1, maxval = 60)
htf_sweeps_tf_6_map = input.bool(false, "M", inline = "6.0", group = "Timeframes")
htf_sweeps_bull_color = input.color(colors_green, "Coloring ", inline = "1.0", group = "HTF")
htf_sweeps_bear_color = input.color(colors_black, "", inline = "1.0", group = "HTF")
htf_sweeps_wick_border_color = input.color(colors_black, "", inline = "1.0", group = "HTF")
htf_sweeps_offset = input.int(10, "Offset ", minval = 1, inline = "2.0", group = "HTF", tooltip = "The distance from the current chart candles.")
htf_sweeps_space = input.int(1, "Space ", minval = 1, inline = "3.0", maxval = 4, group = "HTF", tooltip = "Space between candles")
htf_sweeps_margin = input.int(10, "Margin ", minval = 1, inline = "4.0", group = "HTF", tooltip = "The distance between HTF group candles.")
htf_sweeps_candle_width = input.string("Small", "Size ", inline = "5.0", group = "HTF", options = , tooltip = "Candle size")
htf_sweeps_label_show = input.bool(true, "Labels ", inline = "6.0", group = "HTF")
htf_sweeps_label_size = input.string("Large", "", inline = "6.0", group = "HTF", options = )
htf_sweeps_label_position = input.string("Top", "", inline = "6.0", group = "HTF", options = , tooltip = " - Size of the label - Position of the label - Text color of the label")
htf_sweeps_label_color = input.color(colors_black, "", inline = "6.0", group = "HTF")
// htf_sweeps_bias_show = input.bool(true, "Bias ", inline = "6.0", group = "HTF")
// htf_sweeps_bias_bull_color = input.color(colors_green, "", inline = "6.0", group = "HTF")
// htf_sweeps_bias_bear_color = input.color(colors_red, "", inline = "6.0", group = "HTF")
// htf_sweeps_time_show = input.bool(true, "Time ", inline = "7.0", group = "HTF")
// htf_sweeps_time_color = input.color(colors_gray, "", inline = "7.0", group = "HTF")
htf_sweeps_ltf_trace_h_l_show = input.bool(true, "H/L Line ", inline = "1.0", group="LTF")
htf_sweeps_ltf_trace_h_l_style = input.string('····', '', options = , inline = "1.0", group="LTF")
htf_sweeps_ltf_trace_h_l_width = input.int(1, '', inline = "1.0", minval = 0, maxval = 4, group="LTF")
htf_sweeps_ltf_trace_h_l_color = input.color(color.new(colors_gray, 50), "", inline = "1.0", group="LTF")
htf_sweeps_ltf_trace_o_c_line_show = input.bool(true, "O/C Line ", inline = "2.0", group = "LTF")
htf_sweeps_ltf_trace_o_c_line_style = input.string('⎯⎯⎯', "", options = , inline = "2.0", group = "LTF")
htf_sweeps_ltf_trace_o_c_line_width = input.int(1, '', inline = "2.0", minval = 0, maxval = 4, group = "LTF")
htf_sweeps_ltf_trace_o_c_line_color = input.color(color.new(colors_gray, 50), "", inline = "2.0", group = "LTF")
htf_sweeps_sweep_show = input.bool(true, "Sweep ", inline = "1.0", group = "Sweep")
htf_sweeps_sweep_ltf_show = input.bool(true, "LTF ", inline = "1.0", group = "Sweep")
htf_sweeps_sweep_htf_show = input.bool(true, "HTF", inline = "1.0", group = "Sweep", tooltip = "Show sweeps. - Show sweeps on LTF. - Show sweeps on HTF.")
htf_sweeps_sweep_line_style = input.string('⎯⎯⎯', " ", options = , inline = "1.1", group = "Sweep")
htf_sweeps_sweep_line_width = input.int(1, '', inline = "1.1", group = "Sweep")
htf_sweeps_sweep_line_color = input.color(colors_black, "", inline = "1.1", group = "Sweep")
htf_sweeps_i_sweep_show = input.bool(false, "I-sweep ", inline = "2.0", group = "Sweep")
htf_sweeps_i_sweep_ltf_show = input.bool(true, "LTF ", inline = "2.0", group = "Sweep")
htf_sweeps_i_sweep_htf_show = input.bool(true, "HTF", inline = "2.0", group = "Sweep", tooltip = "Show invalidated sweeps. - Show invalidated sweeps on LTF. - Show invalidated sweeps on HTF.")
htf_sweeps_i_sweep_line_style = input.string('----', " ", options = , inline = "2.1", group = "Sweep")
htf_sweeps_i_sweep_line_width = input.int(1, '', inline = "2.1", group = "Sweep")
htf_sweeps_i_sweep_line_color = input.color(colors_gray, "", inline = "2.1", group = "Sweep")
htf_sweeps_real_time_sweep_show = input.bool(false, "Real-time", inline = "3.0", group = "Sweep", tooltip = "Control visibility of Real-time Sweeps on LTF and HTF")
// htf_sweeps_dashboard_info_show = input.bool(true, "Panel ", inline = "1.0", group = "Dashboard")
// htf_sweeps_dashboard_info_position = input.string("Bottom Center", "", options = , inline = "1.0", group = "Dashboard", tooltip = "The dashboard will display only the HTF that is mapped to LTF")
htf_sweeps_alerts_sweep_formation = input.bool(false, "Sweep Formation", inline = "1.0", group = "Alerts")
htf_sweeps_alerts_sweep_invalidation = input.bool(false, "Sweep Invalidation", inline = "2.0", group = "Alerts")
//#endregion
// # ========================================================================= #
// # | End |
// # ========================================================================= #
// # ========================================================================= #
// # | UDTs |
// # ========================================================================= #
//#region
type UDT_Store
line bin_ln
box bin_box
label bin_lbl
polyline bin_polyline
type UDT_Sweep
string tf
int x1
float y
int x2
bool bull
// sweep is invalidated
bool invalidated = false
// id of htf candle, that invalidated sweep
int invalidated_on
// if sweep is invalidated on candle that forms a sweep, then sweep will be removed
bool removed = false
// mark sweep as formed after last candle that forms a sweep is closed and sweep was not invalidated
bool formed = false
type UDT_HTF_Candle
int num
int index
string tf
// real coordinates of HTF candle
float o
float c
float h
float l
int o_idx
int c_idx
int h_idx
int l_idx
int ot
int ct
// position of HTF candle on chart
int candle_left
int candle_rigth
float candle_top
float candle_bottom
int wick_x
int shift
bool is_closed
array htf_sweeps
array ltf_sweeps
bool bull
bool bull_sweep
bool bear_sweep
//#endregion
// # ========================================================================= #
// # | End |
// # ========================================================================= #
// # ========================================================================= #
// # | Bin |
// # ========================================================================= #
//#region
var UDT_Store bin = UDT_Store.new(
bin_ln = array.new()
, bin_box = array.new()
, bin_lbl = array.new()
, bin_polyline = array.new()
)
method clean_bin(UDT_Store store) =>
for obj in store.bin_ln
obj.delete()
for obj in store.bin_box
obj.delete()
for obj in store.bin_lbl
obj.delete()
for obj in store.bin_polyline
obj.delete()
store.bin_ln.clear()
store.bin_box.clear()
store.bin_lbl.clear()
store.bin_polyline.clear()
//#endregion
// # ========================================================================= #
// # | End |
// # ========================================================================= #
// # ========================================================================= #
// # | Functions |
// # ========================================================================= #
//#region
method text_size(string size) =>
out = switch size
"Tiny" => size.tiny
"Small" => size.small
"Normal" => size.normal
"Large" => size.large
"Huge" => size.huge
"Auto" => size.auto
out
method line_style(string style) =>
out = switch style
'⎯⎯⎯' => line.style_solid
'----' => line.style_dashed
'····' => line.style_dotted
method font_style(string font) =>
out = switch font
'Default' => font.family_default
'Monospace' => font.family_monospace
method candle_size(string size) =>
out = switch size
'Tiny' => 2
'Small' => 4
'Medium' => 6
'Large' => 8
'Huge' => 10
out
method tf_label(string tf) =>
tfl = tf
if tfl == ''
tfl := timeframe.period
out = switch tfl
'1' => '1m'
'2' => '2m'
'3' => '3m'
'5' => '5m'
'10' => '10m'
'15' => '15m'
'20' => '20m'
'30' => '30m'
'45' => '45m'
'60' => '1H'
'90' => '90m'
'120' => '2H'
'180' => '3H'
'240' => '4H'
'480' => '8H'
'540' => '9H'
'720' => '12H'
=> tfl
out
const string default_tz = "America/New_York"
var string htf_sweeps_tz = default_tz
get_short_dayofweek(int d) =>
switch d
dayofweek.monday => 'MON'
dayofweek.tuesday => 'TUE'
dayofweek.wednesday => 'WED'
dayofweek.thursday => 'THU'
dayofweek.friday => 'FRI'
dayofweek.saturday => 'SAT'
dayofweek.sunday => 'SUN'
=> ''
get_week_of_month(int t) =>
y = year(t)
m = month(t)
d = dayofmonth(t)
// Timestamp of first day of the same month
firstDay = timestamp(y, m, 1, 0, 0)
// Day of month index starting from 0 → (0–30)
dayIndex = d - 1
// Week index starting from 0 → (0–4)
weekIndex = int(dayIndex / 7)
// Week number starting from 1 → (1–5)
str.tostring(weekIndex + 1)
get_short_month(int t) =>
var string months = array.from(
"JAN", "FEB", "MAR", "APR", "MAY", "JUN",
"JUL", "AUG", "SEP", "OCT", "NOV", "DEC")
m = month(t)
m >= 1 and m <= array.size(months) ? array.get(months, m - 1) : ""
method candle_time_label(UDT_HTF_Candle candle) =>
string lbl = ""
if timeframe.in_seconds(candle.tf) >= timeframe.in_seconds("12M")
lbl := str.format_time(candle.ot, "yyyy", htf_sweeps_tz)
else if timeframe.in_seconds(candle.tf) >= timeframe.in_seconds("1M")
lbl := get_short_month(candle.ot)
else if timeframe.in_seconds(candle.tf) >= timeframe.in_seconds("1W")
lbl := get_week_of_month(candle.ot)
else if timeframe.in_seconds(candle.tf) >= timeframe.in_seconds("1D")
// Get date components in the selected timezone
y = year(candle.ot, htf_sweeps_tz)
m = month(candle.ot, htf_sweeps_tz)
d = dayofmonth(candle.ot, htf_sweeps_tz)
// Create timestamp at noon for that date in the selected timezone (using noon to avoid timezone edge cases)
date_ts = timestamp(htf_sweeps_tz, y, m, d, 12, 0, 0)
// Add 1 day to account for timezone offset
date_ts := date_ts + 86400000
// Get day of week for that date
lbl := get_short_dayofweek(dayofweek(date_ts, htf_sweeps_tz))
else
lbl := str.format_time(candle.ot, "HH:mm", htf_sweeps_tz)
lbl
// Returns formatted remaining time until current HTF candle close.
// Format: " HH:MM:SS"
get_htf_remaining_time(int from, string tf, string ses, string tz) =>
ct = time_close(tf, ses, na(tz) ? "" : tz)
if na(ct) or na(from)
""
else
// Remaining time in ms (clamped to 0 so it never goes negative)
remaining_ms = math.max(ct - from, 0)
// Total whole seconds remaining
remaining_sec = int(remaining_ms / 1000)
// Unit constants (seconds)
sec_per_min = 60
sec_per_hour = 60 * sec_per_min
sec_per_day = 24 * sec_per_hour
sec_per_month = 30 * sec_per_day
sec_per_year = 365 * sec_per_day
// Break down into Y / M / D / H / M / S (all ints)
years = int(remaining_sec / sec_per_year)
rem_after_years = remaining_sec % sec_per_year
months = int(rem_after_years / sec_per_month)
rem_after_months = rem_after_years % sec_per_month
days = int(rem_after_months / sec_per_day)
rem_after_days = rem_after_months % sec_per_day
hours = int(rem_after_days / sec_per_hour)
rem_after_hours = rem_after_days % sec_per_hour
minutes = int(rem_after_hours / sec_per_min)
seconds = rem_after_hours % sec_per_min
// Only show non-zero units
year_str = years > 0 ? str.format("{0}Y ", str.tostring(years, "#")) : ""
month_str = months > 0 ? str.format("{0}M ", str.tostring(months, "#")) : ""
day_str = days > 0 ? str.format("{0}D ", str.tostring(days, "#")) : ""
time_str = str.format("{0}:{1}:{2}",
str.tostring(hours, "00"),
str.tostring(minutes, "00"),
str.tostring(seconds, "00"))
year_str + month_str + day_str + time_str
//#endregion
// # ========================================================================= #
// # | End |
// # ========================================================================= #
// # ========================================================================= #
// # | Variables |
// # ========================================================================= #
//#region
var ltf = timeframe.period
var htf_1_candles = array.new()
var htf_2_candles = array.new()
var htf_3_candles = array.new()
var htf_4_candles = array.new()
var htf_5_candles = array.new()
var htf_6_candles = array.new()
var htf_candle_width = candle_size(htf_sweeps_candle_width)
//#endregion
// # ========================================================================= #
// # | End |
// # ========================================================================= #
// # ========================================================================= #
// # | Alert Methods |
// # ========================================================================= #
//#region
method enable_sweep_formed_alert(UDT_Sweep sweep) =>
if not na(sweep) and htf_sweeps_alerts_sweep_formation
if not sweep.invalidated
if sweep.bull
alert(str.format("Bullish HTF Sweep ({0}) formed on {1}. Price level {2, number, currency}", tf_label(sweep.tf), syminfo.ticker, sweep.y))
else
alert(str.format("Bearish HTF Sweep ({0}) formed on {1}. Price level {2, number, currency}", tf_label(sweep.tf), syminfo.ticker, sweep.y))
sweep
method enable_sweep_invalidated_alert(UDT_Sweep sweep) =>
if not na(sweep) and htf_sweeps_alerts_sweep_invalidation
if not sweep.invalidated
if sweep.bull
alert(str.format("Bullish HTF Sweep ({0}) invalidated on {1}. Price level {2, number, currency}", tf_label(sweep.tf), syminfo.ticker, sweep.y))
else
alert(str.format("Bearish HTF Sweep ({0}) invalidated on {1}. Price level {2, number, currency}", tf_label(sweep.tf), syminfo.ticker, sweep.y))
sweep
//#endregion
// # ========================================================================= #
// # | End |
// # ========================================================================= #
// # ========================================================================= #
// # | HTF Sweeps |
// # ========================================================================= #
//#region
method session_begins(string tf, string ses, string tz) =>
ta.change(time(tf, ses, na(tz) ? "" : tz))!= 0
method in_session(string tf, string ses, string tz) =>
t = time(tf, ses, na(tz) ? "" : tz)
ct = time_close(tf, ses, na(tz) ? "" : tz)
not na(t) and not na(ct)
method position_ltf_sweeps(array htf_candles) =>
count = htf_candles.size()
if count == 1
candle = htf_candles.get(0)
for in candle.ltf_sweeps
sweep.x2 := candle.c_idx
if count >= 2
candle = htf_candles.get(1)
next_candle = htf_candles.get(0)
for in candle.ltf_sweeps
sweep.x2 := next_candle.c_idx
htf_candles
method position_htf_sweeps(array htf_candles, int buffer) =>
count = htf_candles.size()
if count > 1
c_last = htf_candles.get(0)
for in htf_candles
for in candle.htf_sweeps
sweep.x2 := c_last.candle_rigth + buffer
sweep.x1 := candle.wick_x
htf_candles
method invalidate_sweep(UDT_Sweep sweep, UDT_HTF_Candle c2) =>
c2_bull = c2.bull
// if body of next candle cross sweep
invalidated = not na(sweep.y) and (sweep.bull ? (c2_bull ? sweep.y < c2.c : sweep.y < c2.o) : (c2_bull ? sweep.y > c2.o : sweep.y > c2.c))
invalidated
method invalidate_sweeps(array htf_candles) =>
count = htf_candles.size()
if count > 1
for i = count - 1 to 1
c1 = htf_candles.get(i)
for in c1.ltf_sweeps
if not sweep.removed and na(sweep.invalidated_on)
for k = i - 1 to 0
c2 = htf_candles.get(k)
htf_sweep = c1.htf_sweeps.get(j)
invalidated = sweep.invalidate_sweep(c2)
// invalidation by candle of sweep
if sweep.x2 <= c2.c_idx and sweep.x2 > c2.o_idx
if not c2.is_closed
if not sweep.invalidated and htf_sweeps_real_time_sweep_show
sweep.enable_sweep_invalidated_alert()
sweep.invalidated := invalidated
htf_sweep.invalidated := sweep.invalidated
else
if invalidated and na(sweep.invalidated_on)
sweep.invalidated_on := invalidated ? c2.o_idx : na
htf_sweep.invalidated_on := sweep.invalidated_on
break
else if na(sweep.invalidated_on)
// invalidation by the next candle
if not c2.is_closed
if not sweep.invalidated and htf_sweeps_real_time_sweep_show
sweep.enable_sweep_invalidated_alert()
sweep.invalidated := invalidated
htf_sweep.invalidated := sweep.invalidated
else
if invalidated
if not sweep.invalidated
sweep.enable_sweep_invalidated_alert()
sweep.invalidated := invalidated
sweep.invalidated_on := invalidated ? c2.o_idx : na
htf_sweep.invalidated := sweep.invalidated
htf_sweep.invalidated_on := sweep.invalidated_on
break
// filter removed sweeps
c2 = htf_candles.get(i - 1)
if not sweep.formed and not sweep.removed
if c2.is_closed
htf_sweep = c1.htf_sweeps.get(j)
if sweep.invalidated and not na(sweep.invalidated_on)
// if sweep is invalidated on candle that forms a sweep, then sweep will be removed
if not sweep.formed
sweep.removed := true
htf_sweep.removed := true
else
// mark sweep as formed after last candle that forms a sweep is closed and sweep was not invalidated
if not sweep.formed
sweep.formed := true
htf_sweep.formed := true
htf_candles
detect_sweep(UDT_HTF_Candle c1, UDT_HTF_Candle c2) =>
c1_bull = c1.bull
c2_bull = c2.bull
bull_sweep_in_range = c2_bull ? (c1_bull ? (c2.c < c1.h) : (c2.c < c1.h)) : (c1_bull ? (c2.o < c1.h) : (c2.o < c1.h))
is_bull_sweep = c2.h > c1.h and bull_sweep_in_range
bear_sweep_in_range = c2_bull ? (c1_bull ? (c2.o > c1.l) : (c2.o > c1.l)) : (c1_bull ? (c2.c > c1.l) : (c2.c > c1.l))
is_bear_sweep = c2.l < c1.l and bear_sweep_in_range
if is_bull_sweep
if not c1.bull_sweep
htf_sweep = UDT_Sweep.new(x1=c1.h_idx, x2=c2.c_idx, y=c1.h, bull=true, tf=c1.tf)
ltf_sweep = UDT_Sweep.new(x1=c1.h_idx, x2=c2.c_idx, y=c1.h, bull=true, tf=c1.tf)
c1.htf_sweeps.push(htf_sweep)
c1.ltf_sweeps.push(ltf_sweep)
c1.bull_sweep := true
ltf_sweep.enable_sweep_formed_alert()
else if is_bear_sweep
if not c1.bear_sweep
htf_sweep = UDT_Sweep.new(x1=c1.l_idx, x2=c2.c_idx, y=c1.l, bull=false, tf=c1.tf)
ltf_sweep = UDT_Sweep.new(x1=c1.l_idx, x2=c2.c_idx, y=c1.l, bull=false, tf=c1.tf)
c1.htf_sweeps.push(htf_sweep)
c1.ltf_sweeps.push(ltf_sweep)
c1.bear_sweep := true
ltf_sweep.enable_sweep_formed_alert()
method detect_sweeps(array htf_candles) =>
count = htf_candles.size()
if count > 1
size = math.min(4, count - 1)
for i = size to 1
c1 = htf_candles.get(i)
c2 = htf_candles.get(i - 1)
if not c2.is_closed and c1.htf_sweeps.size() <= 2
detect_sweep(c1, c2)
htf_candles.position_ltf_sweeps()
htf_candles.invalidate_sweeps()
htf_candles
method draw_sweep(UDT_Sweep sweep, bool ltf) =>
if sweep.invalidated
if htf_sweeps_i_sweep_show
if ltf and htf_sweeps_i_sweep_ltf_show or not ltf and htf_sweeps_i_sweep_htf_show
if htf_sweeps_real_time_sweep_show ? true : not sweep.removed and not na(sweep.invalidated_on)
bin.bin_ln.push(line.new(x1=sweep.x1, y1=sweep.y, x2=sweep.x2, y2=sweep.y, xloc = xloc.bar_index, color = htf_sweeps_i_sweep_line_color, style = line_style(htf_sweeps_i_sweep_line_style), width = htf_sweeps_i_sweep_line_width))
else
if htf_sweeps_sweep_show
if ltf and htf_sweeps_sweep_ltf_show or not ltf and htf_sweeps_sweep_htf_show
bin.bin_ln.push(line.new(x1=sweep.x1, y1=sweep.y, x2=sweep.x2, y2=sweep.y, xloc = xloc.bar_index, color = htf_sweeps_sweep_line_color, style = line_style(htf_sweeps_sweep_line_style), width = htf_sweeps_sweep_line_width))
sweep
is_bullish_candle(float c, float o, float h, float l) =>
if c == o
math.abs(o - h) < math.abs(o - l)
else
c > o
method add_htf_candle(array htf_candles, UDT_HTF_Candle candle, int total_candles_number)=>
if not na(candle)
if htf_candles.size() >= total_candles_number
htf_candles.pop()
htf_candles.unshift(candle)
htf_candles
method detect_htf_candle(array htf_candles, string tf, string ltf) =>
UDT_HTF_Candle htf_candle = na
if session_begins(tf, "", na) or htf_candles.size()==0
UDT_HTF_Candle candle = UDT_HTF_Candle.new(tf = tf, htf_sweeps = array.new(), ltf_sweeps = array.new())
candle.o := open
candle.c := close
candle.h := high
candle.l := low
candle.o_idx := bar_index
candle.c_idx := bar_index
candle.h_idx := bar_index
candle.l_idx := bar_index
candle.ot := time
candle.bull := is_bullish_candle(candle.c, candle.o, candle.h, candle.l)
if htf_candles.size() > 0
last_candle = htf_candles.get(0)
last_candle.is_closed := true
last_candle.ct := time
htf_candle := candle
else if in_session(tf, "", na) and htf_candles.size()>0
candle = htf_candles.first()
candle.c := close
candle.c_idx := bar_index + 1
candle.ct := time
if high > candle.h
candle.h := high
candle.h_idx := bar_index
if low < candle.l
candle.l := low
candle.l_idx := bar_index
candle.bull := is_bullish_candle(candle.c, candle.o, candle.h, candle.l)
htf_candle
get_htf_candle_shift(int candle_index, int offset, int buffer, int width, int candles_amount)=>
offset + (width + buffer) * (candles_amount - candle_index - 1)
method position_htf_candle(UDT_HTF_Candle candle, int candle_index, int offset, int buffer, int width, int candles_amount) =>
candle.shift := get_htf_candle_shift(candle_index, offset, buffer, width, candles_amount)
candle.candle_left := last_bar_index + candle.shift
candle.candle_rigth := candle.candle_left + width
candle.candle_top := math.max(candle.o, candle.c)
candle.candle_bottom := math.min(candle.o, candle.c)
candle.wick_x := candle.candle_left + width/2
candle
method position_htf_candles(array htf_candles, int shift) =>
candles_amount = htf_candles.size()
for in htf_candles
candle.position_htf_candle(index, shift, htf_sweeps_space, htf_candle_width, candles_amount)
method draw_htf_candle(UDT_HTF_Candle candle) =>
candle_color = candle.bull ? htf_sweeps_bull_color : htf_sweeps_bear_color
bin.bin_box.push(box.new(left=candle.candle_left, top=candle.candle_top, right=candle.candle_rigth, bottom=candle.candle_bottom, border_color = htf_sweeps_wick_border_color, border_width = 1, bgcolor = candle_color))
bin.bin_ln.push(line.new(x1=candle.wick_x, y1=candle.h, x2=candle.wick_x, y2=candle.candle_top, color = htf_sweeps_wick_border_color))
bin.bin_ln.push(line.new(x1=candle.wick_x, y1=candle.candle_bottom, x2=candle.wick_x, y2=candle.l, color = htf_sweeps_wick_border_color))
candle
method draw_htf_label(array htf_candles, string tf) =>
float y_top = na
float y_bottom = na
int x_min = na
int x_max = na
for in htf_candles
switch htf_sweeps_label_position
"Both" =>
y_top := na(y_top) ? candle.h : math.max(y_top, candle.h)
y_bottom := na(y_bottom) ? candle.l : math.min(y_bottom, candle.l)
"Top" =>
y_top := na(y_top) ? candle.h : math.max(y_top, candle.h)
"Bottom" =>
y_bottom := na(y_bottom) ? candle.l : math.min(y_bottom, candle.l)
x_min := na(x_min) ? candle.wick_x : math.min(x_min, candle.wick_x)
x_max := na(x_max) ? candle.wick_x : math.max(x_max, candle.wick_x)
// time label for HTF candle
txt = candle.candle_time_label()
bin.bin_lbl.push(label.new(x = candle.wick_x, y = candle.l, text = txt, tooltip = str.format("HTF candle open {0}", str.format_time(candle.ot, "yyyy-MM-dd HH:mm Z", htf_sweeps_tz)), xloc=xloc.bar_index, color=color_transparent, style = label.style_label_up, textcolor = htf_sweeps_label_color, size=text_size("Tiny"), text_font_family=font_style(general_font)))
x = math.round(math.avg(x_min, x_max))
txt = tf_label(tf)
remaining_ms = get_htf_remaining_time(timenow, tf, "", na)
if not na(y_top)
bin.bin_lbl.push(label.new(x = x, y = y_top, text = txt, tooltip = str.format("HTF {0}", txt), xloc=xloc.bar_index, color=color_transparent, style=label.style_label_down, textcolor=htf_sweeps_label_color, size=text_size(htf_sweeps_label_size), text_font_family=font_style(general_font)))
bin.bin_lbl.push(label.new(x = x, y = y_top, text = remaining_ms, tooltip = str.format("Time remaining until active HTF candle close {0}", remaining_ms), xloc=xloc.bar_index, color=color_transparent, style=label.style_label_down, textcolor=htf_sweeps_label_color, size=text_size("Tiny"), text_font_family=font_style(general_font)))
if not na(y_bottom)
bin.bin_lbl.push(label.new(x = x, y = y_bottom, text = txt, tooltip = str.format("HTF {0}", txt), xloc=xloc.bar_index, color=color_transparent, style=label.style_label_up, textcolor=htf_sweeps_label_color, size=text_size(htf_sweeps_label_size), text_font_family=font_style(general_font)))
// if htf_sweeps_bias_show and htf_candles.size() > 1
// c1 = htf_candles.get(0)
// c2 = htf_candles.get(1)
// bullish = c1.h > c2.h and c1.l > c2.l
// bearish = c1.h < c2.h and c1.l < c2.l
// bin.bin_lbl.push(label.new(x = x, y = na(y_top) ? y_bottom : y_top, text = " ", xloc=xloc.bar_index, color = bullish ? htf_sweeps_bias_bull_color : htf_sweeps_bias_bear_color, style = bullish ? label.style_arrowup : label.style_arrowdown, size = size.normal))
htf_candles
method draw_ltf_open_close_line(UDT_HTF_Candle candle) =>
y1 = math.min(candle.o, candle.c)
y2 = math.max(candle.c, candle.o)
bin.bin_ln.push(line.new(x1=candle.ot, y1=y1, x2=candle.ot, y2=y2, xloc = xloc.bar_time, extend = extend.both, color = htf_sweeps_ltf_trace_o_c_line_color, style = line_style(htf_sweeps_ltf_trace_o_c_line_style), width = htf_sweeps_ltf_trace_o_c_line_width))
candle
method draw_ltf_high_line(UDT_HTF_Candle candle) =>
bin.bin_ln.push(line.new(x1=candle.ot, y1=candle.h, x2=candle.ct, y2=candle.h, xloc = xloc.bar_time, extend = extend.none, color = htf_sweeps_ltf_trace_h_l_color, style = line_style(htf_sweeps_ltf_trace_h_l_style), width = htf_sweeps_ltf_trace_h_l_width))
candle
method draw_ltf_low_line(UDT_HTF_Candle candle) =>
bin.bin_ln.push(line.new(x1=candle.ot, y1=candle.l, x2=candle.ct, y2=candle.l, xloc = xloc.bar_time, extend = extend.none, color = htf_sweeps_ltf_trace_h_l_color, style = line_style(htf_sweeps_ltf_trace_h_l_style), width = htf_sweeps_ltf_trace_h_l_width))
candle
method plot_ltf(array htf_candles) =>
for in htf_candles
if htf_sweeps_ltf_trace_o_c_line_show
candle.draw_ltf_open_close_line()
if htf_sweeps_ltf_trace_h_l_show
candle.draw_ltf_high_line()
candle.draw_ltf_low_line()
for in candle.ltf_sweeps
ltf_sweep.draw_sweep(true)
htf_candles
method plot_htf(array htf_candles, string tf, bool ltf_map) =>
htf_candles.position_htf_sweeps(htf_sweeps_space)
for in htf_candles
candle.draw_htf_candle()
for in candle.htf_sweeps
htf_sweep.draw_sweep(false)
if htf_sweeps_label_show
htf_candles.draw_htf_label(tf)
if ltf_map
htf_candles.plot_ltf()
htf_candles
//#endregion
// # ========================================================================= #
// # | End |
// # ========================================================================= #
// # ========================================================================= #
// # | Plotting |
// # ========================================================================= #
//#region
bin.clean_bin()
var tf_1_show = htf_sweeps_tf_1_show and timeframe.in_seconds(timeframe.period) < timeframe.in_seconds(htf_sweeps_tf_1_tf)
var tf_2_show = htf_sweeps_tf_2_show and timeframe.in_seconds(timeframe.period) < timeframe.in_seconds(htf_sweeps_tf_2_tf)
var tf_3_show = htf_sweeps_tf_3_show and timeframe.in_seconds(timeframe.period) < timeframe.in_seconds(htf_sweeps_tf_3_tf)
var tf_4_show = htf_sweeps_tf_4_show and timeframe.in_seconds(timeframe.period) < timeframe.in_seconds(htf_sweeps_tf_4_tf)
var tf_5_show = htf_sweeps_tf_5_show and timeframe.in_seconds(timeframe.period) < timeframe.in_seconds(htf_sweeps_tf_5_tf)
var tf_6_show = htf_sweeps_tf_6_show and timeframe.in_seconds(timeframe.period) < timeframe.in_seconds(htf_sweeps_tf_6_tf)
if tf_1_show
htf_1_candle = htf_1_candles.detect_htf_candle(htf_sweeps_tf_1_tf, ltf)
htf_1_candles.add_htf_candle(htf_1_candle, htf_sweeps_tf_1_number)
htf_1_candles.detect_sweeps()
if tf_2_show
htf_2_candle = htf_2_candles.detect_htf_candle(htf_sweeps_tf_2_tf, ltf)
htf_2_candles.add_htf_candle(htf_2_candle, htf_sweeps_tf_2_number)
htf_2_candles.detect_sweeps()
if tf_3_show
htf_3_candle = htf_3_candles.detect_htf_candle(htf_sweeps_tf_3_tf, ltf)
htf_3_candles.add_htf_candle(htf_3_candle, htf_sweeps_tf_3_number)
htf_3_candles.detect_sweeps()
if tf_4_show
htf_4_candle = htf_4_candles.detect_htf_candle(htf_sweeps_tf_4_tf, ltf)
htf_4_candles.add_htf_candle(htf_4_candle, htf_sweeps_tf_4_number)
htf_4_candles.detect_sweeps()
if tf_5_show
htf_5_candle = htf_5_candles.detect_htf_candle(htf_sweeps_tf_5_tf, ltf)
htf_5_candles.add_htf_candle(htf_5_candle, htf_sweeps_tf_5_number)
htf_5_candles.detect_sweeps()
if tf_6_show
htf_6_candle = htf_6_candles.detect_htf_candle(htf_sweeps_tf_6_tf, ltf)
htf_6_candles.add_htf_candle(htf_6_candle, htf_sweeps_tf_6_number)
htf_6_candles.detect_sweeps()
if barstate.islast
offset = htf_sweeps_offset
if tf_1_show
htf_1_candles.position_htf_candles(offset)
htf_1_candles.plot_htf(htf_sweeps_tf_1_tf, htf_sweeps_tf_1_map)
offset += get_htf_candle_shift(0, htf_sweeps_margin, htf_sweeps_space, htf_candle_width, htf_sweeps_tf_1_number)
if tf_2_show
htf_2_candles.position_htf_candles(offset)
htf_2_candles.plot_htf(htf_sweeps_tf_2_tf, htf_sweeps_tf_2_map)
offset += get_htf_candle_shift(0, htf_sweeps_margin, htf_sweeps_space, htf_candle_width, htf_sweeps_tf_2_number)
if tf_3_show
htf_3_candles.position_htf_candles(offset)
htf_3_candles.plot_htf(htf_sweeps_tf_3_tf, htf_sweeps_tf_3_map)
offset += get_htf_candle_shift(0, htf_sweeps_margin, htf_sweeps_space, htf_candle_width, htf_sweeps_tf_3_number)
if tf_4_show
htf_4_candles.position_htf_candles(offset)
htf_4_candles.plot_htf(htf_sweeps_tf_4_tf, htf_sweeps_tf_4_map)
offset += get_htf_candle_shift(0, htf_sweeps_margin, htf_sweeps_space, htf_candle_width, htf_sweeps_tf_4_number)
if tf_5_show
htf_5_candles.position_htf_candles(offset)
htf_5_candles.plot_htf(htf_sweeps_tf_5_tf, htf_sweeps_tf_5_map)
offset += get_htf_candle_shift(0, htf_sweeps_margin, htf_sweeps_space, htf_candle_width, htf_sweeps_tf_5_number)
if tf_6_show
htf_6_candles.position_htf_candles(offset)
htf_6_candles.plot_htf(htf_sweeps_tf_6_tf, htf_sweeps_tf_6_map)
//#endregion
// # ========================================================================= #
// # | End |
// # ========================================================================= #
// # ========================================================================= #
// # | Brand |
// # ========================================================================= #
//#region
if barstate.isfirst and general_brand_show == false
var table brand = table.new(position.bottom_right, 1, 1, bgcolor = chart.bg_color)
table.cell(brand, 0, 0, "© CandelaCharts", text_color = colors_gray, text_halign = text.align_center, text_size = text_size(general_text), text_font_family = font_style(general_font))
//#endregion
// # ========================================================================= #
// # | End |
// # ========================================================================= #
Bullish Divergent Bar DCA Strategy [Skyrexio]Overview
Bullish Divergent Bar DCA Strategy is a long-only, multi-layer Dollar-Cost Averaging (DCA) strategy that builds positions around bullish divergent bars formed below the Williams Alligator. It detects potential local bottoms and then scales into the move using up to four pyramiding entries, each with its own size and price threshold. The strategy optionally incorporates Market Facilitation Index (MFI) and Awesome Oscillator (AO) momentum to strengthen reversal confirmation and uses ATR-based take profit on the averaged entry price.
Unique Features
Layered DCA entries with equity-based sizing . It supports up to four DCA layers, where each additional layer is opened only after a configurable percentage drawdown from the first entry and position size is computed as a fraction of current equity via a geometric weighting scheme.
Optional AO and MFI confirmation . Users can require Awesome Oscillator momentum divergence, MFI/volume “squat” bars, or both to confirm that the reversal bar is accompanied by capitulation and weakening downside momentum.
ATR-based dynamic take profit . Take profit is defined as a multiple of ATR added to the current average entry price, automatically adjusting exits to prevailing volatility.
Built-in DCA visualization . The script can plot the initial entry level and all DCA thresholds to make the averaging structure and risk visually transparent on the chart.
Methodology
The core entry logic starts from a bullish divergent bar definition: the bar must close above its midpoint (close > hl2) and be the lowest low within the user-defined lookback window, flagging a local swing low. On top of this, the bar must form entirely below all three Alligator lines, ensuring that the pattern appears after a sustained downside move rather than inside noise.
If enabled, AO adds a momentum filter by requiring the Awesome Oscillator difference to be negative (descending bar on AO histogram), signaling fading downside momentum at the potential bottom. If the MFI filter is enabled, the bar (or one of the last two bars) must be a “squat” bar where spread narrows while volume increases, approximating effort vs. result exhaustion.
Once a valid bullish reversal bar is detected and the time is within the configured trading window, the strategy opens the first DCA layer using a stop entry at the bar’s high (confirmation level), only entering if price actually breaks the bar high. Additional layers (second, third, and fourth entries) are only allowed if price trades below percentage thresholds from the first entry price and a new valid bullish reversal bar forms, thereby averaging down into deep pullbacks while still requiring fresh reversal evidence.
While any DCA position is open, the strategy continuously recalculates the take profit as the current volume-weighted average entry price plus ATR multiplied by a user-defined factor. All individual entries share the same take profit level through separate strategy exit calls, so the entire stacked position exits together once price has moved sufficiently above the averaged entry.
Strategy settings
In the inputs window, users can configure the following strategy settings:
sourceUuid / secretToken: Identifiers used to format JSON alerts for automated execution through webhooks.
Trade Start Date/Time: Beginning of the backtest/live-trading window.
Trade Stop Date/Time: End of the backtest/live-trading window.
Show DCA Levels (default = false): Toggles plotting of the initial entry level and all three DCA thresholds on the chart.
Enable MFI (default = false): Enables the MFI-style volume/spread filter.
Enable AO (default = false): Enables Awesome Oscillator confirmation.
Number Of Bar For Lowest Bar (default = 7): Lookback window used to identify the lowest low bar for the bullish reversal bar condition.
Layer 2 Threshold Percent (default = 4.0): Percentage drop from the first layer price that must be reached to allow the second DCA entry.
Layer 3 Threshold Percent (default = 10.0): Percentage drop from the first layer price required to unlock the third DCA layer.
Layer 4 Threshold Percent (default = 22.0): Percentage drop from the first layer price required to unlock the fourth DCA layer.
Position Size Multiplier (default = 2.0): Multiplier used in the geometric weighting scheme to determine how much equity is allocated to each additional DCA layer.
Number Of ATR For Take Profit (default = 2.0): ATR multiple added to the current average entry price to calculate the shared take profit for all open layers.
Users can refine these parameters during backtesting to fit the volatility profile and structure of the specific asset and timeframe.
Justification of Methodology
Before understanding why this particular combination of indicator has been chosen let's briefly explain what is Williams Alligator, MFI and AO.
let’s start with the Williams Alligator. Developed by Bill Williams, the Alligator is a technical indicator that identifies trends and potential market reversals. It consists of three smoothed moving averages:
Jaw (Blue Line): The slowest of the three, based on a 13-period smoothed moving average shifted 8 bars ahead.
Teeth (Red Line): The medium-speed line, derived from an 8-period smoothed moving average shifted 5 bars forward.
Lips (Green Line): The fastest line, calculated using a 5-period smoothed moving average shifted 3 bars forward.
When the lines diverge and align in order, the "Alligator" is "awake," signaling a strong trend. When the lines overlap or intertwine, the "Alligator" is "asleep," indicating a range-bound or sideways market. This indicator helps traders determine when to enter or avoid trades.
The Awesome Oscillator (AO), developed by Bill Williams, is a momentum indicator designed to measure market momentum by contrasting recent price movements with a longer-term historical perspective. It helps traders detect potential trend reversals and assess the strength of ongoing trends.
The formula for AO is as follows:
AO = SMA5(Median Price) − SMA34(Median Price)
where:
Median Price = (High + Low) / 2
SMA5 = 5-period Simple Moving Average of the Median Price
SMA 34 = 34-period Simple Moving Average of the Median Price
The Market Facilitation Index (MFI) is a technical indicator that measures the price movement per unit of volume, helping traders gauge the efficiency of price movement in relation to trading volume. Here's how you can calculate it:
MFI = (High−Low)/Volume
MFI can be used in combination with volume, so we can divide 4 states. Bill Williams introduced these to help traders interpret the interaction between volume and price movement. Here’s a quick summary:
Green Window (Increased MFI & Increased Volume): Indicates strong momentum with both price and volume increasing. Often a sign of trend continuation, as both buying and selling interest are rising.
Fake Window (Increased MFI & Decreased Volume): Shows that price is moving but with lower volume, suggesting weak support for the trend. This can signal a potential end of the current trend.
Squat Window (Decreased MFI & Increased Volume): Shows high volume but little price movement, indicating a tug-of-war between buyers and sellers. This often precedes a breakout as the pressure builds.
Fade Window (Decreased MFI & Decreased Volume): Indicates a lack of interest from both buyers and sellers, leading to lower momentum. This typically happens in range-bound markets and may signal consolidation before a new move.
For our purposes we are interested in squat bars. This is the sign that volume cannot move the price easily. This type of bar increases the probability of trend reversal. In this indicator we added to enable the MFI filter of reversal bars. If potential divergent bar or two preceding bars have squat state this bar can be interpret as a reversal one.
The strategy intentionally focuses on bullish divergent bars forming at local lows and below the Alligator to catch potential exhaustion points in downtrends where risk/reward becomes asymmetric. The Alligator (Jaw, Teeth, Lips) acts as a dynamic structure filter: requiring price to be below all three lines before reversal helps avoid chasing minor pullbacks inside an ongoing uptrend and instead concentrates entries on deeper corrections where mean reversion potential is higher.
The custom bullish divergent bar rule (close above midpoint and being the lowest low over N bars) approximates a local capitulation candle, which often precedes short squeezes or at least strong reactions. By combining this with AO and MFI-style filters, the strategy further increases the likelihood that the pattern coincides with downside momentum(as a confirmation that current trend is downward, AO difference < 0) and effort vs. result anomalies (squat bars), which is common signatures of trend exhaustion.
The DCA structure is designed to deploy capital progressively rather than all at once: the first entry is triggered only if price confirms the reversal by breaking above the bar’s high, while subsequent layers require both a deeper discount relative to the initial entry and a new bullish reversal signal. Percentage thresholds from the first entry ensure that each additional allocation is made at meaningfully better prices, improving the blended entry level and reducing the break-even distance.
Finally, using ATR as the basis for take profit aligns exits with current volatility. A fixed-percentage target can be too tight in volatile regimes or too loose in quiet markets, whereas ATR-based targets scale with average bar range. Applying ATR to the evolving average entry price of all open layers keeps the risk/reward framework consistent across different volatility regimes and DCA configurations.
Backtest Results
Operating window: Date range of backtests is 2025.01.01 - 2026.01.01. It is chosen to let the strategy to close all opened positions.
Commission and Slippage: Includes a standard Binance commission of 0.1% and accounts for possible slippage over 5 ticks.
Initial capital: 10000 USDT
Maximum Single Position Loss: -6.56%
Maximum Single Profit: +4.92%
Net Profit: +934.08 USDT (+9.34%)
Total Trades: 121 (82.64% win rate)
Profit Factor: 2.948
Maximum Accumulated Loss: 624.72 USDT (-6.15%)
Average Profit per Trade: 7.72 USDT (+0.37%)
Average Trade Duration: 60 hours
These results are obtained with realistic parameters representing trading conditions observed at major exchanges such as Binance and with realistic trading portfolio usage parameters.
You should run your own backtests on the target asset and timeframe (for example, BTC/USDT on intraday charts) and adjust threshold percentages, layer sizing, and ATR take profit factor to match your risk tolerance and market conditions.
How to Use
Add the script to favorites for easy access.
Apply to the desired timeframe and chart.
Configure settings using the dropdown choice list in the built-in menu.
Set up alerts to automate strategy positions through web hook with the text: {{strategy.order.alert_message}}
Disclaimer:
Educational and informational tool reflecting Skyrex commitment to informed trading. Past performance does not guarantee future results. Test strategies in a simulated environment before live implementation
IFVG Flow (M3/M5) - Reversal Pink / Continuation Blueddddddddddddddddddddddddddddddddddddddddddddddddddd
SMC Full History JBI 1This indicator keeps BOS and CHoCH visible all the way to the oldest bars, revealing true market structure across all timeframes, unlike other indicators that erase historical signals, making trend and reversal zones clear and reliable.
Fractal Breakout with 3-Point TrendTriggers buy when the price breaks above the last fractal high
Triggers sell when the price breaks below the last fractal low
Filter is calculate the closing price of last 3 fractal highs or low to determine the trend
Pivot Points AvancadoOlá Amigos,
Indicador Pivot Points com Cruzamento de Médias Móveis
Fabricio Nicolau
MATT 3This indicator helps identify high-probability trend shifts and continuation setups by combining momentum, trend strength, and volatility into a single, easy-to-read signal. It highlights bullish/bearish conditions, marks potential entries and exits, and reduces noise during choppy markets with adaptive filtering. Use it to confirm direction, time pullbacks, and stay aligned with the dominant trend.
MATT 2This indicator helps identify high-probability trend shifts and continuation setups by combining momentum, trend strength, and volatility into a single, easy-to-read signal. It highlights bullish/bearish conditions, marks potential entries and exits, and reduces noise during choppy markets with adaptive filtering. Use it to confirm direction, time pullbacks, and stay aligned with the dominant trend.
MATT 1This indicator helps identify high-probability trend shifts and continuation setups by combining momentum, trend strength, and volatility into a single, easy-to-read signal. It highlights bullish/bearish conditions, marks potential entries and exits, and reduces noise during choppy markets with adaptive filtering. Use it to confirm direction, time pullbacks, and stay aligned with the dominant trend.
MATT 4This indicator helps identify high-probability trend shifts and continuation setups by combining momentum, trend strength, and volatility into a single, easy-to-read signal. It highlights bullish/bearish conditions, marks potential entries and exits, and reduces noise during choppy markets with adaptive filtering. Use it to confirm direction, time pullbacks, and stay aligned with the dominant trend.
Trendlines with Breaks + Fib Lines ONLY15min and 3min fib line already marked 15min and 3min fib line already marked15min and 3min fib line already marked15min and 3min fib line already marked15min and 3min fib line already marked15min and 3min fib line already marked15min and 3min fib line already marked15min and 3min fib line already marked15min and 3min fib line already marked15min and 3min fib line already marked15min and 3min fib line already marked15min and 3min fib line already marked
UFX PRO How it works
The indicator plots a single line on the chart that changes position and color depending on the trend:
🟢 Uptrend:
The SuperTrend line is below the price → bullish bias
🔴 Downtrend:
The SuperTrend line is above the price → bearish bias
When the price crosses the SuperTrend line, it often signals a potential trend reversal.
✅ Advantages
✔ Easy to read
✔ Works well in trending markets
✔ Adaptive to volatility
✔ Useful for stops and trend confirmation





















