OPEN-SOURCE SCRIPT
HTF Candle Countdown Timer

//version=5
indicator("HTF Candle Countdown Timer", overlay=true)
// ============================================================================
// INPUTS - SETTINGS MENU
// ============================================================================
// --- Mode Selection ---
mode = input.string(title="Mode", defval="Auto", options=["Auto", "Custom"],
tooltip="Auto: Αυτόματη αντιστοίχιση timeframes\nCustom: Επιλέξτε το δικό σας timeframe")
// --- Custom Timeframe Selection ---
customTF = input.timeframe(title="Custom Timeframe", defval="15",
tooltip="Ενεργό μόνο σε Custom Mode")
// --- Table Position ---
tablePos = input.string(title="Table Position", defval="Bottom Right",
options=["Top Left", "Top Right", "Bottom Left", "Bottom Right"])
// --- Colors ---
textColor = input.color(title="Text Color", defval=color.white)
bgColor = input.color(title="Background Color", defval=color.black)
transparentBg = input.bool(title="Transparent Background", defval=false,
tooltip="Ενεργοποίηση διάφανου φόντου")
// --- Text Size ---
textSize = input.string(title="Text Size", defval="Normal",
options=["Auto", "Tiny", "Small", "Normal", "Large", "Huge"])
// ============================================================================
// FUNCTIONS
// ============================================================================
// Μετατροπή string position σε table position constant
getTablePosition(pos) =>
switch pos
"Top Left" => position.top_left
"Top Right" => position.top_right
"Bottom Left" => position.bottom_left
"Bottom Right" => position.bottom_right
=> position.bottom_right
// Μετατροπή string size σε size constant
getTextSize(size) =>
switch size
"Auto" => size.auto
"Tiny" => size.tiny
"Small" => size.small
"Normal" => size.normal
"Large" => size.large
"Huge" => size.huge
=> size.normal
// Αυτόματη αντιστοίχιση timeframes
getAutoTimeframe() =>
currentTF = timeframe.period
string targetTF = ""
if currentTF == "1"
targetTF := "15"
else if currentTF == "3"
targetTF := "30"
else if currentTF == "5"
targetTF := "60"
else if currentTF == "15"
targetTF := "240"
else if currentTF == "60"
targetTF := "D"
else if currentTF == "240"
targetTF := "W"
else
// Default fallback για μη-mapped timeframes
targetTF := "60"
targetTF
// Μετατροπή timeframe string σε λεπτά για σύγκριση
timeframeToMinutes(tf) =>
float minutes = 0.0
if str.contains(tf, "D")
multiplier = str.tonumber(str.replace(tf, "D", ""))
minutes := na(multiplier) ? 1440.0 : multiplier * 1440.0
else if str.contains(tf, "W")
multiplier = str.tonumber(str.replace(tf, "W", ""))
minutes := na(multiplier) ? 10080.0 : multiplier * 10080.0
else if str.contains(tf, "M")
multiplier = str.tonumber(str.replace(tf, "M", ""))
minutes := na(multiplier) ? 43200.0 : multiplier * 43200.0
else
minutes := str.tonumber(tf)
minutes
// Format countdown σε ώρες:λεπτά:δευτερόλεπτα ή λεπτά:δευτερόλεπτα
formatCountdown(milliseconds) =>
totalSeconds = math.floor(milliseconds / 1000)
hours = math.floor(totalSeconds / 3600)
minutes = math.floor((totalSeconds % 3600) / 60)
seconds = totalSeconds % 60
string result = ""
if hours > 0
result := str.format("{0,number,00}:{1,number,00}:{2,number,00}", hours, minutes, seconds)
else
result := str.format("{0,number,00}:{1,number,00}", minutes, seconds)
result
// Μετατροπή timeframe σε readable format
formatTimeframe(tf) =>
string formatted = ""
if str.contains(tf, "D")
formatted := tf + "aily"
else if str.contains(tf, "W")
formatted := tf + "eekly"
else if str.contains(tf, "M")
formatted := tf + "onthly"
else if tf == "60"
formatted := "1H"
else if tf == "240"
formatted := "4H"
else
formatted := tf + "min"
formatted
// ============================================================================
// MAIN LOGIC
// ============================================================================
// Επιλογή target timeframe βάσει mode
targetTimeframe = mode == "Auto" ? getAutoTimeframe() : customTF
// Validation: Έλεγχος αν το target timeframe είναι μεγαλύτερο από το τρέχον
currentTFMinutes = timeframeToMinutes(timeframe.period)
targetTFMinutes = timeframeToMinutes(targetTimeframe)
var string warningMessage = ""
if targetTFMinutes <= currentTFMinutes
warningMessage := "⚠ HTF < Current TF"
else
warningMessage := ""
// Υπολογισμός του χρόνου κλεισίματος του HTF candle
htfTime = request.security(syminfo.tickerid, targetTimeframe, time)
htfTimeClose = request.security(syminfo.tickerid, targetTimeframe, time_close)
// Υπολογισμός υπολειπόμενου χρόνου σε milliseconds
remainingTime = htfTimeClose - timenow
// Format countdown
countdown = warningMessage != "" ? warningMessage : formatCountdown(remainingTime)
// Format timeframe για εμφάνιση
displayTF = formatTimeframe(targetTimeframe)
// ============================================================================
// TABLE DISPLAY
// ============================================================================
// Δημιουργία table
var table countdownTable = table.new(
position=getTablePosition(tablePos),
columns=2,
rows=2,
bgcolor=transparentBg ? color.new(bgColor, 100) : bgColor,
frame_width=1,
frame_color=color.gray,
border_width=1)
// Update table content
if barstate.islast
// Header
table.cell(countdownTable, 0, 0, "Timeframe:",
text_color=textColor,
bgcolor=transparentBg ? color.new(bgColor, 100) : bgColor,
text_size=getTextSize(textSize))
table.cell(countdownTable, 1, 0, displayTF,
text_color=textColor,
bgcolor=transparentBg ? color.new(bgColor, 100) : bgColor,
text_size=getTextSize(textSize))
// Countdown
table.cell(countdownTable, 0, 1, "Countdown:",
text_color=textColor,
bgcolor=transparentBg ? color.new(bgColor, 100) : bgColor,
text_size=getTextSize(textSize))
table.cell(countdownTable, 1, 1, countdown,
text_color=warningMessage != "" ? color.orange : textColor,
bgcolor=transparentBg ? color.new(bgColor, 100) : bgColor,
text_size=getTextSize(textSize))
// ============================================================================
// END OF SCRIPT
// ============================================================================
indicator("HTF Candle Countdown Timer", overlay=true)
// ============================================================================
// INPUTS - SETTINGS MENU
// ============================================================================
// --- Mode Selection ---
mode = input.string(title="Mode", defval="Auto", options=["Auto", "Custom"],
tooltip="Auto: Αυτόματη αντιστοίχιση timeframes\nCustom: Επιλέξτε το δικό σας timeframe")
// --- Custom Timeframe Selection ---
customTF = input.timeframe(title="Custom Timeframe", defval="15",
tooltip="Ενεργό μόνο σε Custom Mode")
// --- Table Position ---
tablePos = input.string(title="Table Position", defval="Bottom Right",
options=["Top Left", "Top Right", "Bottom Left", "Bottom Right"])
// --- Colors ---
textColor = input.color(title="Text Color", defval=color.white)
bgColor = input.color(title="Background Color", defval=color.black)
transparentBg = input.bool(title="Transparent Background", defval=false,
tooltip="Ενεργοποίηση διάφανου φόντου")
// --- Text Size ---
textSize = input.string(title="Text Size", defval="Normal",
options=["Auto", "Tiny", "Small", "Normal", "Large", "Huge"])
// ============================================================================
// FUNCTIONS
// ============================================================================
// Μετατροπή string position σε table position constant
getTablePosition(pos) =>
switch pos
"Top Left" => position.top_left
"Top Right" => position.top_right
"Bottom Left" => position.bottom_left
"Bottom Right" => position.bottom_right
=> position.bottom_right
// Μετατροπή string size σε size constant
getTextSize(size) =>
switch size
"Auto" => size.auto
"Tiny" => size.tiny
"Small" => size.small
"Normal" => size.normal
"Large" => size.large
"Huge" => size.huge
=> size.normal
// Αυτόματη αντιστοίχιση timeframes
getAutoTimeframe() =>
currentTF = timeframe.period
string targetTF = ""
if currentTF == "1"
targetTF := "15"
else if currentTF == "3"
targetTF := "30"
else if currentTF == "5"
targetTF := "60"
else if currentTF == "15"
targetTF := "240"
else if currentTF == "60"
targetTF := "D"
else if currentTF == "240"
targetTF := "W"
else
// Default fallback για μη-mapped timeframes
targetTF := "60"
targetTF
// Μετατροπή timeframe string σε λεπτά για σύγκριση
timeframeToMinutes(tf) =>
float minutes = 0.0
if str.contains(tf, "D")
multiplier = str.tonumber(str.replace(tf, "D", ""))
minutes := na(multiplier) ? 1440.0 : multiplier * 1440.0
else if str.contains(tf, "W")
multiplier = str.tonumber(str.replace(tf, "W", ""))
minutes := na(multiplier) ? 10080.0 : multiplier * 10080.0
else if str.contains(tf, "M")
multiplier = str.tonumber(str.replace(tf, "M", ""))
minutes := na(multiplier) ? 43200.0 : multiplier * 43200.0
else
minutes := str.tonumber(tf)
minutes
// Format countdown σε ώρες:λεπτά:δευτερόλεπτα ή λεπτά:δευτερόλεπτα
formatCountdown(milliseconds) =>
totalSeconds = math.floor(milliseconds / 1000)
hours = math.floor(totalSeconds / 3600)
minutes = math.floor((totalSeconds % 3600) / 60)
seconds = totalSeconds % 60
string result = ""
if hours > 0
result := str.format("{0,number,00}:{1,number,00}:{2,number,00}", hours, minutes, seconds)
else
result := str.format("{0,number,00}:{1,number,00}", minutes, seconds)
result
// Μετατροπή timeframe σε readable format
formatTimeframe(tf) =>
string formatted = ""
if str.contains(tf, "D")
formatted := tf + "aily"
else if str.contains(tf, "W")
formatted := tf + "eekly"
else if str.contains(tf, "M")
formatted := tf + "onthly"
else if tf == "60"
formatted := "1H"
else if tf == "240"
formatted := "4H"
else
formatted := tf + "min"
formatted
// ============================================================================
// MAIN LOGIC
// ============================================================================
// Επιλογή target timeframe βάσει mode
targetTimeframe = mode == "Auto" ? getAutoTimeframe() : customTF
// Validation: Έλεγχος αν το target timeframe είναι μεγαλύτερο από το τρέχον
currentTFMinutes = timeframeToMinutes(timeframe.period)
targetTFMinutes = timeframeToMinutes(targetTimeframe)
var string warningMessage = ""
if targetTFMinutes <= currentTFMinutes
warningMessage := "⚠ HTF < Current TF"
else
warningMessage := ""
// Υπολογισμός του χρόνου κλεισίματος του HTF candle
htfTime = request.security(syminfo.tickerid, targetTimeframe, time)
htfTimeClose = request.security(syminfo.tickerid, targetTimeframe, time_close)
// Υπολογισμός υπολειπόμενου χρόνου σε milliseconds
remainingTime = htfTimeClose - timenow
// Format countdown
countdown = warningMessage != "" ? warningMessage : formatCountdown(remainingTime)
// Format timeframe για εμφάνιση
displayTF = formatTimeframe(targetTimeframe)
// ============================================================================
// TABLE DISPLAY
// ============================================================================
// Δημιουργία table
var table countdownTable = table.new(
position=getTablePosition(tablePos),
columns=2,
rows=2,
bgcolor=transparentBg ? color.new(bgColor, 100) : bgColor,
frame_width=1,
frame_color=color.gray,
border_width=1)
// Update table content
if barstate.islast
// Header
table.cell(countdownTable, 0, 0, "Timeframe:",
text_color=textColor,
bgcolor=transparentBg ? color.new(bgColor, 100) : bgColor,
text_size=getTextSize(textSize))
table.cell(countdownTable, 1, 0, displayTF,
text_color=textColor,
bgcolor=transparentBg ? color.new(bgColor, 100) : bgColor,
text_size=getTextSize(textSize))
// Countdown
table.cell(countdownTable, 0, 1, "Countdown:",
text_color=textColor,
bgcolor=transparentBg ? color.new(bgColor, 100) : bgColor,
text_size=getTextSize(textSize))
table.cell(countdownTable, 1, 1, countdown,
text_color=warningMessage != "" ? color.orange : textColor,
bgcolor=transparentBg ? color.new(bgColor, 100) : bgColor,
text_size=getTextSize(textSize))
// ============================================================================
// END OF SCRIPT
// ============================================================================
Скрипт с открытым кодом
В истинном духе TradingView автор этого скрипта опубликовал его с открытым исходным кодом, чтобы трейдеры могли понять, как он работает, и проверить на практике. Вы можете воспользоваться им бесплатно, но повторное использование этого кода в публикации регулируется Правилами поведения.
Отказ от ответственности
Все виды контента, которые вы можете увидеть на TradingView, не являются финансовыми, инвестиционными, торговыми или любыми другими рекомендациями. Мы не предоставляем советы по покупке и продаже активов. Подробнее — в Условиях использования TradingView.
Скрипт с открытым кодом
В истинном духе TradingView автор этого скрипта опубликовал его с открытым исходным кодом, чтобы трейдеры могли понять, как он работает, и проверить на практике. Вы можете воспользоваться им бесплатно, но повторное использование этого кода в публикации регулируется Правилами поведения.
Отказ от ответственности
Все виды контента, которые вы можете увидеть на TradingView, не являются финансовыми, инвестиционными, торговыми или любыми другими рекомендациями. Мы не предоставляем советы по покупке и продаже активов. Подробнее — в Условиях использования TradingView.