Dua indikator all-in-one untuk TradingView — Panel Dashboard (valuasi, Minervini Score, RRG, smart money) dan SMC (Order Blocks, FVG, Market Structure). Copy-paste langsung ke Pine Editor.
Gratis untuk semua Pine Script v5 Real-time Multi-timeframe
// =====================================================================
// YPC Indicator System - SMC
// Build :@YPCSaham
// =====================================================================
//@version=5
indicator('YPC Indicator System - SMC', 'YPC Indicator System - SMC', overlay=true, precision=2, max_labels_count=500, max_lines_count=500, max_boxes_count=500)
//---------------------------------------------------------------------------------------------------------------------}
//CONSTANTS & STRINGS & INPUTS
//---------------------------------------------------------------------------------------------------------------------{
BULLISH_LEG = 1
BEARISH_LEG = 0
BULLISH = +1
BEARISH = -1
GREEN = #089981
RED = #F23645
BLUE = #2157f3
GRAY = #878b94
MONO_BULLISH = #b2b5be
MONO_BEARISH = #5d606b
HISTORICAL = 'Historical'
PRESENT = 'Present'
COLORED = 'Colored'
MONOCHROME = 'Monochrome'
ALL = 'All'
BOS = 'BOS'
CHOCH = 'CHoCH'
TINY = size.tiny
SMALL = size.small
NORMAL = size.normal
ATR = 'Atr'
RANGE = 'Cumulative Mean Range'
CLOSE = 'Close'
HIGHLOW = 'High/Low'
SOLID = '⎯⎯⎯'
DASHED = '----'
DOTTED = '····'
SMART_GROUP = 'Smart Money Concepts'
INTERNAL_GROUP = 'Real Time Internal Structure'
SWING_GROUP = 'Real Time Swing Structure'
BLOCKS_GROUP = 'Order Blocks'
EQUAL_GROUP = 'EQH/EQL'
GAPS_GROUP = 'Fair Value Gaps'
LEVELS_GROUP = 'Highs & Lows MTF'
ZONES_GROUP = 'Premium & Discount Zones'
modeTooltip = 'Allows to display historical Structure or only the recent ones'
styleTooltip = 'Indicator color theme'
showTrendTooltip = 'Display additional candles with a color reflecting the current trend detected by structure'
showInternalsTooltip = 'Display internal market structure'
internalFilterConfluenceTooltip = 'Filter non significant internal structure breakouts'
showStructureTooltip = 'Display swing market Structure'
showSwingsTooltip = 'Display swing point as labels on the chart'
showHighLowSwingsTooltip = 'Highlight most recent strong and weak high/low points on the chart'
showInternalOrderBlocksTooltip = 'Display internal order blocks on the chart\n\nNumber of internal order blocks to display on the chart'
showSwingOrderBlocksTooltip = 'Display swing order blocks on the chart\n\nNumber of internal swing blocks to display on the chart'
orderBlockFilterTooltip = 'Method used to filter out volatile order blocks \n\nIt is recommended to use the cumulative mean range method when a low amount of data is available'
orderBlockMitigationTooltip = 'Select what values to use for order block mitigation'
showEqualHighsLowsTooltip = 'Display equal highs and equal lows on the chart'
equalHighsLowsLengthTooltip = 'Number of bars used to confirm equal highs and equal lows'
equalHighsLowsThresholdTooltip = 'Sensitivity threshold in a range (0, 1) used for the detection of equal highs & lows\n\nLower values will return fewer but more pertinent results'
showFairValueGapsTooltip = 'Display fair values gaps on the chart'
fairValueGapsThresholdTooltip = 'Filter out non significant fair value gaps'
fairValueGapsTimeframeTooltip = 'Fair value gaps timeframe'
fairValueGapsExtendTooltip = 'Determine how many bars to extend the Fair Value Gap boxes on chart'
showPremiumDiscountZonesTooltip = 'Display premium, discount, and equilibrium zones on chart'
modeInput = input.string( HISTORICAL, 'Mode', group = SMART_GROUP, tooltip = modeTooltip, options = [HISTORICAL, PRESENT])
styleInput = input.string( COLORED, 'Style', group = SMART_GROUP, tooltip = styleTooltip,options = [COLORED, MONOCHROME])
showTrendInput = input( false, 'Color Candles', group = SMART_GROUP, tooltip = showTrendTooltip)
showInternalsInput = input( true, 'Show Internal Structure', group = INTERNAL_GROUP, tooltip = showInternalsTooltip)
showInternalBullInput = input.string( ALL, 'Bullish Structure', group = INTERNAL_GROUP, inline = 'ibull', options = [ALL,BOS,CHOCH])
internalBullColorInput = input( GREEN, '', group = INTERNAL_GROUP, inline = 'ibull')
showInternalBearInput = input.string( ALL, 'Bearish Structure' , group = INTERNAL_GROUP, inline = 'ibear', options = [ALL,BOS,CHOCH])
internalBearColorInput = input( RED, '', group = INTERNAL_GROUP, inline = 'ibear')
internalFilterConfluenceInput = input( false, 'Confluence Filter', group = INTERNAL_GROUP, tooltip = internalFilterConfluenceTooltip)
internalStructureSize = input.string( TINY, 'Internal Label Size', group = INTERNAL_GROUP, options = [TINY,SMALL,NORMAL])
showStructureInput = input( true, 'Show Swing Structure', group = SWING_GROUP, tooltip = showStructureTooltip)
showSwingBullInput = input.string( ALL, 'Bullish Structure', group = SWING_GROUP, inline = 'bull', options = [ALL,BOS,CHOCH])
swingBullColorInput = input( GREEN, '', group = SWING_GROUP, inline = 'bull')
showSwingBearInput = input.string( ALL, 'Bearish Structure', group = SWING_GROUP, inline = 'bear', options = [ALL,BOS,CHOCH])
swingBearColorInput = input( RED, '', group = SWING_GROUP, inline = 'bear')
swingStructureSize = input.string( SMALL, 'Swing Label Size', group = SWING_GROUP, options = [TINY,SMALL,NORMAL])
showSwingsInput = input( false, 'Show Swings Points', group = SWING_GROUP, tooltip = showSwingsTooltip,inline = 'swings')
swingsLengthInput = input.int( 50, '', group = SWING_GROUP, minval = 10, inline = 'swings')
showHighLowSwingsInput = input( true, 'Show Strong/Weak High/Low',group = SWING_GROUP, tooltip = showHighLowSwingsTooltip)
showInternalOrderBlocksInput = input( true, 'Internal Order Blocks' , group = BLOCKS_GROUP, tooltip = showInternalOrderBlocksTooltip, inline = 'iob')
internalOrderBlocksSizeInput = input.int( 2, '', group = BLOCKS_GROUP, minval = 1, maxval = 20, inline = 'iob')
showSwingOrderBlocksInput = input( false, 'Swing Order Blocks', group = BLOCKS_GROUP, tooltip = showSwingOrderBlocksTooltip, inline = 'ob')
swingOrderBlocksSizeInput = input.int( 5, '', group = BLOCKS_GROUP, minval = 1, maxval = 20, inline = 'ob')
orderBlockFilterInput = input.string( 'Atr', 'Order Block Filter', group = BLOCKS_GROUP, tooltip = orderBlockFilterTooltip, options = [ATR, RANGE])
orderBlockMitigationInput = input.string( HIGHLOW, 'Order Block Mitigation', group = BLOCKS_GROUP, tooltip = orderBlockMitigationTooltip, options = [CLOSE,HIGHLOW])
internalBullishOrderBlockColor = input.color(color.new(#3179f5, 80), 'Internal Bullish OB', group = BLOCKS_GROUP)
internalBearishOrderBlockColor = input.color(color.new(#f77c80, 80), 'Internal Bearish OB', group = BLOCKS_GROUP)
swingBullishOrderBlockColor = input.color(color.new(#1848cc, 80), 'Bullish OB', group = BLOCKS_GROUP)
swingBearishOrderBlockColor = input.color(color.new(#b22833, 80), 'Bearish OB', group = BLOCKS_GROUP)
showEqualHighsLowsInput = input( true, 'Equal High/Low', group = EQUAL_GROUP, tooltip = showEqualHighsLowsTooltip)
equalHighsLowsLengthInput = input.int( 3, 'Bars Confirmation', group = EQUAL_GROUP, tooltip = equalHighsLowsLengthTooltip, minval = 1)
equalHighsLowsThresholdInput = input.float( 0.1, 'Threshold', group = EQUAL_GROUP, tooltip = equalHighsLowsThresholdTooltip, minval = 0, maxval = 0.5, step = 0.1)
equalHighsLowsSizeInput = input.string( TINY, 'Label Size', group = EQUAL_GROUP, options = [TINY,SMALL,NORMAL])
showFairValueGapsInput = input( false, 'Fair Value Gaps', group = GAPS_GROUP, tooltip = showFairValueGapsTooltip)
fairValueGapsThresholdInput = input( true, 'Auto Threshold', group = GAPS_GROUP, tooltip = fairValueGapsThresholdTooltip)
fairValueGapsTimeframeInput = input.timeframe('', 'Timeframe', group = GAPS_GROUP, tooltip = fairValueGapsTimeframeTooltip)
fairValueGapsBullColorInput = input.color(color.new(#00ff68, 70), 'Bullish FVG' , group = GAPS_GROUP)
fairValueGapsBearColorInput = input.color(color.new(#ff0008, 70), 'Bearish FVG' , group = GAPS_GROUP)
fairValueGapsExtendInput = input.int( 1, 'Extend FVG', group = GAPS_GROUP, tooltip = fairValueGapsExtendTooltip, minval = 0)
showDailyLevelsInput = input( false, 'Daily', group = LEVELS_GROUP, inline = 'daily')
dailyLevelsStyleInput = input.string( SOLID, '', group = LEVELS_GROUP, inline = 'daily', options = [SOLID,DASHED,DOTTED])
dailyLevelsColorInput = input( BLUE, '', group = LEVELS_GROUP, inline = 'daily')
showWeeklyLevelsInput = input( false, 'Weekly', group = LEVELS_GROUP, inline = 'weekly')
weeklyLevelsStyleInput = input.string( SOLID, '', group = LEVELS_GROUP, inline = 'weekly', options = [SOLID,DASHED,DOTTED])
weeklyLevelsColorInput = input( BLUE, '', group = LEVELS_GROUP, inline = 'weekly')
showMonthlyLevelsInput = input( false, 'Monthly', group = LEVELS_GROUP, inline = 'monthly')
monthlyLevelsStyleInput = input.string( SOLID, '', group = LEVELS_GROUP, inline = 'monthly', options = [SOLID,DASHED,DOTTED])
monthlyLevelsColorInput = input( BLUE, '', group = LEVELS_GROUP, inline = 'monthly')
showPremiumDiscountZonesInput = input( false, 'Premium/Discount Zones', group = ZONES_GROUP , tooltip = showPremiumDiscountZonesTooltip)
premiumZoneColorInput = input.color( RED, 'Premium Zone', group = ZONES_GROUP)
equilibriumZoneColorInput = input.color( GRAY, 'Equilibrium Zone', group = ZONES_GROUP)
discountZoneColorInput = input.color( GREEN, 'Discount Zone', group = ZONES_GROUP)
//---------------------------------------------------------------------------------------------------------------------}
//DATA STRUCTURES & VARIABLES
//---------------------------------------------------------------------------------------------------------------------{
// @type UDT representing alerts as bool fields
// @field internalBullishBOS internal structure custom alert
// @field internalBearishBOS internal structure custom alert
// @field internalBullishCHoCH internal structure custom alert
// @field internalBearishCHoCH internal structure custom alert
// @field swingBullishBOS swing structure custom alert
// @field swingBearishBOS swing structure custom alert
// @field swingBullishCHoCH swing structure custom alert
// @field swingBearishCHoCH swing structure custom alert
// @field internalBullishOrderBlock internal order block custom alert
// @field internalBearishOrderBlock internal order block custom alert
// @field swingBullishOrderBlock swing order block custom alert
// @field swingBearishOrderBlock swing order block custom alert
// @field equalHighs equal high low custom alert
// @field equalLows equal high low custom alert
// @field bullishFairValueGap fair value gap custom alert
// @field bearishFairValueGap fair value gap custom alert
type alerts
bool internalBullishBOS = false
bool internalBearishBOS = false
bool internalBullishCHoCH = false
bool internalBearishCHoCH = false
bool swingBullishBOS = false
bool swingBearishBOS = false
bool swingBullishCHoCH = false
bool swingBearishCHoCH = false
bool internalBullishOrderBlock = false
bool internalBearishOrderBlock = false
bool swingBullishOrderBlock = false
bool swingBearishOrderBlock = false
bool equalHighs = false
bool equalLows = false
bool bullishFairValueGap = false
bool bearishFairValueGap = false
// @type UDT representing last swing extremes (top & bottom)
// @field top last top swing price
// @field bottom last bottom swing price
// @field barTime last swing bar time
// @field barIndex last swing bar index
// @field lastTopTime last top swing time
// @field lastBottomTime last bottom swing time
type trailingExtremes
float top
float bottom
int barTime
int barIndex
int lastTopTime
int lastBottomTime
// @type UDT representing Fair Value Gaps
// @field top top price
// @field bottom bottom price
// @field bias bias (BULLISH or BEARISH)
// @field topBox top box
// @field bottomBox bottom box
type fairValueGap
float top
float bottom
int bias
box topBox
box bottomBox
// @type UDT representing trend bias
// @field bias BULLISH or BEARISH
type trend
int bias
// @type UDT representing Equal Highs Lows display
// @field l_ine displayed line
// @field l_abel displayed label
type equalDisplay
line l_ine = na
label l_abel = na
// @type UDT representing a pivot point (swing point)
// @field currentLevel current price level
// @field lastLevel last price level
// @field crossed true if price level is crossed
// @field barTime bar time
// @field barIndex bar index
type pivot
float currentLevel
float lastLevel
bool crossed
int barTime = time
int barIndex = bar_index
// @type UDT representing an order block
// @field barHigh bar high
// @field barLow bar low
// @field barTime bar time
// @field bias BULLISH or BEARISH
type orderBlock
float barHigh
float barLow
int barTime
int bias
// @variable current swing pivot high
var pivot swingHigh = pivot.new(na,na,false)
// @variable current swing pivot low
var pivot swingLow = pivot.new(na,na,false)
// @variable current internal pivot high
var pivot internalHigh = pivot.new(na,na,false)
// @variable current internal pivot low
var pivot internalLow = pivot.new(na,na,false)
// @variable current equal high pivot
var pivot equalHigh = pivot.new(na,na,false)
// @variable current equal low pivot
var pivot equalLow = pivot.new(na,na,false)
// @variable swing trend bias
var trend swingTrend = trend.new(0)
// @variable internal trend bias
var trend internalTrend = trend.new(0)
// @variable equal high display
var equalDisplay equalHighDisplay = equalDisplay.new()
// @variable equal low display
var equalDisplay equalLowDisplay = equalDisplay.new()
// @variable storage for fairValueGap UDTs
var array<fairValueGap> fairValueGaps = array.new<fairValueGap>()
// @variable storage for parsed highs
var array<float> parsedHighs = array.new<float>()
// @variable storage for parsed lows
var array<float> parsedLows = array.new<float>()
// @variable storage for raw highs
var array<float> highs = array.new<float>()
// @variable storage for raw lows
var array<float> lows = array.new<float>()
// @variable storage for bar time values
var array<int> times = array.new<int>()
// @variable last trailing swing high and low
var trailingExtremes trailing = trailingExtremes.new()
// @variable storage for orderBlock UDTs (swing order blocks)
var array<orderBlock> swingOrderBlocks = array.new<orderBlock>()
// @variable storage for orderBlock UDTs (internal order blocks)
var array<orderBlock> internalOrderBlocks = array.new<orderBlock>()
// @variable storage for swing order blocks boxes
var array<box> swingOrderBlocksBoxes = array.new<box>()
// @variable storage for internal order blocks boxes
var array<box> internalOrderBlocksBoxes = array.new<box>()
// @variable color for swing bullish structures
var swingBullishColor = styleInput == MONOCHROME ? MONO_BULLISH : swingBullColorInput
// @variable color for swing bearish structures
var swingBearishColor = styleInput == MONOCHROME ? MONO_BEARISH : swingBearColorInput
// @variable color for bullish fair value gaps
var fairValueGapBullishColor = styleInput == MONOCHROME ? color.new(MONO_BULLISH,70) : fairValueGapsBullColorInput
// @variable color for bearish fair value gaps
var fairValueGapBearishColor = styleInput == MONOCHROME ? color.new(MONO_BEARISH,70) : fairValueGapsBearColorInput
// @variable color for premium zone
var premiumZoneColor = styleInput == MONOCHROME ? MONO_BEARISH : premiumZoneColorInput
// @variable color for discount zone
var discountZoneColor = styleInput == MONOCHROME ? MONO_BULLISH : discountZoneColorInput
// @variable bar index on current script iteration
varip int currentBarIndex = bar_index
// @variable bar index on last script iteration
varip int lastBarIndex = bar_index
// @variable alerts in current bar
alerts currentAlerts = alerts.new()
// @variable time at start of chart
var initialTime = time
// we create the needed boxes for displaying order blocks at the first execution
if barstate.isfirst
if showSwingOrderBlocksInput
for index = 1 to swingOrderBlocksSizeInput
swingOrderBlocksBoxes.push(box.new(na,na,na,na,xloc = xloc.bar_time,extend = extend.right))
if showInternalOrderBlocksInput
for index = 1 to internalOrderBlocksSizeInput
internalOrderBlocksBoxes.push(box.new(na,na,na,na,xloc = xloc.bar_time,extend = extend.right))
// @variable source to use in bearish order blocks mitigation
bearishOrderBlockMitigationSource = orderBlockMitigationInput == CLOSE ? close : high
// @variable source to use in bullish order blocks mitigation
bullishOrderBlockMitigationSource = orderBlockMitigationInput == CLOSE ? close : low
// @variable default volatility measure
atrMeasure = ta.atr(200)
// @variable parsed volatility measure by user settings
volatilityMeasure = orderBlockFilterInput == ATR ? atrMeasure : ta.cum(ta.tr)/bar_index
// @variable true if current bar is a high volatility bar
highVolatilityBar = (high - low) >= (2 * volatilityMeasure)
// @variable parsed high
parsedHigh = highVolatilityBar ? low : high
// @variable parsed low
parsedLow = highVolatilityBar ? high : low
// we store current values into the arrays at each bar
parsedHighs.push(parsedHigh)
parsedLows.push(parsedLow)
highs.push(high)
lows.push(low)
times.push(time)
//---------------------------------------------------------------------------------------------------------------------}
//USER-DEFINED FUNCTIONS
//---------------------------------------------------------------------------------------------------------------------{
// @function Get the value of the current leg, it can be 0 (bearish) or 1 (bullish)
// @returns int
leg(int size) =>
var leg = 0
newLegHigh = high[size] > ta.highest( size)
newLegLow = low[size] < ta.lowest( size)
if newLegHigh
leg := BEARISH_LEG
else if newLegLow
leg := BULLISH_LEG
leg
// @function Identify whether the current value is the start of a new leg (swing)
// @param leg (int) Current leg value
// @returns bool
startOfNewLeg(int leg) => ta.change(leg) != 0
// @function Identify whether the current level is the start of a new bearish leg (swing)
// @param leg (int) Current leg value
// @returns bool
startOfBearishLeg(int leg) => ta.change(leg) == -1
// @function Identify whether the current level is the start of a new bullish leg (swing)
// @param leg (int) Current leg value
// @returns bool
startOfBullishLeg(int leg) => ta.change(leg) == +1
// @function create a new label
// @param labelTime bar time coordinate
// @param labelPrice price coordinate
// @param tag text to display
// @param labelColor text color
// @param labelStyle label style
// @returns label ID
drawLabel(int labelTime, float labelPrice, string tag, color labelColor, string labelStyle) =>
var label l_abel = na
if modeInput == PRESENT
l_abel.delete()
l_abel := label.new(chart.point.new(labelTime,na,labelPrice),tag,xloc.bar_time,color=color(na),textcolor=labelColor,style = labelStyle,size = size.small)
// @function create a new line and label representing an EQH or EQL
// @param p_ivot starting pivot
// @param level price level of current pivot
// @param size how many bars ago was the current pivot detected
// @param equalHigh true for EQH, false for EQL
// @returns label ID
drawEqualHighLow(pivot p_ivot, float level, int size, bool equalHigh) =>
equalDisplay e_qualDisplay = equalHigh ? equalHighDisplay : equalLowDisplay
string tag = 'EQL'
color equalColor = swingBullishColor
string labelStyle = label.style_label_up
if equalHigh
tag := 'EQH'
equalColor := swingBearishColor
labelStyle := label.style_label_down
if modeInput == PRESENT
line.delete( e_qualDisplay.l_ine)
label.delete( e_qualDisplay.l_abel)
e_qualDisplay.l_ine := line.new(chart.point.new(p_ivot.barTime,na,p_ivot.currentLevel), chart.point.new(time[size],na,level), xloc = xloc.bar_time, color = equalColor, style = line.style_dotted)
labelPosition = math.round(0.5*(p_ivot.barIndex + bar_index - size))
e_qualDisplay.l_abel := label.new(chart.point.new(na,labelPosition,level), tag, xloc.bar_index, color = color(na), textcolor = equalColor, style = labelStyle, size = equalHighsLowsSizeInput)
// @function store current structure and trailing swing points, and also display swing points and equal highs/lows
// @param size (int) structure size
// @param equalHighLow (bool) true for displaying current highs/lows
// @param internal (bool) true for getting internal structures
// @returns label ID
getCurrentStructure(int size,bool equalHighLow = false, bool internal = false) =>
currentLeg = leg(size)
newPivot = startOfNewLeg(currentLeg)
pivotLow = startOfBullishLeg(currentLeg)
pivotHigh = startOfBearishLeg(currentLeg)
if newPivot
if pivotLow
pivot p_ivot = equalHighLow ? equalLow : internal ? internalLow : swingLow
if equalHighLow and math.abs(p_ivot.currentLevel - low[size]) < equalHighsLowsThresholdInput * atrMeasure
drawEqualHighLow(p_ivot, low[size], size, false)
p_ivot.lastLevel := p_ivot.currentLevel
p_ivot.currentLevel := low[size]
p_ivot.crossed := false
p_ivot.barTime := time[size]
p_ivot.barIndex := bar_index[size]
if not equalHighLow and not internal
trailing.bottom := p_ivot.currentLevel
trailing.barTime := p_ivot.barTime
trailing.barIndex := p_ivot.barIndex
trailing.lastBottomTime := p_ivot.barTime
if showSwingsInput and not internal and not equalHighLow
drawLabel(time[size], p_ivot.currentLevel, p_ivot.currentLevel < p_ivot.lastLevel ? 'LL' : 'HL', swingBullishColor, label.style_label_up)
else
pivot p_ivot = equalHighLow ? equalHigh : internal ? internalHigh : swingHigh
if equalHighLow and math.abs(p_ivot.currentLevel - high[size]) < equalHighsLowsThresholdInput * atrMeasure
drawEqualHighLow(p_ivot,high[size],size,true)
p_ivot.lastLevel := p_ivot.currentLevel
p_ivot.currentLevel := high[size]
p_ivot.crossed := false
p_ivot.barTime := time[size]
p_ivot.barIndex := bar_index[size]
if not equalHighLow and not internal
trailing.top := p_ivot.currentLevel
trailing.barTime := p_ivot.barTime
trailing.barIndex := p_ivot.barIndex
trailing.lastTopTime := p_ivot.barTime
if showSwingsInput and not internal and not equalHighLow
drawLabel(time[size], p_ivot.currentLevel, p_ivot.currentLevel > p_ivot.lastLevel ? 'HH' : 'LH', swingBearishColor, label.style_label_down)
// @function draw line and label representing a structure
// @param p_ivot base pivot point
// @param tag test to display
// @param structureColor base color
// @param lineStyle line style
// @param labelStyle label style
// @param labelSize text size
// @returns label ID
drawStructure(pivot p_ivot, string tag, color structureColor, string lineStyle, string labelStyle, string labelSize) =>
var line l_ine = line.new(na,na,na,na,xloc = xloc.bar_time)
var label l_abel = label.new(na,na)
if modeInput == PRESENT
l_ine.delete()
l_abel.delete()
l_ine := line.new(chart.point.new(p_ivot.barTime,na,p_ivot.currentLevel), chart.point.new(time,na,p_ivot.currentLevel), xloc.bar_time, color=structureColor, style=lineStyle)
l_abel := label.new(chart.point.new(na,math.round(0.5*(p_ivot.barIndex+bar_index)),p_ivot.currentLevel), tag, xloc.bar_index, color=color(na), textcolor=structureColor, style=labelStyle, size = labelSize)
// @function delete order blocks
// @param internal true for internal order blocks
// @returns orderBlock ID
deleteOrderBlocks(bool internal = false) =>
array<orderBlock> orderBlocks = internal ? internalOrderBlocks : swingOrderBlocks
for [index,eachOrderBlock] in orderBlocks
bool crossedOderBlock = false
if bearishOrderBlockMitigationSource > eachOrderBlock.barHigh and eachOrderBlock.bias == BEARISH
crossedOderBlock := true
if internal
currentAlerts.internalBearishOrderBlock := true
else
currentAlerts.swingBearishOrderBlock := true
else if bullishOrderBlockMitigationSource < eachOrderBlock.barLow and eachOrderBlock.bias == BULLISH
crossedOderBlock := true
if internal
currentAlerts.internalBullishOrderBlock := true
else
currentAlerts.swingBullishOrderBlock := true
if crossedOderBlock
orderBlocks.remove(index)
// @function fetch and store order blocks
// @param p_ivot base pivot point
// @param internal true for internal order blocks
// @param bias BULLISH or BEARISH
// @returns void
storeOrdeBlock(pivot p_ivot,bool internal = false,int bias) =>
if (not internal and showSwingOrderBlocksInput) or (internal and showInternalOrderBlocksInput)
array<float> a_rray = na
int parsedIndex = na
if bias == BEARISH
a_rray := parsedHighs.slice(p_ivot.barIndex,bar_index)
parsedIndex := p_ivot.barIndex + a_rray.indexof(a_rray.max())
else
a_rray := parsedLows.slice(p_ivot.barIndex,bar_index)
parsedIndex := p_ivot.barIndex + a_rray.indexof(a_rray.min())
orderBlock o_rderBlock = orderBlock.new(parsedHighs.get(parsedIndex), parsedLows.get(parsedIndex), times.get(parsedIndex),bias)
array<orderBlock> orderBlocks = internal ? internalOrderBlocks : swingOrderBlocks
if orderBlocks.size() >= 100
orderBlocks.pop()
orderBlocks.unshift(o_rderBlock)
// @function draw order blocks as boxes
// @param internal true for internal order blocks
// @returns void
drawOrderBlocks(bool internal = false) =>
array<orderBlock> orderBlocks = internal ? internalOrderBlocks : swingOrderBlocks
orderBlocksSize = orderBlocks.size()
if orderBlocksSize > 0
maxOrderBlocks = internal ? internalOrderBlocksSizeInput : swingOrderBlocksSizeInput
array<orderBlock> parsedOrdeBlocks = orderBlocks.slice(0, math.min(maxOrderBlocks,orderBlocksSize))
array<box> b_oxes = internal ? internalOrderBlocksBoxes : swingOrderBlocksBoxes
for [index,eachOrderBlock] in parsedOrdeBlocks
orderBlockColor = styleInput == MONOCHROME ? (eachOrderBlock.bias == BEARISH ? color.new(MONO_BEARISH,80) : color.new(MONO_BULLISH,80)) : internal ? (eachOrderBlock.bias == BEARISH ? internalBearishOrderBlockColor : internalBullishOrderBlockColor) : (eachOrderBlock.bias == BEARISH ? swingBearishOrderBlockColor : swingBullishOrderBlockColor)
box b_ox = b_oxes.get(index)
b_ox.set_top_left_point( chart.point.new(eachOrderBlock.barTime,na,eachOrderBlock.barHigh))
b_ox.set_bottom_right_point(chart.point.new(last_bar_time,na,eachOrderBlock.barLow))
b_ox.set_border_color( internal ? na : orderBlockColor)
b_ox.set_bgcolor( orderBlockColor)
// @function detect and draw structures, also detect and store order blocks
// @param internal true for internal structures or order blocks
// @returns void
displayStructure(bool internal = false) =>
var bullishBar = true
var bearishBar = true
if internalFilterConfluenceInput
bullishBar := high - math.max(close, open) > math.min(close, open - low)
bearishBar := high - math.max(close, open) < math.min(close, open - low)
pivot p_ivot = internal ? internalHigh : swingHigh
trend t_rend = internal ? internalTrend : swingTrend
lineStyle = internal ? line.style_dashed : line.style_solid
labelSize = internal ? internalStructureSize : swingStructureSize
extraCondition = internal ? internalHigh.currentLevel != swingHigh.currentLevel and bullishBar : true
bullishColor = styleInput == MONOCHROME ? MONO_BULLISH : internal ? internalBullColorInput : swingBullColorInput
if ta.crossover(close,p_ivot.currentLevel) and not p_ivot.crossed and extraCondition
string tag = t_rend.bias == BEARISH ? CHOCH : BOS
if internal
currentAlerts.internalBullishCHoCH := tag == CHOCH
currentAlerts.internalBullishBOS := tag == BOS
else
currentAlerts.swingBullishCHoCH := tag == CHOCH
currentAlerts.swingBullishBOS := tag == BOS
p_ivot.crossed := true
t_rend.bias := BULLISH
displayCondition = internal ? showInternalsInput and (showInternalBullInput == ALL or (showInternalBullInput == BOS and tag != CHOCH) or (showInternalBullInput == CHOCH and tag == CHOCH)) : showStructureInput and (showSwingBullInput == ALL or (showSwingBullInput == BOS and tag != CHOCH) or (showSwingBullInput == CHOCH and tag == CHOCH))
if displayCondition
drawStructure(p_ivot,tag,bullishColor,lineStyle,label.style_label_down,labelSize)
if (internal and showInternalOrderBlocksInput) or (not internal and showSwingOrderBlocksInput)
storeOrdeBlock(p_ivot,internal,BULLISH)
p_ivot := internal ? internalLow : swingLow
extraCondition := internal ? internalLow.currentLevel != swingLow.currentLevel and bearishBar : true
bearishColor = styleInput == MONOCHROME ? MONO_BEARISH : internal ? internalBearColorInput : swingBearColorInput
if ta.crossunder(close,p_ivot.currentLevel) and not p_ivot.crossed and extraCondition
string tag = t_rend.bias == BULLISH ? CHOCH : BOS
if internal
currentAlerts.internalBearishCHoCH := tag == CHOCH
currentAlerts.internalBearishBOS := tag == BOS
else
currentAlerts.swingBearishCHoCH := tag == CHOCH
currentAlerts.swingBearishBOS := tag == BOS
p_ivot.crossed := true
t_rend.bias := BEARISH
displayCondition = internal ? showInternalsInput and (showInternalBearInput == ALL or (showInternalBearInput == BOS and tag != CHOCH) or (showInternalBearInput == CHOCH and tag == CHOCH)) : showStructureInput and (showSwingBearInput == ALL or (showSwingBearInput == BOS and tag != CHOCH) or (showSwingBearInput == CHOCH and tag == CHOCH))
if displayCondition
drawStructure(p_ivot,tag,bearishColor,lineStyle,label.style_label_up,labelSize)
if (internal and showInternalOrderBlocksInput) or (not internal and showSwingOrderBlocksInput)
storeOrdeBlock(p_ivot,internal,BEARISH)
// @function draw one fair value gap box (each fair value gap has two boxes)
// @param leftTime left time coordinate
// @param rightTime right time coordinate
// @param topPrice top price level
// @param bottomPrice bottom price level
// @param boxColor box color
// @returns box ID
fairValueGapBox(leftTime,rightTime,topPrice,bottomPrice,boxColor) => box.new(chart.point.new(leftTime,na,topPrice),chart.point.new(rightTime + fairValueGapsExtendInput * (time-time[1]),na,bottomPrice), xloc=xloc.bar_time, border_color = boxColor, bgcolor = boxColor)
// @function delete fair value gaps
// @returns fairValueGap ID
deleteFairValueGaps() =>
for [index,eachFairValueGap] in fairValueGaps
if (low < eachFairValueGap.bottom and eachFairValueGap.bias == BULLISH) or (high > eachFairValueGap.top and eachFairValueGap.bias == BEARISH)
eachFairValueGap.topBox.delete()
eachFairValueGap.bottomBox.delete()
fairValueGaps.remove(index)
// @function draw fair value gaps
// @returns fairValueGap ID
drawFairValueGaps() =>
[lastClose, lastOpen, lastTime, currentHigh, currentLow, currentTime, last2High, last2Low] = request.security(syminfo.tickerid, fairValueGapsTimeframeInput, [close[1], open[1], time[1], high[0], low[0], time[0], high[2], low[2]],lookahead = barmerge.lookahead_on)
barDeltaPercent = (lastClose - lastOpen) / (lastOpen * 100)
newTimeframe = timeframe.change(fairValueGapsTimeframeInput)
threshold = fairValueGapsThresholdInput ? ta.cum(math.abs(newTimeframe ? barDeltaPercent : 0)) / bar_index * 2 : 0
bullishFairValueGap = currentLow > last2High and lastClose > last2High and barDeltaPercent > threshold and newTimeframe
bearishFairValueGap = currentHigh < last2Low and lastClose < last2Low and -barDeltaPercent > threshold and newTimeframe
if bullishFairValueGap
currentAlerts.bullishFairValueGap := true
fairValueGaps.unshift(fairValueGap.new(currentLow,last2High,BULLISH,fairValueGapBox(lastTime,currentTime,currentLow,math.avg(currentLow,last2High),fairValueGapBullishColor),fairValueGapBox(lastTime,currentTime,math.avg(currentLow,last2High),last2High,fairValueGapBullishColor)))
if bearishFairValueGap
currentAlerts.bearishFairValueGap := true
fairValueGaps.unshift(fairValueGap.new(currentHigh,last2Low,BEARISH,fairValueGapBox(lastTime,currentTime,currentHigh,math.avg(currentHigh,last2Low),fairValueGapBearishColor),fairValueGapBox(lastTime,currentTime,math.avg(currentHigh,last2Low),last2Low,fairValueGapBearishColor)))
// @function get line style from string
// @param style line style
// @returns string
getStyle(string style) =>
switch style
SOLID => line.style_solid
DASHED => line.style_dashed
DOTTED => line.style_dotted
// @function draw MultiTimeFrame levels
// @param timeframe base timeframe
// @param sameTimeframe true if chart timeframe is same as base timeframe
// @param style line style
// @param levelColor line and text color
// @returns void
drawLevels(string timeframe, bool sameTimeframe, string style, color levelColor) =>
[topLevel, bottomLevel, leftTime, rightTime] = request.security(syminfo.tickerid, timeframe, [high[1], low[1], time[1], time],lookahead = barmerge.lookahead_on)
float parsedTop = sameTimeframe ? high : topLevel
float parsedBottom = sameTimeframe ? low : bottomLevel
int parsedLeftTime = sameTimeframe ? time : leftTime
int parsedRightTime = sameTimeframe ? time : rightTime
int parsedTopTime = time
int parsedBottomTime = time
if not sameTimeframe
int leftIndex = times.binary_search_rightmost(parsedLeftTime)
int rightIndex = times.binary_search_rightmost(parsedRightTime)
array<int> timeArray = times.slice(leftIndex,rightIndex)
array<float> topArray = highs.slice(leftIndex,rightIndex)
array<float> bottomArray = lows.slice(leftIndex,rightIndex)
parsedTopTime := timeArray.size() > 0 ? timeArray.get(topArray.indexof(topArray.max())) : initialTime
parsedBottomTime := timeArray.size() > 0 ? timeArray.get(bottomArray.indexof(bottomArray.min())) : initialTime
var line topLine = line.new(na, na, na, na, xloc = xloc.bar_time, color = levelColor, style = getStyle(style))
var line bottomLine = line.new(na, na, na, na, xloc = xloc.bar_time, color = levelColor, style = getStyle(style))
var label topLabel = label.new(na, na, xloc = xloc.bar_time, text = str.format('P{0}H',timeframe), color=color(na), textcolor = levelColor, size = size.small, style = label.style_label_left)
var label bottomLabel = label.new(na, na, xloc = xloc.bar_time, text = str.format('P{0}L',timeframe), color=color(na), textcolor = levelColor, size = size.small, style = label.style_label_left)
topLine.set_first_point( chart.point.new(parsedTopTime,na,parsedTop))
topLine.set_second_point( chart.point.new(last_bar_time + 20 * (time-time[1]),na,parsedTop))
topLabel.set_point( chart.point.new(last_bar_time + 20 * (time-time[1]),na,parsedTop))
bottomLine.set_first_point( chart.point.new(parsedBottomTime,na,parsedBottom))
bottomLine.set_second_point(chart.point.new(last_bar_time + 20 * (time-time[1]),na,parsedBottom))
bottomLabel.set_point( chart.point.new(last_bar_time + 20 * (time-time[1]),na,parsedBottom))
// @function true if chart timeframe is higher than provided timeframe
// @param timeframe timeframe to check
// @returns bool
higherTimeframe(string timeframe) => timeframe.in_seconds() > timeframe.in_seconds(timeframe)
// @function update trailing swing points
// @returns int
updateTrailingExtremes() =>
trailing.top := math.max(high,trailing.top)
trailing.lastTopTime := trailing.top == high ? time : trailing.lastTopTime
trailing.bottom := math.min(low,trailing.bottom)
trailing.lastBottomTime := trailing.bottom == low ? time : trailing.lastBottomTime
// @function draw trailing swing points
// @returns void
drawHighLowSwings() =>
var line topLine = line.new(na, na, na, na, color = swingBearishColor, xloc = xloc.bar_time)
var line bottomLine = line.new(na, na, na, na, color = swingBullishColor, xloc = xloc.bar_time)
var label topLabel = label.new(na, na, color=color(na), textcolor = swingBearishColor, xloc = xloc.bar_time, style = label.style_label_down, size = size.tiny)
var label bottomLabel = label.new(na, na, color=color(na), textcolor = swingBullishColor, xloc = xloc.bar_time, style = label.style_label_up, size = size.tiny)
rightTimeBar = last_bar_time + 20 * (time - time[1])
topLine.set_first_point( chart.point.new(trailing.lastTopTime, na, trailing.top))
topLine.set_second_point( chart.point.new(rightTimeBar, na, trailing.top))
topLabel.set_point( chart.point.new(rightTimeBar, na, trailing.top))
topLabel.set_text( swingTrend.bias == BEARISH ? 'Strong High' : 'Weak High')
bottomLine.set_first_point( chart.point.new(trailing.lastBottomTime, na, trailing.bottom))
bottomLine.set_second_point(chart.point.new(rightTimeBar, na, trailing.bottom))
bottomLabel.set_point( chart.point.new(rightTimeBar, na, trailing.bottom))
bottomLabel.set_text( swingTrend.bias == BULLISH ? 'Strong Low' : 'Weak Low')
// @function draw a zone with a label and a box
// @param labelLevel price level for label
// @param labelIndex bar index for label
// @param top top price level for box
// @param bottom bottom price level for box
// @param tag text to display
// @param zoneColor base color
// @param style label style
// @returns void
drawZone(float labelLevel, int labelIndex, float top, float bottom, string tag, color zoneColor, string style) =>
var label l_abel = label.new(na,na,text = tag, color=color(na),textcolor = zoneColor, style = style, size = size.small)
var box b_ox = box.new(na,na,na,na,bgcolor = color.new(zoneColor,80),border_color = color(na), xloc = xloc.bar_time)
b_ox.set_top_left_point( chart.point.new(trailing.barTime,na,top))
b_ox.set_bottom_right_point(chart.point.new(last_bar_time,na,bottom))
l_abel.set_point( chart.point.new(na,labelIndex,labelLevel))
// @function draw premium/discount zones
// @returns void
drawPremiumDiscountZones() =>
drawZone(trailing.top, math.round(0.5*(trailing.barIndex + last_bar_index)), trailing.top, 0.95*trailing.top + 0.05*trailing.bottom, 'Premium', premiumZoneColor, label.style_label_down)
equilibriumLevel = math.avg(trailing.top, trailing.bottom)
drawZone(equilibriumLevel, last_bar_index, 0.525*trailing.top + 0.475*trailing.bottom, 0.525*trailing.bottom + 0.475*trailing.top, 'Equilibrium', equilibriumZoneColorInput, label.style_label_left)
drawZone(trailing.bottom, math.round(0.5*(trailing.barIndex + last_bar_index)), 0.95*trailing.bottom + 0.05*trailing.top, trailing.bottom, 'Discount', discountZoneColor, label.style_label_up)
//---------------------------------------------------------------------------------------------------------------------}
//MUTABLE VARIABLES & EXECUTION
//---------------------------------------------------------------------------------------------------------------------{
parsedOpen = showTrendInput ? open : na
candleColor = internalTrend.bias == BULLISH ? swingBullishColor : swingBearishColor
plotcandle(parsedOpen,high,low,close,color = candleColor, wickcolor = candleColor, bordercolor = candleColor)
if showHighLowSwingsInput or showPremiumDiscountZonesInput
updateTrailingExtremes()
if showHighLowSwingsInput
drawHighLowSwings()
if showPremiumDiscountZonesInput
drawPremiumDiscountZones()
if showFairValueGapsInput
deleteFairValueGaps()
getCurrentStructure(swingsLengthInput,false)
getCurrentStructure(5,false,true)
if showEqualHighsLowsInput
getCurrentStructure(equalHighsLowsLengthInput,true)
if showInternalsInput or showInternalOrderBlocksInput or showTrendInput
displayStructure(true)
if showStructureInput or showSwingOrderBlocksInput or showHighLowSwingsInput
displayStructure()
if showInternalOrderBlocksInput
deleteOrderBlocks(true)
if showSwingOrderBlocksInput
deleteOrderBlocks()
if showFairValueGapsInput
drawFairValueGaps()
if barstate.islastconfirmedhistory or barstate.islast
if showInternalOrderBlocksInput
drawOrderBlocks(true)
if showSwingOrderBlocksInput
drawOrderBlocks()
lastBarIndex := currentBarIndex
currentBarIndex := bar_index
newBar = currentBarIndex != lastBarIndex
if barstate.islastconfirmedhistory or (barstate.isrealtime and newBar)
if showDailyLevelsInput and not higherTimeframe('D')
drawLevels('D',timeframe.isdaily,dailyLevelsStyleInput,dailyLevelsColorInput)
if showWeeklyLevelsInput and not higherTimeframe('W')
drawLevels('W',timeframe.isweekly,weeklyLevelsStyleInput,weeklyLevelsColorInput)
if showMonthlyLevelsInput and not higherTimeframe('M')
drawLevels('M',timeframe.ismonthly,monthlyLevelsStyleInput,monthlyLevelsColorInput)
//---------------------------------------------------------------------------------------------------------------------}
//ALERTS
//---------------------------------------------------------------------------------------------------------------------{
alertcondition(currentAlerts.internalBullishBOS, 'Internal Bullish BOS', 'Internal Bullish BOS formed')
alertcondition(currentAlerts.internalBullishCHoCH, 'Internal Bullish CHoCH', 'Internal Bullish CHoCH formed')
alertcondition(currentAlerts.internalBearishBOS, 'Internal Bearish BOS', 'Internal Bearish BOS formed')
alertcondition(currentAlerts.internalBearishCHoCH, 'Internal Bearish CHoCH', 'Internal Bearish CHoCH formed')
alertcondition(currentAlerts.swingBullishBOS, 'Bullish BOS', 'Internal Bullish BOS formed')
alertcondition(currentAlerts.swingBullishCHoCH, 'Bullish CHoCH', 'Internal Bullish CHoCH formed')
alertcondition(currentAlerts.swingBearishBOS, 'Bearish BOS', 'Bearish BOS formed')
alertcondition(currentAlerts.swingBearishCHoCH, 'Bearish CHoCH', 'Bearish CHoCH formed')
alertcondition(currentAlerts.internalBullishOrderBlock, 'Bullish Internal OB Breakout', 'Price broke bullish internal OB')
alertcondition(currentAlerts.internalBearishOrderBlock, 'Bearish Internal OB Breakout', 'Price broke bearish internal OB')
alertcondition(currentAlerts.swingBullishOrderBlock, 'Bullish Swing OB Breakout', 'Price broke bullish swing OB')
alertcondition(currentAlerts.swingBearishOrderBlock, 'Bearish Swing OB Breakout', 'Price broke bearish swing OB')
alertcondition(currentAlerts.equalHighs, 'Equal Highs', 'Equal highs detected')
alertcondition(currentAlerts.equalLows, 'Equal Lows', 'Equal lows detected')
alertcondition(currentAlerts.bullishFairValueGap, 'Bullish FVG', 'Bullish FVG formed')
alertcondition(currentAlerts.bearishFairValueGap, 'Bearish FVG', 'Bearish FVG formed')
//---------------------------------------------------------------------------------------------------------------------}
// On-Balance Accumulation Distribution (Volume-Weighted) by [LeafAlgo] & candlestick analyzer by [a_b_c_x] //
// Link 1: https://id.tradingview.com/script/hgbhJQQB-On-Balance-Accumulation-Distribution-Volume-Weighted/ //
// Link 2: https://id.tradingview.com/script/LAJVNEqf/ //
groupPlot = 'Accum/Distri Zones'
HiddenPlot = input(true,title = "Hidden Accum/Distri Block", group=groupPlot,inline='line')
length = input.int(1, minval=1, title="Length",group=groupPlot)
volumeFactor = input(1.0, title="Volume Factor",group=groupPlot)
// Calculate OBAD
obad = math.sum(volume * close * volumeFactor * ta.change(close), length)
obadSignal = ta.sma(obad, 9)
upMayoi = -high + math.max(open, close)
downMayoi = -low + math.min(open, close)
Josho_Kitai = (upMayoi + downMayoi) / close
// Visualization Enhancements
obadColor = obad >= obadSignal ? color.lime : color.fuchsia
obadbgColor = obad >= obadSignal ? color.new(color.lime, 10) : color.new(color.fuchsia, 10)
obadsigColor = obadSignal > 0 ? color.green : color.maroon
//barcolor(obadColor)
//bgcolor(obadbgColor)
// Plotting Accum/Distri
//plot(HiddenPlot?na: math.sum(Josho_Kitai, length) / length, color=obadsigColor, style=plot.style_steplinebr, linewidth=50, display = display.pane)
// Other Plotting Options
//hline(0, "Zero Line", color=color.gray)
// Background Kuadran
//Insert your stock ticker here
ticker = syminfo.ticker
//Define the period for your calculations
groupBg = 'BG Color Kuadran'
len = input.int(20, minval=1, title='Length',group=groupBg)
HiddenBgKuadran = input(true,title = "Hidden Background Kuadran", group=groupBg,inline='line')
window = len
//Calculate the Close price of the chosen stock
stock_close = request.security(ticker, timeframe.period, close)
stock_ema = ta.ema(stock_close, 25)
//Get the Close price of the S&P 500 Index for the Relative Strength calculation
index_close = request.security('COMPOSITE', timeframe.period, close)
//Calculate the Relative Strength (RS)
rs = stock_close / index_close * 100
//Calculate From Relative Strength scatter Plot//
rs1 = stock_close / index_close
wma_rs = ta.wma(rs1, len)
//Normalization
jdk_rs_ratio = ta.wma(rs1 / wma_rs, len) * 100
jdk_rm_ratio = jdk_rs_ratio / ta.wma(jdk_rs_ratio, len) * 100
//Plot JUnit RS and JUnit RoC
// plot(jdk_rs_ratio, color=color.new(color.blue, 0), title='JUnit RS')
// plot(jdk_rm_ratio, color=color.new(color.red, 0), title='Junit RoC')
//hline(100, 'Zero Line', color=color.gray)
statecolor = color.purple
if statecolor[1] == color.green
statecolor := color.green
statecolor
else if statecolor[1] == color.red
statecolor := color.red
statecolor
else if statecolor[1] == color.yellow
statecolor := color.yellow
statecolor
else if statecolor[1] == color.blue
statecolor := color.blue
statecolor
if jdk_rs_ratio > 100 and jdk_rm_ratio > 100
statecolor := color.green
statecolor
else if jdk_rs_ratio > 100 and jdk_rm_ratio < 100
statecolor := color.yellow
statecolor
else if jdk_rs_ratio < 100 and jdk_rm_ratio < 100
statecolor := color.red
statecolor
else if jdk_rs_ratio < 100 and jdk_rm_ratio > 100
statecolor := color.blue
statecolor
buy_signal = statecolor[0] == color.green and year >= 2010
sell_signal = statecolor[0] == color.red
hold_signal = statecolor[0] == color.yellow
watch_signal = statecolor[0] == color.blue
//Add color to background when both JUnit RS and JUnit RoC cross above 100
bgcolor(HiddenBgKuadran?na: buy_signal ? color.green : na, transp=30)
bgcolor(HiddenBgKuadran?na:sell_signal ? color.red : na, transp=30)
bgcolor(HiddenBgKuadran?na:hold_signal ? color.yellow : na, transp=30)
bgcolor(HiddenBgKuadran?na:watch_signal ? color.blue : na, transp=30)
// Chop Zone - SamX by [SamAccountX] //
// Link : https://id.tradingview.com/script/8IaHOdPX-Chop-Zone-SamX/ //
g_NormalInputs = 'Basic Configuration'
tf = input.timeframe(title="Timeframe", defval="", group=g_NormalInputs)
showGaps = input.bool(title="Show gaps for higher timeframes", defval=true, group=g_NormalInputs, tooltip="If selected, higher TF values will only be returned when " +
'the higher timeframe bar actually closes. This helps avoid real-time repaining at the expense of potential resolution clarity. \n\n' +
'If this option is unchecked, the current bar will be populated with the current higher TF bar\'s value (which will repaint), however ' +
'historical bars will not repaint.')
src = input.source(title='MA Source', defval=close, group=g_NormalInputs, tooltip="Price source to use for calculating the MA basis for the chop zones.")
lenc = input.int(title='MA Length', defval=34, minval=1, maxval=500, step=1, group=g_NormalInputs, tooltip="Length to use for calculating the MA basis for the chop zones.")
showAsAngleArea = input.bool(title="Plot calculated angle", defval=false, group=g_NormalInputs, tooltip="If selected, the default bar-style chop zone will be replaced with an " +
'Area-style chart displaying the actual calculated angles. \n\n' +
'Note #1: This works best using the Gradient color settings below. \n\n' +
'Note #2: If configured to calculate on a timeframe HIGHER than the current chart timeframe, it is recommended to un-check the "Show gaps for higher timeframes" setting above ' +
'to avoid display anomolies.')
// Coloring settings
// Gradient settings
g_GradientSettings = "Gradient Color Settings"
colorAsGradient = input.bool(title="Color bars using gradient", defval=false, group=g_GradientSettings)
downColor = input.color(title="Downslope:", defval=color.rgb(255, 0, 0, 0), inline="Gradient", group=g_GradientSettings)
upColor = input.color(title=" Upslope:", defval=color.rgb(0, 255, 0, 0), inline="Gradient", group=g_GradientSettings)
gradientLimit = input.int(title="Gradient Limit", defval=33, minval=1, maxval=89, step=1, group=g_GradientSettings, tooltip="Select the desired gradient threshold angle. This " +
'will be used in gradient color calculations. This value will be extrapolated as the absolute distance from 0. If the calculated angle exceeds this threshold, the resulting ' +
'bar color will be the equivilent of the closest in-range color.')
// Fixed bar color settings
g_BarColors = 'Bar colors'
// Tier 0 - centered on 0 degrees
colorLevel0 = input.color(title=" Tier-1 Color:", defval=color.rgb(253, 216, 53, 0), group=g_BarColors)
// Tier 1 - 1x past tier 0
colorLevel1Pos = input.color(title="Tier-2 Color - Positive:", defval=color.rgb(0, 150, 136, 0), group=g_BarColors, inline="tier-2")
colorLevel1Neg = input.color(title=" Negative:", defval=color.rgb(255, 183, 77, 0), group=g_BarColors, inline="tier-2")
// Tier 2 - 1x past tier 1
colorLevel2Pos = input.color(title="Tier-3 Color - Positive:", defval=color.rgb(165, 214, 167, 0), group=g_BarColors, inline="tier-3")
colorLevel2Neg = input.color(title=" Negative:", defval=color.rgb(255, 109, 0, 0), group=g_BarColors, inline="tier-3")
// Tier 3 - 1x past tier 2
colorLevel3Pos = input.color(title="Tier-4 Color - Positive:", defval=color.rgb(67, 160, 71, 0), group=g_BarColors, inline="tier-4")
colorLevel3Neg = input.color(title=" Negative:", defval=color.rgb(233, 30, 99, 0), group=g_BarColors, inline="tier-4")
// Tier 4 - 1x past tier 3
colorLevel4Pos = input.color(title="Tier-5 Color - Positive:", defval=color.rgb(38, 198, 218, 0), group=g_BarColors, inline="tier-5")
colorLevel4Neg = input.color(title=" Negative:", defval=color.rgb(213, 0, 0, 0), group=g_BarColors, inline="tier-5")
//
// Advanced input settings - generally should not be changed...
g_AdvancedInputs = 'Advanced Configuration'
maType = input.string(title='Moving Average Calculation', group=g_AdvancedInputs, options=['Exponential', 'Simple', 'Smoothed', 'Weighted', 'Linear', 'Hull', 'Volume-Weigehted', 'RMA', 'ALMA'],
defval='Exponential', tooltip='Type of moving average calculation to use (default is Exponential (EMA)). ALMA uses the standard values for sigma and offset. \n\n' +
'Note: DO NOT CHANGE THIS UNLESS YOU KNOW WHAT YOU\'RE DOING!!!')
periodsIn = input.int(title='Periods', defval=30, minval=1, maxval=300, step=1, group=g_AdvancedInputs, tooltip='Number of candles to check when searching for highest high and lowest low. \n\n' +
'Note: DO NOT CHANGE THIS UNLESS YOU KNOW WHAT YOU\'RE DOING!!!')
spanFactor = input.int(title='Span Length', defval=25, minval=1, maxval=100, step=1, group=g_AdvancedInputs, tooltip='Span length for range calculations. \n\n' +
'Note: DO NOT CHANGE THIS UNLESS YOU KNOW WHAT YOU\'RE DOING!!!')
periodAvgSrc = input.string(title='Period/Bar Average', defval="hlc3", options=["hl2", "hlc3", "ohlc4", "hlcc4"], tooltip='Method to use to derive the average price for a ' +
'given bar for use in slope calculations. \n\n' +
'Note: DO NOT CHANGE THIS UNLESS YOU KNOW WHAT YOU\'RE DOING!!!')
stepSize = input.float(title="Bar Step Size", defval=1.43, minval=.01, maxval=10, step=0.1, group=g_AdvancedInputs, tooltip='Step size to use for chop zone brackets. Increasing this will result ' +
'in each bar covering a wider range of angles, while decreasing this will result in each bar covering a narrower range of angles.')
useAltSlopeCalc = input.bool(title='Use alternate slope calculation method', defval=false, group=g_AdvancedInputs, tooltip='Select this to find the MA slope using an alternate calculation method. \n\n' +
'Note: DO NOT CHANGE THIS UNLESS YOU KNOW WHAT YOU\'RE DOING!!!')
//
// *** Function definitions ***
// Smoothed MA
smoothedMovingAvg(src, lenc) =>
smma = 0.0
// TV will complain about the use of the ta.sma function use inside a function saying that it should be called on each calculation,
// but since we're only using it once to set the initial value for the smoothed MA (when the previous smma value is NaN - Not a Number)
// and using the previous smma value for each subsequent iteration, this can be safely ignored
smma := na(smma[1]) ? ta.sma(src, lenc) : (smma[1] * (lenc - 1) + src) / lenc
smma
//
// MA calculation
ma(source, length, type) =>
switch type
"Simple" => ta.sma(source, length)
"Exponential" => ta.ema(source, length)
"Weighted" => ta.wma(source, length)
"Volume-Weigehted" => ta.vwma(source, length)
"Smoothed" => smoothedMovingAvg(source, length)
"RMA" => ta.rma(source, length)
"Linear" => ta.linreg(source, length, 0)
"Hull" => ta.hma(source, length)
"ALMA" => ta.alma(source, length, 0.85, 6)
//
// *** Functional code start ***
//
// Explicitly define our ticker to help ensure that we're always getting ACTUAL price instead of relying on the input
// ticker info and input vars (as they tend to inherit the type from what's displayed on the current chart)
realPriceTicker = ticker.new(prefix=syminfo.prefix, ticker=syminfo.ticker)
avgCalc = switch periodAvgSrc
"hl2" => hl2
"hlc3" => hlc3
"ohlc4" => ohlc4
"hlcc4" => hlcc4
=> hlc3
avg = showGaps ? request.security(symbol=realPriceTicker, timeframe=tf, expression=avgCalc, lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_on) :
request.security(symbol=realPriceTicker, timeframe=tf, expression=avgCalc, lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_off)
pi = math.pi
periods = periodsIn
highestHigh = showGaps ? request.security(symbol=realPriceTicker, timeframe=tf, expression=ta.highest(periods), lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_on) :
request.security(symbol=realPriceTicker, timeframe=tf, expression=ta.highest(periods), lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_off)
lowestLow = showGaps ? request.security(symbol=realPriceTicker, timeframe=tf, expression=ta.lowest(periods), lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_on) :
request.security(symbol=realPriceTicker, timeframe=tf, expression=ta.lowest(periods), lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_off)
span = spanFactor / (highestHigh - lowestLow) * lowestLow
ema34 = showGaps ? request.security(symbol=realPriceTicker, timeframe=tf, expression=ma(src, len, maType), lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_on) :
request.security(symbol=realPriceTicker, timeframe=tf, expression=ma(src, len, maType), lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_off)
ema34_prev = showGaps ? request.security(symbol=realPriceTicker, timeframe=tf, expression=ma(src[1], len, maType), lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_on) :
request.security(symbol=realPriceTicker, timeframe=tf, expression=ma(src[1], len, maType), lookahead=barmerge.lookahead_off, gaps=barmerge.gaps_off)
var emaAngle = 0.0
if (useAltSlopeCalc)
rightX = 1
rightY = ema34
leftX = 0
leftY = ema34_prev
slope = (rightY - leftY) / (rightX - leftX)
angleRadians = math.atan(slope)
angleDegrees = math.todegrees(angleRadians)
emaAngle := angleDegrees //slope < 0 ? -angleDegrees : angleDegrees
else
x1_ema34 = 0
x2_ema34 = 1
y1_ema34 = 0
y2_ema34 = (ema34_prev - ema34) / avg * span
c_ema34 = math.sqrt((x2_ema34 - x1_ema34)*(x2_ema34 - x1_ema34) + (y2_ema34 - y1_ema34)*(y2_ema34 - y1_ema34))
emaAngle_1 = math.round(180 * math.acos((x2_ema34 - x1_ema34)/c_ema34) / pi)
emaAngle := y2_ema34 > 0 ? -emaAngle_1 : emaAngle_1
// Select color based on inputs and calculated MA angle...
//
// First, we need to calculate our 0-level zone. Since we need to also include the ACTUAL 0.00 angle as well, we
// have a few options for sizing this zone... For simplicity, we're going to divide our bar step size by 2 and
// round to 2 decimal places. Should rounding be required, we'll always round down.
//
// Unfortunately, TV doesn't have a `floor` function that can round to decimals (only integers), so we'll have to
// use some clever math gymnastics to accomplish this.
halfStep = math.floor((stepSize / 2) * 100) / 100
var color chopZoneColor = na
if (emaAngle >= 3*stepSize + halfStep)
chopZoneColor := colorLevel4Pos
else if (emaAngle < 3*stepSize + halfStep and emaAngle >= 2*stepSize + halfStep)
chopZoneColor := colorLevel3Pos
else if (emaAngle < 2*stepSize + halfStep and emaAngle >= stepSize + halfStep)
chopZoneColor := colorLevel2Pos
else if (emaAngle < stepSize + halfStep and emaAngle >= halfStep)
chopZoneColor := colorLevel1Pos
else if (emaAngle > -halfStep and emaAngle < halfStep)
// Between -.71 and .71
chopZoneColor := colorLevel0
else if (emaAngle > -stepSize - halfStep and emaAngle <= -halfStep)
chopZoneColor := colorLevel1Neg
else if (emaAngle > -2*stepSize - halfStep and emaAngle <= -stepSize - halfStep)
chopZoneColor := colorLevel2Neg
else if (emaAngle > -3*stepSize - halfStep and emaAngle <= -2*stepSize - halfStep)
chopZoneColor := colorLevel3Neg
else if (emaAngle <= -3*stepSize - halfStep)
chopZoneColor := colorLevel4Neg
if (colorAsGradient)
chopZoneColor := color.from_gradient(emaAngle, -gradientLimit, gradientLimit, downColor, upColor)
// plot(showAsAngleArea ? na : 5, title='Chop Zone', color=na(avg) ? na : chopZoneColor, style=plot.style_columns)
// plot(showAsAngleArea ? emaAngle : na, title='MA Angle', color=na(avg) ? na : chopZoneColor, style=plot.style_area)
// Trend Continuation Signals with TP & SL V2 by [UAlgo] //
// Link : https://my.tradingview.com/script/5fVw87rQ-Trend-Signals-with-TP-SL-UAlgo-Strategy/ //
srcTrend = input(close, title="Source", group = "Trend Continuation Signals with TP & SL")
Multiplier = input.float(5, title="Sensitivity (0.5 - 5)", step=0.1, defval=2, minval=0.5, maxval=5, group = "Trend Continuation Signals with TP & SL")
atrPeriods = input.int(14, title="ATR Length", defval=10, group = "Trend Continuation Signals with TP & SL")
atrCalcMethod = input.string("Method 1", title="ATR Calculation Methods", options=["Method 1", "Method 2"], group = "Trend Continuation Signals with TP & SL")
cloud_val = input.int(10, title="Cloud Moving Average Length", defval=10, minval=5, maxval=500, group = "Trend Continuation Signals with TP & SL")
showBuySellSignals = input.bool(true, title="Show Buy/Sell Signals", defval=true, group = "Trend Continuation Signals with TP & SL")
showMovingAverageCloud = input.bool(true, title="Show Cloud MA", group = "Trend Continuation Signals with TP & SL")
// TP & SL Group
tp_sl_method = input.string("ATR", title="TP & SL Type", options=["ATR", "Percent"], group="TP & SL")
atr_tp_multiplier = input.float(1.0, title="ATR TP Multiplier", defval=1.0, group="TP & SL", tooltip="Multiplier for ATR-based Take Profit", inline="ATR")
atr_sl_multiplier = input.float(1.0, title="ATR SL Multiplier", defval=1.0, group="TP & SL", tooltip="Multiplier for ATR-based Stop Loss", inline="ATR")
percent_tp = input.float(1.0, title="Percent TP (0 for Disabling)", minval=0, defval=2.0, group="TP & SL", tooltip="Percent for Take Profit", inline="Percent")
percent_sl = input.float(1.0, title="Percent SL (0 for Disabling)", minval=0, defval=2.0, group="TP & SL", tooltip="Percent for Stop Loss", inline="Percent")
// New signal handling option
prevent_multiple_positions = input.bool(true, title="Prevent Multiple Positions", defval=true, group="Position Management")
// Utility Functions
percent(nom, div) =>
100 * nom / div
src1 = ta.hma(open, 5)[1]
src2 = ta.hma(close, 12)
momm1 = ta.change(src1)
momm2 = ta.change(src2)
f1(m, n) => m >= n ? m : 0.0
f2(m, n) => m >= n ? 0.0 : -m
m1 = f1(momm1, momm2)
m2 = f2(momm1, momm2)
sm1 = math.sum(m1, 1)
sm2 = math.sum(m2, 1)
cmoCalc = percent(sm1 - sm2, sm1 + sm2)
hh = ta.highest(2)
h1 = ta.dev(hh, 2) ? na : hh
hpivot = fixnan(h1)
ll = ta.lowest(2)
l1 = ta.dev(ll, 2) ? na : ll
lpivot = fixnan(l1)
rsiCalc = ta.rsi(close, 9)
lowPivot = lpivot
highPivot = hpivot
sup = rsiCalc < 25 and cmoCalc > 50 and lowPivot
res = rsiCalc > 75 and cmoCalc < -50 and highPivot
atr2 = ta.sma(ta.tr, atrPeriods)
atr = atrCalcMethod == "Method 1" ? ta.atr(atrPeriods) : atr2
up = srcTrend - (Multiplier * atr)
up1 = nz(up[1], up)
up := close[1] > up1 ? math.max(up, up1) : up
dn = srcTrend + (Multiplier * atr)
dn1 = nz(dn[1], dn)
dn := close[1] < dn1 ? math.min(dn, dn1) : dn
trend = 1
trend := nz(trend[1], trend)
trend := trend == -1 and close > dn1 ? 1 : trend == 1 and close < up1 ? -1 : trend
buySignal = trend == 1 and trend[1] == -1
sellSignal = trend == -1 and trend[1] == 1
pos = 0.0
pos := buySignal ? 1 : sellSignal ? -1 : pos[1]
longCond = buySignal and pos[1] != 1
shortCond = sellSignal and pos[1] != -1
entryOfLongPosition = ta.valuewhen(longCond, close, 0)
entryOfShortPosition = ta.valuewhen(shortCond, close, 0)
sl_percent = percent_sl > 0 ? percent_sl / 100 : 99999
tp_percent = percent_tp > 0 ? percent_tp / 100 : 99999
stopLossForLong = tp_sl_method == "Percent" ? entryOfLongPosition * (1 - sl_percent) : entryOfLongPosition - atr_sl_multiplier * atr
stopLossForShort = tp_sl_method == "Percent" ? entryOfShortPosition * (1 + sl_percent) : entryOfShortPosition + atr_sl_multiplier * atr
takeProfitForLong = tp_sl_method == "Percent" ? entryOfLongPosition * (1 + tp_percent) : entryOfLongPosition + atr_tp_multiplier * atr
takeProfitForShort = tp_sl_method == "Percent" ? entryOfShortPosition * (1 - tp_percent) : entryOfShortPosition - atr_tp_multiplier * atr
long_sl = low < stopLossForLong and pos[1] == 1
short_sl = high > stopLossForShort and pos[1] == -1
if long_sl or short_sl
pos := 0
lindex = ta.valuewhen(longCond, bar_index, 0)
sindex = ta.valuewhen(shortCond, bar_index, 0)
entryColor = pos == 1 ? #2b98f1 : #af3cc4
hakiColor = pos == 1 ? color.rgb(36, 240, 80) : color.rgb(194, 58, 87)
if pos != 0
lineEntry = line.new(bar_index, pos > 0 ? entryOfLongPosition : entryOfShortPosition, pos > 0 ? lindex : sindex, pos > 0 ? entryOfLongPosition : entryOfShortPosition, color=entryColor)
line.delete(lineEntry[1])
// labelEntry = label.new(bar_index, pos > 0 ? entryOfLongPosition : entryOfShortPosition, color=entryColor, textcolor=#ffffff, style=label.style_label_left, text="HAKA: " + str.tostring(pos > 0 ? entryOfLongPosition : entryOfShortPosition))
// label.delete(labelEntry[1])
//stopLine = line.new(bar_index, pos > 0 ? stopLossForLong : stopLossForShort, pos > 0 ? lindex : sindex, pos > 0 ? stopLossForLong : stopLossForShort, color=color.red)
tpLine = line.new(bar_index, pos > 0 ? takeProfitForLong : takeProfitForShort, pos > 0 ? lindex : sindex, pos > 0 ? takeProfitForLong : takeProfitForShort, color=color.green)
//line.delete(stopLine[1])
line.delete(tpLine[1])
// labelStop = label.new(bar_index, pos > 0 ? stopLossForLong : stopLossForShort, color=color.red, textcolor=#000000, style=label.style_label_left, text="Stop Loss Price: " + str.tostring(math.round((pos > 0 ? stopLossForLong : stopLossForShort) * 100) / 100))
// labelTp = label.new(bar_index, pos > 0 ? takeProfitForLong : takeProfitForShort, color=hakiColor, textcolor=#000000, style=label.style_label_left, text="HAKI: " + str.tostring(math.round((pos > 0 ? takeProfitForLong : takeProfitForShort) * 100) / 100))
// label.delete(labelStop[1])
//label.delete(labelTp[1])
changeCond = trend != trend[1]
smaSrcHigh = ta.ema(high, cloud_val)
smaSrcLow = ta.ema(low, cloud_val)
[macdLine, signalLine, histLine] = ta.macd(close, 12, 26, 9)
plot_high = plot(showMovingAverageCloud ? smaSrcHigh : na, color=na, transp=1, editable=false)
plot_low = plot(showMovingAverageCloud ? smaSrcLow : na, color=na, transp=1, editable=false)
plotshape(longCond ? up : na, title="UpTrend Begins", location=location.belowbar, style=shape.triangleup, size=size.tiny, color=color.new(color.teal, transp=20))
plotshape(longCond and showBuySellSignals ? up : na, title="Buy", text="Buy", location=location.belowbar, style=shape.labelup, size=size.tiny, color=color.new(color.teal, transp=20), textcolor=color.white)
plotshape(shortCond ? dn : na, title="DownTrend Begins", location=location.abovebar, style=shape.triangledown, size=size.tiny, color=color.new(color.red, transp=20))
plotshape(shortCond and showBuySellSignals ? dn : na, title="Sell", text="Sell", location=location.abovebar, style=shape.labeldown, size=size.tiny, color=color.new(color.red, transp=20), textcolor=color.white)
// fill(plot_high, plot_low, color=(macdLine > 0) and (macdLine[0] > macdLine[1]) ? color.new(color.aqua, transp=85) : na, title="Positive Cloud Uptrend")
// fill(plot_high, plot_low, color=macdLine > 0 and macdLine[0] < macdLine[1] ? color.new(color.aqua, transp=85) : na, title="Positive Cloud Downtrend")
// fill(plot_high, plot_low, color=macdLine < 0 and macdLine[0] < macdLine[1] ? color.new(color.red, transp=85) : na, title="Negative Cloud Uptrend")
// fill(plot_high, plot_low, color=macdLine < 0 and macdLine[0] > macdLine[1] ? color.new(color.red, transp=85) : na, title="Negative Cloud Downtrend")
mPlot = plot(ohlc4, title="", style=plot.style_circles, linewidth=0)
// Big Money Detector by [hunterfreaks] //
// Link : https://id.tradingview.com/u/hunterfreaks //
volMultiplier = input.float(2.0, title="Volume Spike Multiplier")
// Multiplier for detecting a candle range spike
rangeMultiplier = input.float(1.5, title="Candle Range Spike Multiplier")
// Length of the moving average used in spike calculations
lengthBig = input.int(60, title="Length for Average Calculation") // Replaced 20 with 60 for longer-term context
// === Volume and Candle Range Spike Detection ===
// Calculate average volume
avgVol = ta.sma(volume, lengthBig)
// Check if current volume is significantly higher than average
volSpike = volume > avgVol * volMultiplier
// Calculate current candle range (high - low)
candleRange = high - low
// Calculate average candle range
avgRange = ta.sma(candleRange, lengthBig)
// Check if current candle range is significantly larger than average
rangeSpike = candleRange > avgRange * rangeMultiplier
// === Big Money Entry and Exit Detection ===
// Entry: Volume spike + Range spike + Close > Open
bigMoneyIn = volSpike and rangeSpike and close > open
// Exit: Volume spike + Range spike + Close < Open
bigMoneyOut = volSpike and rangeSpike and close < open
// === Signal Label ===
if bigMoneyIn
label.new(bar_index, low, text="IN 💰", style=label.style_label_up, color=#701bc0bd, size = size.small, textcolor=color.white)
if bigMoneyOut
label.new(bar_index, high, "OUT 💰", style=label.style_label_down, color=color.rgb(250, 131, 20), size = size.small, textcolor=color.white)
// Momentum Squeeze Candle by [Darwinian] //
// Link : https://www.tradingview.com/script/6LLROyth-Momentum-Squeeze-Candle-Darwinian/ //
// --- Core Squeeze Settings ---
sqzGroup = 'Squeeze Settings'
squeezeMethod = input.string('BB + KC (Classic)', 'Squeeze Detection Method', options = ['BB + KC (Classic)', 'ATR Ratio', 'Choppiness Index', 'BB Width', 'Volume Contraction', 'Hybrid Multi-Method'], group = sqzGroup, tooltip = 'Choose squeeze detection algorithm', display = display.none)
lengthVar = input.int(20, 'BB/KC/ATR Length', minval = 1, group = sqzGroup, display = display.none)
multBB = input.float(2.0, 'BB Std Dev', minval = 0.5, step = 0.1, group = sqzGroup, display = display.none)
multKC = input.float(1.5, 'KC ATR Multiplier', minval = 0.5, step = 0.1, group = sqzGroup, display = display.none)
squeezeSensitivity = input.float(1.0, 'Squeeze Sensitivity (Higher = Stricter)', minval = 0.5, maxval = 2.0, step = 0.1, group = sqzGroup, tooltip = '1.0 = Standard, >1.0 = Fewer squeezes (stricter), <1.0 = More squeezes', display = display.none)
// Method-specific settings
atrRatioThreshold = input.float(0.7, 'ATR Ratio Threshold', minval = 0.3, maxval = 1.5, step = 0.05, group = sqzGroup, tooltip = 'For ATR Ratio method: lower = stricter', display = display.none)
choppyThreshold = input.float(61.8, 'Choppiness Threshold', minval = 38.2, maxval = 80, step = 1, group = sqzGroup, tooltip = 'For Choppiness method: higher = more consolidation required', display = display.none)
bbWidthThreshold = input.float(10.0, 'BB Width % Threshold', minval = 1, maxval = 30, step = 1, group = sqzGroup, tooltip = 'For BB Width method: lower = stricter', display = display.none)
hybridMinScore = input.int(3, 'Hybrid Min Score (1-5)', minval = 1, maxval = 5, group = sqzGroup, tooltip = 'For Hybrid method: signals required from different methods', display = display.none)
// --- Visual Settings ---
visualGroup = 'Visual Settings'
showMomentum = input.bool(true, 'Show Momentum Triangles', group = visualGroup, display = display.none)
colorCandles = input.bool(true, 'Color Candles During Squeeze', group = visualGroup, display = display.none)
showBands = input.bool(false, 'Show BB and KC Bands', group = visualGroup, display = display.none)
// --- Color Settings ---
colorGroup = 'Color Settings'
colorMomUp = input.color(color.lime, 'Momentum Up Triangle', group = colorGroup, display = display.none)
colorMomDown = input.color(color.red, 'Momentum Down Triangle', group = colorGroup, display = display.none)
colorCandle = input.color(color.rgb(222, 243, 33), 'Squeeze Candle Color', group = colorGroup, display = display.none)
// ============================================================================
// CORE CALCULATIONS
// ============================================================================
// --- Bollinger Bands ---
basis = ta.sma(close, lengthVar)
dev = multBB * ta.stdev(close, lengthVar)
upperBB = basis + dev
lowerBB = basis - dev
// --- Keltner Channels ---
ema = ta.ema(close, lengthVar)
atrVar = ta.atr(lengthVar)
upperKC = ema + multKC * atrVar
lowerKC = ema - multKC * atrVar
// ============================================================================
// SQUEEZE DETECTION - MULTIPLE METHODS
// ============================================================================
// --- METHOD 1: BB + KC (Classic TTM) ---
buffer = atrVar * 0.1 * squeezeSensitivity
sqzOn_BBKC = lowerBB > lowerKC + buffer and upperBB < upperKC - buffer
sqzOff_BBKC = lowerBB < lowerKC - buffer and upperBB > upperKC + buffer
// --- METHOD 2: ATR Ratio ---
atrShort = ta.atr(10)
atrLong = ta.atr(50)
atrRatio = atrLong > 0 ? atrShort / atrLong : 1.0
sqzOn_ATR = atrRatio < atrRatioThreshold * squeezeSensitivity
sqzOff_ATR = atrRatio > 1.0
// --- METHOD 3: Choppiness Index ---
choppyLength = 14
atr_sum = math.sum(ta.atr(1), choppyLength)
range_hl = ta.highest(high, choppyLength) - ta.lowest(low, choppyLength)
choppiness = range_hl > 0 and atr_sum > 0 ? 100 * math.log10(atr_sum / range_hl) / math.log10(choppyLength) : 50
adjustedChoppyThreshold = choppyThreshold * squeezeSensitivity
sqzOn_Choppy = choppiness > adjustedChoppyThreshold
sqzOff_Choppy = choppiness < 38.2
// --- METHOD 4: BB Width ---
bbWidthPercent = basis > 0 ? (upperBB - lowerBB) / basis * 100 : 0
adjustedBBWidthThreshold = bbWidthThreshold / squeezeSensitivity
sqzOn_BBWidth = bbWidthPercent < adjustedBBWidthThreshold
sqzOff_BBWidth = bbWidthPercent > adjustedBBWidthThreshold * 1.5
// --- METHOD 5: Volume Contraction ---
avgVolume = ta.sma(volume, lengthVar)
recentVolume = ta.sma(volume, 5)
volRatio = avgVolume > 0 ? recentVolume / avgVolume : 1.0
volThreshold = 0.75 * squeezeSensitivity
sqzOn_Volume = volRatio < volThreshold
sqzOff_Volume = volume > avgVolume * 1.3
// --- METHOD 6: Hybrid Multi-Method ---
// Score from 0-5 based on how many methods agree
hybridScore = 0
hybridScore := hybridScore + (sqzOn_BBKC ? 1 : 0)
hybridScore := hybridScore + (sqzOn_ATR ? 1 : 0)
hybridScore := hybridScore + (sqzOn_Choppy ? 1 : 0)
hybridScore := hybridScore + (sqzOn_BBWidth ? 1 : 0)
hybridScore := hybridScore + (sqzOn_Volume ? 1 : 0)
sqzOn_Hybrid = hybridScore >= hybridMinScore
sqzOff_Hybrid = hybridScore <= 1 // Most methods show expansion
// --- FINAL SQUEEZE SELECTION BASED ON CHOSEN METHOD ---
sqzOn = squeezeMethod == 'BB + KC (Classic)' ? sqzOn_BBKC : squeezeMethod == 'ATR Ratio' ? sqzOn_ATR : squeezeMethod == 'Choppiness Index' ? sqzOn_Choppy : squeezeMethod == 'BB Width' ? sqzOn_BBWidth : squeezeMethod == 'Volume Contraction' ? sqzOn_Volume : squeezeMethod == 'Hybrid Multi-Method' ? sqzOn_Hybrid : sqzOn_BBKC
sqzOff = squeezeMethod == 'BB + KC (Classic)' ? sqzOff_BBKC : squeezeMethod == 'ATR Ratio' ? sqzOff_ATR : squeezeMethod == 'Choppiness Index' ? sqzOff_Choppy : squeezeMethod == 'BB Width' ? sqzOff_BBWidth : squeezeMethod == 'Volume Contraction' ? sqzOff_Volume : squeezeMethod == 'Hybrid Multi-Method' ? sqzOff_Hybrid : sqzOff_BBKC
// --- Momentum Calculation ---
highest_high = ta.highest(high, lengthVar)
lowest_low = ta.lowest(low, lengthVar)
avg_hl = (highest_high + lowest_low) / 2
momentum = ta.linreg(close - avg_hl, lengthVar, 0)
momentumSlope = ta.change(momentum, 3)
// ============================================================================
// VISUALIZATION
// ============================================================================
// --- Bollinger Bands and Keltner Channels ---
plot(showBands ? upperBB : na, 'Upper BB', color = color.blue, linewidth = 1)
plot(showBands ? lowerBB : na, 'Lower BB', color = color.blue, linewidth = 1)
plot(showBands ? upperKC : na, 'Upper KC', color = color.orange, linewidth = 1)
plot(showBands ? lowerKC : na, 'Lower KC', color = color.orange, linewidth = 1)
// --- Candle Coloring ---
candleColorVar = colorCandles and sqzOn ? colorCandle : na
barcolor(candleColorVar, title = 'Squeeze Candle Color')
// --- Momentum Histogram (Separate Panel Reference) ---
// Note: This is displayed on the main chart overlay, but you can see values
// We'll create labels to show momentum direction
// Show momentum direction with small triangles
// Priority-based momentum direction with Wyckoff accumulation/distribution
// --- PRIORITY 1: Wyckoff Accumulation/Distribution (ATR + Volume) ---
// ATR compression ratio
atrShortTerm = ta.sma(atr, 5)
atrLongTerm = ta.sma(atr, 20)
atrCompressionRatio = atrLongTerm > 0 ? atrShortTerm / atrLongTerm : 1.0
// Volume analysis
volMA = ta.sma(volume, 20)
volDrying = volume < volMA * 0.8 // Volume drying up (accumulation)
volSurging = volume > volMA * 1.2 // Volume surging (distribution)
// Price position confirmation
priceMA = ta.sma(close, 20)
priceAboveMA = close > priceMA
priceBelowMA = close < priceMA
// ACCUMULATION: Low ATR + Low Volume + Price holding = Smart money accumulating
atrCompressed = atrCompressionRatio < 0.85
accumulation = atrCompressed and volDrying and priceAboveMA
wyckoffMomUp = accumulation
// DISTRIBUTION: High ATR + High Volume + Price failing = Smart money distributing
atrExpanded = atrCompressionRatio > 1.15
distribution = atrExpanded and volSurging and priceBelowMA
wyckoffMomDown = distribution
// --- PRIORITY 2: RSI outside neutral zone (45-55) ---
rsi = ta.rsi(close, 14)
rsiUp = rsi > 55
rsiDown = rsi < 45
rsiNeutral = rsi >= 45 and rsi <= 55
// --- PRIORITY 3: Hybrid logic (slope + momentum) ---
recentSlope = ta.change(close, 3)
slopeBasedUp = recentSlope > 0 and momentum > -0.5
slopeBasedDown = recentSlope < 0 and momentum < 0.5
// --- FINAL DIRECTION WITH PRIORITY HIERARCHY ---
// Priority 1: Wyckoff signals (strongest)
// Priority 2: RSI signals (strong)
// Priority 3: Slope-based (fallback)
momentumUp = wyckoffMomUp or (not wyckoffMomDown and (rsiUp or (rsiNeutral and slopeBasedUp)))
momentumDown = wyckoffMomDown or (not wyckoffMomUp and (rsiDown or (rsiNeutral and slopeBasedDown)))
plotshape(showMomentum and momentumUp and sqzOn, 'Mom Up', shape.circle, location.bottom, color.new(colorMomUp, 50), size = size.tiny)
plotshape(showMomentum and momentumDown and sqzOn, 'Mom Down', shape.circle, location.bottom, color.new(colorMomDown, 50), size = size.tiny)
Script SMC versi lengkap tersedia di Ebook — mencakup Premium/Discount Zones, Big Money Detector, Momentum Squeeze, dan fitur lainnya yang tidak ter-excerpt di halaman ini.
Cara Membaca Sinyal
Konfirmasi sinyal dari kedua indikator sebelum entry. Semakin banyak konfirmasi, semakin kuat sinyalnya.