O que é a High Low Zone?
Imagine que você está olhando o preço de algo (como uma ação ou criptomoeda) num gráfico que mostra o que aconteceu a cada minuto. O indicador "High Low Zone" desenha umas "caixas ("boxes")" coloridas por cima desse gráfico para te dar uma ideia do que aconteceu em períodos de tempo mais longos, como o que aconteceu durante uma hora inteira ou até mesmo um dia inteiro, sem que você precise mudar de gráfico.
Como funciona?
Ele desenha basicamente dois tipos de "caixas" baseadas em dois tempos maiores que ele calcula automaticamente, dependendo do tempo gráfico que você está usando:
-
Caixa Principal (Zona 1): Mostra a "foto" de um tempo maior (geralmente Diário ou Horário).
- Tem uma caixa interna colorida: Se for verde, significa que no geral, nesse tempo maior, o preço subiu. Se for vermelha, o preço caiu. Se for cinza, ficou mais ou menos na mesma.
- Tem uma caixa externa cinza (pavio): Essa caixa maior mostra o preço mais alto e o mais baixo que foram atingidos durante todo esse tempo maior.
-
Caixa Laranja (Zona 2): Mostra a "foto" de um tempo ainda maior (geralmente Semanal).
- É uma caixa cinza com borda laranja.
- Ela só mostra o preço máximo e mínimo que foram alcançados nesse período super longo (ex: semanal). Não diz se subiu ou desceu, apenas o alcance total do preço.
Pra que serve na prática?
É como ter uma "visão de helicóptero" enquanto você analisa os detalhes. As caixas (ou boxes) te ajudam a ver:
- Qual a tendência geral? (O preço está mais subindo ou caindo nos tempos maiores? - Caixa colorida da Zona 1)
- Onde o preço "bateu" e voltou? (Quais foram os limites máximos e mínimos nesses tempos maiores? - Caixas externas cinzas e laranja). Isso ajuda a identificar zonas de extremos importantes no gráfico.
Isso te dá um contexto melhor para tomar suas decisões, vendo não só o que está acontecendo agora, mas também o cenário mais amplo.
Com a High Low Zone, você consegue identificar rapidamente:
- O Movimento do Box Anterior (Como o preço se comportou no período maior que acabou de fechar)
- O Movimento do Box Atual (Como o preço está se comportando no período maior atual)
- As Ondas de Extremo (Os limites máximos e mínimos alcançados nesses períodos maiores)
- Suportes e Resistências importantes (Níveis chave baseados no método VF)
Código para TradingView (PineScript v6)
Abaixo está o código que você pode copiar e colar no Editor Pine do TradingView para usar este indicador:
//@version=6
indicator("HighLowZone Boxes - Aligned v9.G (Time - Extended RT - Candle Body)", overlay=true,
max_boxes_count = 500)
// --- Constants ---
color BORDER_COLOR_ZONE1 = color.new(color.gray, 0)
color BORDER_COLOR_ZONE2 = color.new(color.orange, 0)
int BORDER_WIDTH = 1
color BULL_COLOR_PERIOD = color.new(color.green, 85) // Color for UP HTF Period (Close > Open)
color BEAR_COLOR_PERIOD = color.new(color.red, 85) // Color for DOWN HTF Period (Close < Open)
color NEUTRAL_COLOR_PERIOD = color.new(color.gray, 85) // Color for NEUTRAL HTF Period (Close == Open)
// --- Cores adicionais (Enhancement) ---
color WICK_COLOR = color.new(color.gray, 85) // Cor do pavio (cinza translúcido)
// --- Functions ---
// Function to determine the higher timeframe based on the level (1 or 2)
getHigherTimeframe(int level) =>
string tf = timeframe.period
string result = na // Default to 'na'
// Define mappings for different base timeframes
// Seconds -> Minutes/Hours
if timeframe.isseconds
result := level == 1 ? '1' : '5' // Level 1: 1min, Level 2: 5min
// Minutes -> Hours/Daily/Weekly/Monthly
else if timeframe.isminutes
int m = timeframe.multiplier
if m < 15 // For timeframes like 1, 3, 5, 10 min
result := level == 1 ? '60' : '1W' // Level 1: 1h, Level 2: 1W
else if m < 60 // For timeframes like 15, 30, 45 min
result := level == 1 ? '1D' : '1W'
else if m == 60
result := level == 1 ? '1D' : '1W' // Level 1: 1D, Level 2: 1W
else if m <= 240 // Includes 120 (2h), 180 (3h), 240 (4h)
result := level == 1 ? '1D' : '1M' // Level 1: 1D, Level 2: 1M
else // Higher minute timeframes (e.g., 360 min)
result := level == 1 ? '1W' : '1M'
// Daily -> Weekly/Monthly
else if timeframe.isdaily
result := level == 1 ? '1W' : '1M' // Level 1: 1W, Level 2: 1M
// Weekly -> Monthly/Quarterly
else if timeframe.isweekly
result := level == 1 ? '1M' : '3M' // Level 1: 1M, Level 2: 3M
// Monthly -> Quarterly/Yearly
else if timeframe.ismonthly
result := level == 1 ? '3M' : '12M' // Level 1: 3M, Level 2: 1Y
// Default if none of the above match (e.g., Yearly)
else
result := level == 1 ? '1D' : '1W' // Fallback defaults
result // Return the calculated timeframe string
// --- Main Logic ---
// 1) Determine higher timeframes
string htf1 = getHigherTimeframe(1)
string htf2 = getHigherTimeframe(2)
// 2) HTF bar change flags including Sunday session start for Forex
// Zone 1 Change Flag
bool newDailyTF1 = timeframe.change(htf1)
bool sundaySession1 = dayofweek(time, syminfo.timezone) == dayofweek.sunday and dayofweek(time[1], syminfo.timezone) != dayofweek.sunday
bool htf1Changed = newDailyTF1 or (htf1 == '1D' and sundaySession1) // Apply Sunday logic only if HTF is Daily
// Zone 2 Change Flag
bool newDailyTF2 = timeframe.change(htf2)
bool sundaySession2 = dayofweek(time, syminfo.timezone) == dayofweek.sunday and dayofweek(time[1], syminfo.timezone) != dayofweek.sunday
bool htf2Changed = newDailyTF2 or (htf2 == '1D' and sundaySession2) // Apply Sunday logic only if HTF is Daily
// 3) State variables for Zone 1
var int startIdx1 = na // Start bar index of the current HTF1 period (for completed box)
var float htfHigh1 = na // Accumulated high within the current HTF1 period
var float htfLow1 = na // Accumulated low within the current HTF1 period
var float periodOpen1 = na // 'open' price of the *first* bar of the current HTF1 period
var float lastClose1 = na // 'close' price of the *last processed* bar within the current HTF1 period
var box rtWick1 = na // Real-time WICK box for Zone 1
var box rtBody1 = na // Real-time BODY box for Zone 1
var int timeStart1 = na // Start time of the previous HTF1 period (for completed box)
// 4) State variables for Zone 2
var int startIdx2 = na // Start bar index of the current HTF2 period (for completed box)
var float htfHigh2 = na // Accumulated high within the current HTF2 period
var float htfLow2 = na // Accumulated low within the current HTF2 period
var box rtWick2 = na // Real-time WICK box for Zone 2 (gray background, orange border)
var box rtBody2 = na // Real-time BODY box for Zone 2 (invisible, preserves structure)
var int timeStart2 = na // Start time of the previous HTF2 period (for completed box)
// --- Zone 1 Logic (Candle Body Enhancement) ---
if htf1Changed // First bar of a new HTF1 period
// --- Close the previous completed boxes (if they exist) ---
if not na(startIdx1)
// Determine the color based on the *previous* period's open and *its last* close
color completedBoxColor1 = na
if lastClose1 > periodOpen1
completedBoxColor1 := BULL_COLOR_PERIOD
else if lastClose1 < periodOpen1
completedBoxColor1 := BEAR_COLOR_PERIOD
else
completedBoxColor1 := NEUTRAL_COLOR_PERIOD
// 1. Draw the completed WICK box (INDEX BASED)
box.new(
left = startIdx1, // Index where the completed period started
right = bar_index - 1, // Index where the completed period ended
top = htfHigh1,
bottom = htfLow1,
border_color = BORDER_COLOR_ZONE1,
border_width = BORDER_WIDTH,
bgcolor = WICK_COLOR, // Gray background for wick
xloc = xloc.bar_index
)
// Calculate final body levels
float bodyHi = math.max(periodOpen1, lastClose1)
float bodyLo = math.min(periodOpen1, lastClose1)
// 2. Draw the completed BODY box (INDEX BASED)
box.new(
left = startIdx1,
right = bar_index - 1,
top = bodyHi,
bottom = bodyLo,
border_color = na, // No border for body (optional)
bgcolor = completedBoxColor1, // Bull/Bear/Neutral color
xloc = xloc.bar_index
)
// --- Reset state for the NEW HTF1 period ---
timeStart1 := time(htf1, 0) // Store start time for potential future completed box
startIdx1 := bar_index // Store the starting index of the new period
htfHigh1 := high // Initialize high with the current bar's high
htfLow1 := low // Initialize low with the current bar's low
periodOpen1 := open // Store the open price of this period's first bar
lastClose1 := close // Initialize lastClose with the current bar's close
// Delete the previous real-time boxes
if not na(rtWick1)
box.delete(rtWick1)
rtWick1 := na // Explicitly set to na after deletion
if not na(rtBody1)
box.delete(rtBody1)
rtBody1 := na // Explicitly set to na after deletion
// --- Create the new real-time boxes (TIME BASED) ---
// 1. Create RT WICK box
rtWick1 := box.new(
left = time(htf1, 0), // Use period start time
right = time_close(htf1, 0), // Use period end time
top = htfHigh1, // Initial high
bottom = htfLow1, // Initial low
border_color = BORDER_COLOR_ZONE1,
border_width = BORDER_WIDTH,
bgcolor = WICK_COLOR, // Gray background
xloc = xloc.bar_time // Use time coordinates
)
// Calculate initial body levels
float bodyTop1 = math.max(periodOpen1, lastClose1) // On first bar, periodOpen=open, lastClose=close
float bodyBot1 = math.min(periodOpen1, lastClose1)
// <<< FIX: Determine initial body color using if/else if/else >>>
color initialRtColor1 = na
if lastClose1 > periodOpen1
initialRtColor1 := BULL_COLOR_PERIOD
else if lastClose1 < periodOpen1
initialRtColor1 := BEAR_COLOR_PERIOD
else
initialRtColor1 := NEUTRAL_COLOR_PERIOD
// 2. Create RT BODY box
rtBody1 := box.new(
left = time(htf1, 0),
right = time_close(htf1, 0),
top = bodyTop1,
bottom = bodyBot1,
border_color = na, // No border for body
bgcolor = initialRtColor1, // Initial Bull/Bear/Neutral color
xloc = xloc.bar_time
)
else // Inside an existing HTF1 period (not the first bar)
// Check if state variables were initialized (handles script reload/compilation mid-period)
if na(htfHigh1) or na(htfLow1) or na(periodOpen1)
// Re-initialize state if needed (less ideal, but prevents errors)
htfHigh1 := high
htfLow1 := low
periodOpen1 := open // May not be the *true* period open if reloaded mid-period
lastClose1 := close
// Also need to potentially recreate RT boxes if 'na' here, complex recovery
else
// Accumulate high and low
htfHigh1 := math.max(htfHigh1, high)
htfLow1 := math.min(htfLow1, low)
lastClose1 := close // Update the last seen close price
// Update the real-time boxes (if they exist)
if not na(rtWick1) and not na(rtBody1) // Check both exist
// 1. Update RT WICK box
box.set_top (rtWick1, htfHigh1)
box.set_bottom(rtWick1, htfLow1)
// Wick color and border remain the same
// 2. Update RT BODY box
// Calculate current body levels
float bodyHi = math.max(periodOpen1, lastClose1)
float bodyLo = math.min(periodOpen1, lastClose1)
// Determine current body color
color rtColor1 = na
if lastClose1 > periodOpen1
rtColor1 := BULL_COLOR_PERIOD
else if lastClose1 < periodOpen1
rtColor1 := BEAR_COLOR_PERIOD
else
rtColor1 := NEUTRAL_COLOR_PERIOD
box.set_top (rtBody1, bodyHi)
box.set_bottom(rtBody1, bodyLo)
box.set_bgcolor(rtBody1, rtColor1) // Update color based on last close vs period open
// --- Zone 2 Logic (Applying structure, maintaining original style) ---
if htf2Changed // First bar of a new HTF2 period
// --- Close the previous completed box (if it exists) ---
if not na(startIdx2)
// Zone 2 completed boxes: Draw only the WICK box (gray background, orange border)
box.new(
left = startIdx2, // Index where the completed period started
right = bar_index - 1, // Index where the completed period ended
top = htfHigh2,
bottom = htfLow2,
border_color = BORDER_COLOR_ZONE2, // Orange border
border_width = BORDER_WIDTH,
bgcolor = WICK_COLOR, // Gray background for wick area
xloc = xloc.bar_index
)
// No separate completed body box for Zone 2 to keep the outline style.
// --- Reset state for the NEW HTF2 period ---
timeStart2 := time(htf2, 0) // Store start time
startIdx2 := bar_index
htfHigh2 := high
htfLow2 := low
// Delete the previous real-time boxes
if not na(rtWick2)
box.delete(rtWick2)
rtWick2 := na
if not na(rtBody2) // Delete the invisible body box too
box.delete(rtBody2)
rtBody2 := na
// --- Create the new real-time boxes (TIME BASED) ---
// 1. Create RT WICK box for Zone 2
rtWick2 := box.new(
left = time(htf2, 0), // Use period start time
right = time_close(htf2, 0), // Use period end time
top = htfHigh2,
bottom = htfLow2,
border_color = BORDER_COLOR_ZONE2, // Orange border
border_width = BORDER_WIDTH,
bgcolor = WICK_COLOR, // Gray background
xloc = xloc.bar_time // Use time coordinates
)
// 2. Create RT BODY box for Zone 2 (invisible - preserves structure if style changes later)
float bodyTop2 = math.max(open, close)
float bodyBot2 = math.min(open, close)
rtBody2 := box.new(
left = time(htf2, 0),
right = time_close(htf2, 0),
top = bodyTop2, // Initial placement
bottom = bodyBot2, // Initial placement
border_color = na,
bgcolor = na, // No background color for Zone 2 body
xloc = xloc.bar_time
)
else // Inside an existing HTF2 period
// Check if state variables were initialized
if na(htfHigh2) or na(htfLow2)
htfHigh2 := high
htfLow2 := low
else
// Accumulate high and low
htfHigh2 := math.max(htfHigh2, high)
htfLow2 := math.min(htfLow2, low)
// Update the real-time boxes (if they exist)
if not na(rtWick2) // Only need to check/update the visible Wick box
// 1. Update RT WICK box
box.set_top (rtWick2, htfHigh2)
box.set_bottom(rtWick2, htfLow2)
// No update needed for the invisible rtBody2 unless its position logic changes
// --- End of Script ---