OPEN-SOURCE SCRIPT
Updated TSD Quantum | mrmoeinudin

This indicator, **TSD Quantum**, has been developed by **Moeinudin Montazerfaraj**, exclusively for the students of the **TSD Intraday Trading Course**.
TSD Quantum is an intelligent and proprietary tool designed to accurately identify **valid supply and demand zones** and distinguish them from weak or linear bases. The algorithm is fully customized to align with the advanced concepts taught in the TSD methodology, empowering traders to make more confident and data-driven decisions.
### Key Features:
- Smart zone detection tailored to TSD methodology
- Floating risk management panel
- Integrated checklist for trade validation
- Real-time display of ATR, spread, and other essential metrics
- Optimized for intraday traders who follow price action and zone-based decision making strategies.
To join our exclusive educational programs, visit our official website:
🌐 [mrmoeinudin.com](mrmoeinudin.com)
Stay connected and follow us for insights, updates, and free educational content:
📌 Telegram: [t.me/mrmoeinudin](https://t.me/mrmoeinudin)
📌 YouTube: [youtube.com/@mrmoeinudin?si=Krd8oL7k__77oKKU]
📌 Instagram: [instagram.com/mrmoeinudin]
Wishing all Persian-speaking traders around the world continued success and growth in their trading journey. 🚀📈
TSD Quantum is an intelligent and proprietary tool designed to accurately identify **valid supply and demand zones** and distinguish them from weak or linear bases. The algorithm is fully customized to align with the advanced concepts taught in the TSD methodology, empowering traders to make more confident and data-driven decisions.
### Key Features:
- Smart zone detection tailored to TSD methodology
- Floating risk management panel
- Integrated checklist for trade validation
- Real-time display of ATR, spread, and other essential metrics
- Optimized for intraday traders who follow price action and zone-based decision making strategies.
To join our exclusive educational programs, visit our official website:
🌐 [mrmoeinudin.com](mrmoeinudin.com)
Stay connected and follow us for insights, updates, and free educational content:
📌 Telegram: [t.me/mrmoeinudin](https://t.me/mrmoeinudin)
📌 YouTube: [youtube.com/@mrmoeinudin?si=Krd8oL7k__77oKKU]
📌 Instagram: [instagram.com/mrmoeinudin]
Wishing all Persian-speaking traders around the world continued success and growth in their trading journey. 🚀📈
Release Notes
//version=5indicator("Rejection Candle Detector", shorttitle="RCD", overlay=true)
// ========== General Settings ==========
enable_indicator = input.bool(true, "Enable Indicator", group="General Settings")
// ========== Text Display Settings ==========
text_size = input.string("small", "Text Size", options=["tiny", "small", "normal", "large", "huge"], group="Text Display")
text_color = input.color(color.blue, "Text Color", group="Text Display")
text_position = input.string("above", "Text Position", options=["above", "below"], group="Text Display")
// ========== Minimum Range Settings (Pips) for 5 Minutes ==========
gold_5m_min_range = input.float(30, "Gold - 5 Minutes (Pips)", minval=0, group="5 Minutes Settings")
eurusd_5m_min_range = input.float(7, "EURUSD - 5 Minutes (Pips)", minval=0, group="5 Minutes Settings")
dax_5m_min_range = input.float(30, "DAX40 - 5 Minutes (Pips)", minval=0, group="5 Minutes Settings")
// ========== Minimum Range Settings (Pips) for 15 Minutes ==========
gold_15m_min_range = input.float(53, "Gold - 15 Minutes (Pips)", minval=0, group="15 Minutes Settings")
eurusd_15m_min_range = input.float(20, "EURUSD - 15 Minutes (Pips)", minval=0, group="15 Minutes Settings")
dax_15m_min_range = input.float(53, "DAX40 - 15 Minutes (Pips)", minval=0, group="15 Minutes Settings")
// ========== Body Percentage Settings ==========
body_percentage_5m = input.float(23, "Body Percentage - 5 Minutes (%)", minval=0, maxval=100, group="Body Percentage")
body_percentage_15m = input.float(23, "Body Percentage - 15 Minutes (%)", minval=0, maxval=100, group="Body Percentage")
// ========== Shadow Difference Settings ==========
shadow_difference_5m = input.float(80, "Shadow Difference - 5 Minutes (%)", minval=0, maxval=100, group="Shadow Settings", tooltip="Minimum difference percentage between upper and lower shadows")
shadow_difference_15m = input.float(80, "Shadow Difference - 15 Minutes (%)", minval=0, maxval=100, group="Shadow Settings", tooltip="Minimum difference percentage between upper and lower shadows")
// ========== Display Days Settings ==========
max_display_days = input.int(5, "Maximum Display Days", minval=1, maxval=365, group="Display Settings", tooltip="Maximum number of past days to show rejection candles")
// ========== Symbol Detection Function ==========
get_symbol_type() =>
symbol_name = str.upper(syminfo.ticker)
if str.contains(symbol_name, "XAU") or str.contains(symbol_name, "GOLD")
"GOLD"
else if str.contains(symbol_name, "EUR") and str.contains(symbol_name, "USD")
"EURUSD"
else if str.contains(symbol_name, "DAX") or str.contains(symbol_name, "GER") or str.contains(symbol_name, "DE")
"DAX"
else
"OTHER"
// ========== Pip Calculation Function ==========
calculate_pip_value(range_value, symbol_type) =>
if symbol_type == "GOLD"
range_value * 10
else if symbol_type == "EURUSD"
range_value * 10000
else if symbol_type == "DAX"
range_value
else
0
// ========== Text Size Function ==========
get_text_size() =>
switch text_size
"tiny" => size.tiny
"small" => size.small
"normal" => size.normal
"large" => size.large
"huge" => size.huge
=> size.small
// ========== Shadow Difference Calculation ==========
calculate_shadow_difference() =>
body_top = math.max(open, close)
body_bottom = math.min(open, close)
upper_shadow = high - body_top
lower_shadow = body_bottom - low
total_shadow = upper_shadow + lower_shadow
if total_shadow > 0
shadow_diff = math.abs(upper_shadow - lower_shadow) / total_shadow * 100
shadow_diff
else
0
// ========== Main Calculations ==========
current_symbol = get_symbol_type()
current_timeframe = timeframe.period
candle_range = high - low
candle_body = math.abs(close - open)
body_ratio = candle_body / candle_range * 100
range_in_pips = calculate_pip_value(candle_range, current_symbol)
shadow_diff_percentage = calculate_shadow_difference()
// ========== Determine Minimum Range and Body Percentage ==========
min_required_range = 0.0
required_body_percentage = 0.0
required_shadow_difference = 0.0
if current_symbol != "OTHER"
if current_timeframe == "5"
if current_symbol == "GOLD"
min_required_range := gold_5m_min_range
else if current_symbol == "EURUSD"
min_required_range := eurusd_5m_min_range
else if current_symbol == "DAX"
min_required_range := dax_5m_min_range
required_body_percentage := body_percentage_5m
required_shadow_difference := shadow_difference_5m
else if current_timeframe == "15"
if current_symbol == "GOLD"
min_required_range := gold_15m_min_range
else if current_symbol == "EURUSD"
min_required_range := eurusd_15m_min_range
else if current_symbol == "DAX"
min_required_range := dax_15m_min_range
required_body_percentage := body_percentage_15m
required_shadow_difference := shadow_difference_15m
// ========== Check if candle is within display range ==========
is_within_display_range() =>
// Calculate cutoff time: current time minus max_display_days
days_in_milliseconds = max_display_days * 24 * 60 * 60 * 1000
cutoff_time = timenow - days_in_milliseconds
// Return true if current bar time is after cutoff time
time >= cutoff_time
// ========== Rejection Candle Conditions ==========
symbol_condition = current_symbol != "OTHER"
timeframe_condition = current_timeframe == "5" or current_timeframe == "15"
range_condition = range_in_pips >= min_required_range
body_condition = body_ratio <= required_body_percentage
shadow_condition = shadow_diff_percentage >= required_shadow_difference
time_condition = is_within_display_range()
is_rejection_candle = enable_indicator and symbol_condition and timeframe_condition and range_condition and body_condition and shadow_condition and time_condition
// ========== Text Display ==========
if is_rejection_candle
label_y = text_position == "above" ? high + (high - low) * 0.1 : low - (high - low) * 0.1
label_style = text_position == "above" ? label.style_label_down : label.style_label_up
label.new(x=bar_index, y=label_y, text="RC", color=color.new(color.white, 100), textcolor=text_color, size=get_text_size(), style=label_style)
Release Notes
//version=5indicator("Rejection Candle Detector", shorttitle="RCD", overlay=true)
// ========== General Settings ==========
enable_indicator = input.bool(true, "Enable Indicator", group="General Settings")
// ========== Text Display Settings ==========
text_size = input.string("small", "Text Size", options=["tiny", "small", "normal", "large", "huge"], group="Text Display")
text_color = input.color(color.blue, "Text Color", group="Text Display")
text_position = input.string("above", "Text Position", options=["above", "below"], group="Text Display")
// ========== Minimum Range Settings (Pips) for 5 Minutes ==========
gold_5m_min_range = input.float(30, "Gold - 5 Minutes (Pips)", minval=0, group="5 Minutes Settings")
eurusd_5m_min_range = input.float(7, "EURUSD - 5 Minutes (Pips)", minval=0, group="5 Minutes Settings")
dax_5m_min_range = input.float(30, "DAX40 - 5 Minutes (Pips)", minval=0, group="5 Minutes Settings")
// ========== Minimum Range Settings (Pips) for 15 Minutes ==========
gold_15m_min_range = input.float(53, "Gold - 15 Minutes (Pips)", minval=0, group="15 Minutes Settings")
eurusd_15m_min_range = input.float(20, "EURUSD - 15 Minutes (Pips)", minval=0, group="15 Minutes Settings")
dax_15m_min_range = input.float(53, "DAX40 - 15 Minutes (Pips)", minval=0, group="15 Minutes Settings")
// ========== Body Percentage Settings ==========
body_percentage_5m = input.float(23, "Body Percentage - 5 Minutes (%)", minval=0, maxval=100, group="Body Percentage")
body_percentage_15m = input.float(23, "Body Percentage - 15 Minutes (%)", minval=0, maxval=100, group="Body Percentage")
// ========== Shadow Difference Settings ==========
shadow_difference_5m = input.float(80, "Shadow Difference - 5 Minutes (%)", minval=0, maxval=100, group="Shadow Settings", tooltip="Minimum difference percentage between upper and lower shadows")
shadow_difference_15m = input.float(80, "Shadow Difference - 15 Minutes (%)", minval=0, maxval=100, group="Shadow Settings", tooltip="Minimum difference percentage between upper and lower shadows")
// ========== Display Days Settings ==========
max_display_days = input.int(5, "Maximum Display Days", minval=1, maxval=365, group="Display Settings", tooltip="Maximum number of past days to show rejection candles")
// ========== Symbol Detection Function ==========
get_symbol_type() =>
symbol_name = str.upper(syminfo.ticker)
if str.contains(symbol_name, "XAU") or str.contains(symbol_name, "GOLD")
"GOLD"
else if str.contains(symbol_name, "EUR") and str.contains(symbol_name, "USD")
"EURUSD"
else if str.contains(symbol_name, "DAX") or str.contains(symbol_name, "GER") or str.contains(symbol_name, "DE")
"DAX"
else
"OTHER"
// ========== Pip Calculation Function ==========
calculate_pip_value(range_value, symbol_type) =>
if symbol_type == "GOLD"
range_value * 10
else if symbol_type == "EURUSD"
range_value * 10000
else if symbol_type == "DAX"
range_value
else
0
// ========== Text Size Function ==========
get_text_size() =>
switch text_size
"tiny" => size.tiny
"small" => size.small
"normal" => size.normal
"large" => size.large
"huge" => size.huge
=> size.small
// ========== Shadow Difference Calculation ==========
calculate_shadow_difference() =>
body_top = math.max(open, close)
body_bottom = math.min(open, close)
upper_shadow = high - body_top
lower_shadow = body_bottom - low
total_shadow = upper_shadow + lower_shadow
if total_shadow > 0
shadow_diff = math.abs(upper_shadow - lower_shadow) / total_shadow * 100
shadow_diff
else
0
// ========== Main Calculations ==========
current_symbol = get_symbol_type()
current_timeframe = timeframe.period
candle_range = high - low
candle_body = math.abs(close - open)
body_ratio = candle_body / candle_range * 100
range_in_pips = calculate_pip_value(candle_range, current_symbol)
shadow_diff_percentage = calculate_shadow_difference()
// ========== Determine Minimum Range and Body Percentage ==========
min_required_range = 0.0
required_body_percentage = 0.0
required_shadow_difference = 0.0
if current_symbol != "OTHER"
if current_timeframe == "5"
if current_symbol == "GOLD"
min_required_range := gold_5m_min_range
else if current_symbol == "EURUSD"
min_required_range := eurusd_5m_min_range
else if current_symbol == "DAX"
min_required_range := dax_5m_min_range
required_body_percentage := body_percentage_5m
required_shadow_difference := shadow_difference_5m
else if current_timeframe == "15"
if current_symbol == "GOLD"
min_required_range := gold_15m_min_range
else if current_symbol == "EURUSD"
min_required_range := eurusd_15m_min_range
else if current_symbol == "DAX"
min_required_range := dax_15m_min_range
required_body_percentage := body_percentage_15m
required_shadow_difference := shadow_difference_15m
// ========== Check if candle is within display range ==========
is_within_display_range() =>
// Calculate cutoff time: current time minus max_display_days
days_in_milliseconds = max_display_days * 24 * 60 * 60 * 1000
cutoff_time = timenow - days_in_milliseconds
// Return true if current bar time is after cutoff time
time >= cutoff_time
// ========== Rejection Candle Conditions ==========
symbol_condition = current_symbol != "OTHER"
timeframe_condition = current_timeframe == "5" or current_timeframe == "15"
range_condition = range_in_pips >= min_required_range
body_condition = body_ratio <= required_body_percentage
shadow_condition = shadow_diff_percentage >= required_shadow_difference
time_condition = is_within_display_range()
is_rejection_candle = enable_indicator and symbol_condition and timeframe_condition and range_condition and body_condition and shadow_condition and time_condition
// ========== Text Display ==========
if is_rejection_candle
label_y = text_position == "above" ? high + (high - low) * 0.1 : low - (high - low) * 0.1
label_style = text_position == "above" ? label.style_label_down : label.style_label_up
label.new(x=bar_index, y=label_y, text="RC", color=color.new(color.white, 100), textcolor=text_color, size=get_text_size(), style=label_style)
Release Notes
//version=5indicator("Hammer & Doji Detector", shorttitle="Hammer & Doji", overlay=true)
// Input settings
doji_threshold = input.float(0.1, "Doji Threshold (%)", minval=0.01, maxval=1.0, step=0.01)
hammer_ratio = input.float(2.0, "Hammer Shadow Ratio", minval=1.5, maxval=5.0, step=0.1)
// Calculate candle dimensions
body_size = math.abs(close - open)
total_range = high - low
upper_shadow = high - math.max(open, close)
lower_shadow = math.min(open, close) - low
// Doji identification conditions
is_doji = body_size <= (total_range * doji_threshold / 100) and total_range > 0
// Hammer identification conditions
is_hammer = (lower_shadow >= body_size * hammer_ratio) and (upper_shadow <= body_size * 0.5) and total_range > 0 and body_size > 0
// Inverted Hammer identification conditions
is_inverted_hammer = (upper_shadow >= body_size * hammer_ratio) and (lower_shadow <= body_size * 0.5) and total_range > 0 and body_size > 0
// Color candles
barcolor(is_doji ? color.yellow : is_hammer ? color.blue : is_inverted_hammer ? color.purple : na, title="Candle Colors")
// Display labels
if is_doji
label.new(bar_index, high + (high - low) * 0.1, "DOJI", color=color.yellow, textcolor=color.black, style=label.style_label_down, size=size.small)
if is_hammer
label.new(bar_index, low - (high - low) * 0.1, "HAMMER", color=color.blue, textcolor=color.white, style=label.style_label_up, size=size.small)
if is_inverted_hammer
label.new(bar_index, high + (high - low) * 0.1, "INV HAMMER", color=color.purple, textcolor=color.white, style=label.style_label_down, size=size.small)
// Display shapes on chart
plotshape(is_doji, title="Doji Marker", location=location.abovebar, color=color.yellow, style=shape.diamond, size=size.small)
plotshape(is_hammer, title="Hammer Marker", location=location.belowbar, color=color.blue, style=shape.triangleup, size=size.small)
plotshape(is_inverted_hammer, title="Inverted Hammer Marker", location=location.abovebar, color=color.purple, style=shape.triangledown, size=size.small)
// Alerts
alertcondition(is_doji, title="Doji Detected", message="Doji candlestick pattern detected")
alertcondition(is_hammer, title="Hammer Detected", message="Hammer candlestick pattern detected")
alertcondition(is_inverted_hammer, title="Inverted Hammer Detected", message="Inverted Hammer candlestick pattern detected")
// Information table
var table info_table = table.new(position.top_right, 2, 4, bgcolor=color.white, border_width=1)
if barstate.islast
table.cell(info_table, 0, 0, "Pattern", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 1, 0, "Status", text_color=color.black, bgcolor=color.gray)
table.cell(info_table, 0, 1, "Doji", text_color=color.black)
table.cell(info_table, 1, 1, is_doji ? "✓" : "✗", text_color=is_doji ? color.green : color.red)
table.cell(info_table, 0, 2, "Hammer", text_color=color.black)
table.cell(info_table, 1, 2, is_hammer ? "✓" : "✗", text_color=is_hammer ? color.green : color.red)
table.cell(info_table, 0, 3, "Inv Hammer", text_color=color.black)
table.cell(info_table, 1, 3, is_inverted_hammer ? "✓" : "✗", text_color=is_inverted_hammer ? color.green : color.red)
Open-source script
In true TradingView spirit, the creator of this script has made it open-source, so that traders can review and verify its functionality. Kudos to the author! While you can use it for free, remember that republishing the code is subject to our House Rules.
Disclaimer
The information and publications are not meant to be, and do not constitute, financial, investment, trading, or other types of advice or recommendations supplied or endorsed by TradingView. Read more in the Terms of Use.
Open-source script
In true TradingView spirit, the creator of this script has made it open-source, so that traders can review and verify its functionality. Kudos to the author! While you can use it for free, remember that republishing the code is subject to our House Rules.
Disclaimer
The information and publications are not meant to be, and do not constitute, financial, investment, trading, or other types of advice or recommendations supplied or endorsed by TradingView. Read more in the Terms of Use.