Pular para o conteúdo principal

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:

  1. 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.
  2. 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.

Resumindo

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 ---