時區和月周日K的開高低收,一分K的開盤價區間標示和六均線與扣抵
選項中有可以調整使用的商品時區
// © tseng27
//@version=6
indicator("台指開盤時區與關鍵價", overlay=true, max_lines_count=500, max_labels_count=500, max_boxes_count=500)
// =========================================================================
// 1. 設定區 (Inputs)
// =========================================================================
grp_bg = "背景設定 (交易時段)"
detect_mode = input.string("自訂時段 (期貨/CFD/美股)", "時段判定模式", options=["自動偵測 (依賴圖表ETH開關)", "自訂時段 (期貨/CFD/美股)"], group=grp_bg)
custom_rth = input.session("0845-1345", "自訂常規時段 (RTH)", group=grp_bg)
custom_tz = input.string("Asia/Taipei", "自訂時區", group=grp_bg)
c_rth = input.color(color.new(color.blue, 95), "常規交易時段背景 (RTH)", group=grp_bg)
c_eth = input.color(color.new(color.gray, 95), "電子交易時段背景 (ETH)", group=grp_bg)
grp_1m = "開盤 1 分K設定"
c_1m = input.color(color.new(color.white, 80), "1 分K 矩形顏色 (預設 20% 不透明)", group=grp_1m)
grp_ohlc = "支撐壓力線 - 一般設定"
show_date = input.bool(true, "顯示日期標籤", group=grp_ohlc)
grp_d = "日K 支撐壓力線設定"
show_d = input.bool(true, "開啟 日K 關鍵價", group=grp_d)
d_w = input.int(1, "日K 線條粗細", minval=1, maxval=10, group=grp_d)
d_s = input.string("實線", "日K 線條樣式", options=["實線", "虛線", "點線"], group=grp_d)
d_c_o = input.color(color.new(#ff9800, 20), "日開盤價 (Open)", group=grp_d)
d_c_h = input.color(color.new(#4caf50, 20), "日最高價 (High)", group=grp_d)
d_c_l = input.color(color.new(#f44336, 20), "日最低價 (Low)", group=grp_d)
d_c_c = input.color(color.new(#2196f3, 20), "日收盤價 (Close)", group=grp_d)
grp_w = "周K 支撐壓力線設定"
show_w = input.bool(true, "開啟 周K 關鍵價", group=grp_w)
w_w = input.int(2, "周K 線條粗細", minval=1, maxval=10, group=grp_w)
w_s = input.string("實線", "周K 線條樣式", options=["實線", "虛線", "點線"], group=grp_w)
w_c_o = input.color(color.new(#ffeb3b, 20), "周開盤價 (Open)", group=grp_w)
w_c_h = input.color(color.new(#00bcd4, 20), "周最高價 (High)", group=grp_w)
w_c_l = input.color(color.new(#e91e63, 20), "周最低價 (Low)", group=grp_w)
w_c_c = input.color(color.new(#9c27b0, 20), "周收盤價 (Close)", group=grp_w)
grp_m = "月K 支撐壓力線設定"
show_m = input.bool(true, "開啟 月K 關鍵價", group=grp_m)
m_w = input.int(3, "月K 線條粗細", minval=1, maxval=10, group=grp_m)
m_s = input.string("實線", "月K 線條樣式", options=["實線", "虛線", "點線"], group=grp_m)
m_c_o = input.color(color.new(#ff5722, 20), "月開盤價 (Open)", group=grp_m)
m_c_h = input.color(color.new(#8bc34a, 20), "月最高價 (High)", group=grp_m)
m_c_l = input.color(color.new(#795548, 20), "月最低價 (Low)", group=grp_m)
m_c_c = input.color(color.new(#607d8b, 20), "月收盤價 (Close)", group=grp_m)
grp_sma = "移動平均線 (SMA) 與扣抵標籤"
kd_trans = input.int(80, "扣抵標籤底色透明度 (%)", minval=0, maxval=100, group=grp_sma)
show_sma5 = input.bool(true, "SMA 5", inline="sma5", group=grp_sma)
wid_sma5 = input.int(1, "粗細", minval=1, maxval=10, inline="sma5", group=grp_sma)
col_sma5 = input.color(color.new(#ff9800, 0), "顏色", inline="sma5", group=grp_sma)
show_kd5 = input.bool(true, "扣抵", inline="sma5", group=grp_sma)
show_sma10 = input.bool(true, "SMA 10", inline="sma10", group=grp_sma)
wid_sma10 = input.int(1, "粗細", minval=1, maxval=10, inline="sma10", group=grp_sma)
col_sma10 = input.color(color.new(#2196f3, 0), "顏色", inline="sma10", group=grp_sma)
show_kd10 = input.bool(true, "扣抵", inline="sma10", group=grp_sma)
show_sma20 = input.bool(true, "SMA 20", inline="sma20", group=grp_sma)
wid_sma20 = input.int(1, "粗細", minval=1, maxval=10, inline="sma20", group=grp_sma)
col_sma20 = input.color(color.new(#4caf50, 0), "顏色", inline="sma20", group=grp_sma)
show_kd20 = input.bool(true, "扣抵", inline="sma20", group=grp_sma)
show_sma60 = input.bool(true, "SMA 60", inline="sma60", group=grp_sma)
wid_sma60 = input.int(1, "粗細", minval=1, maxval=10, inline="sma60", group=grp_sma)
col_sma60 = input.color(color.new(#9c27b0, 0), "顏色", inline="sma60", group=grp_sma)
show_kd60 = input.bool(true, "扣抵", inline="sma60", group=grp_sma)
show_sma120 = input.bool(true, "SMA 120", inline="sma120", group=grp_sma)
wid_sma120 = input.int(1, "粗細", minval=1, maxval=10, inline="sma120", group=grp_sma)
col_sma120 = input.color(color.new(#e91e63, 0), "顏色", inline="sma120", group=grp_sma)
show_kd120 = input.bool(true, "扣抵", inline="sma120", group=grp_sma)
show_sma240 = input.bool(true, "SMA 240", inline="sma240", group=grp_sma)
wid_sma240 = input.int(1, "粗細", minval=1, maxval=10, inline="sma240", group=grp_sma)
col_sma240 = input.color(color.new(#ffeb3b, 0), "顏色", inline="sma240", group=grp_sma)
show_kd240 = input.bool(true, "扣抵", inline="sma240", group=grp_sma)
// =========================================================================
// 2. 交易時段背景色彩 (自動偵測商品)
// =========================================================================
// 使用 TV 內建 session 判斷,自動相容任何類型商品的 RTH 與 ETH
is_auto = detect_mode == "自動偵測 (依賴圖表ETH開關)"
is_rth = is_auto ? session.ismarket : not na(time(timeframe.period, custom_rth, custom_tz))
is_eth = is_auto ? (session.ispremarket or session.ispostmarket) : not is_rth
bg_color = is_rth ? c_rth : is_eth ? c_eth : na
bgcolor(bg_color, title="交易時段背景")
// =========================================================================
// 3. 每日開盤 1 分鐘 K 線的開收盤矩形
// =========================================================================
// 建立一個函式來抓取 1 分鐘級別的每日第一根 K 線 (僅限常規時段)
f_get_first_1m() =>
var float o = na
var float c = na
var int t = na
// 在 1 分鐘級別精準判斷常規時段的「第一根」
_is_auto = detect_mode == "自動偵測 (依賴圖表ETH開關)"
_is_rth = _is_auto ? session.ismarket : not na(time("1", custom_rth, custom_tz))
_is_rth_start = _is_rth and not _is_rth[1]
if _is_rth_start
o := open
c := close
t := time
[o, c, t]
// 向 1 分鐘級別請求資料
[f1_o, f1_c, f1_t] = request.security(syminfo.tickerid, "1", f_get_first_1m())
var box f1_box = na
// 當偵測到新的 1 分鐘開盤時間時,建立新的矩形
if ta.change(f1_t) != 0
top_price = math.max(f1_o, f1_c)
bot_price = math.min(f1_o, f1_c)
f1_box := box.new(left=f1_t, top=top_price, right=time, bottom=bot_price,
border_color=c_1m, bgcolor=c_1m, extend=extend.right, xloc=xloc.bar_time)
// =========================================================================
// 4. 自訂時段 (RTH) 內的 D/W/M OHLC 精準追蹤與畫線
// =========================================================================
// 宣告變數來記錄 "目前" 時段內的極值
var int last_d = na, var int last_w = na, var int last_m = na
var float cur_d_o = na, var float cur_d_h = na, var float cur_d_l = na, var float cur_d_c = na, var int cur_d_t = na
var float cur_w_o = na, var float cur_w_h = na, var float cur_w_l = na, var float cur_w_c = na, var int cur_w_t = na
var float cur_m_o = na, var float cur_m_h = na, var float cur_m_l = na, var float cur_m_c = na, var int cur_m_t = na
// 宣告變數來儲存 "已完成" 的上一週期極值
var float prev_d_o = na, var float prev_d_h = na, var float prev_d_l = na, var float prev_d_c = na, var int prev_d_t = na
var float prev_w_o = na, var float prev_w_h = na, var float prev_w_l = na, var float prev_w_c = na, var int prev_w_t = na
var float prev_m_o = na, var float prev_m_h = na, var float prev_m_l = na, var float prev_m_c = na, var int prev_m_t = na
bool is_new_d = false
bool is_new_w = false
bool is_new_m = false
if is_rth
// 使用指定的時區來判斷當前的日期、週數、月份
int curr_d = dayofmonth(time, custom_tz)
int curr_w = weekofyear(time, custom_tz)
int curr_m = month(time, custom_tz)
// 判斷是否進入了新的週期 (僅在 RTH 內判斷)
is_new_d := na(last_d) or last_d != curr_d
is_new_w := na(last_w) or last_w != curr_w
is_new_m := na(last_m) or last_m != curr_m
// --- 日級別更新 ---
if is_new_d
prev_d_o := cur_d_o, prev_d_h := cur_d_h, prev_d_l := cur_d_l, prev_d_c := cur_d_c, prev_d_t := cur_d_t
cur_d_o := open, cur_d_h := high, cur_d_l := low, cur_d_c := close, cur_d_t := time
else
cur_d_h := math.max(cur_d_h, high), cur_d_l := math.min(cur_d_l, low), cur_d_c := close
// --- 周級別更新 ---
if is_new_w
prev_w_o := cur_w_o, prev_w_h := cur_w_h, prev_w_l := cur_w_l, prev_w_c := cur_w_c, prev_w_t := cur_w_t
cur_w_o := open, cur_w_h := high, cur_w_l := low, cur_w_c := close, cur_w_t := time
else
cur_w_h := math.max(cur_w_h, high), cur_w_l := math.min(cur_w_l, low), cur_w_c := close
// --- 月級別更新 ---
if is_new_m
prev_m_o := cur_m_o, prev_m_h := cur_m_h, prev_m_l := cur_m_l, prev_m_c := cur_m_c, prev_m_t := cur_m_t
cur_m_o := open, cur_m_h := high, cur_m_l := low, cur_m_c := close, cur_m_t := time
else
cur_m_h := math.max(cur_m_h, high), cur_m_l := math.min(cur_m_l, low), cur_m_c := close
// 推進狀態
last_d := curr_d
last_w := curr_w
last_m := curr_m
// 宣告一個陣列來儲存所有生成的標籤,以便後續將它們對齊畫面左側
var all_labels = array.new_label()
// 輔助函式:將字串轉換為 Pine Script 的線條樣式
f_get_style(style_str) =>
style_str == "虛線" ? line.style_dashed : style_str == "點線" ? line.style_dotted : line.style_solid
// 建立繪製歷史級別線條的函式 (當新級別產生時,畫出新的線條並向右無限延伸)
f_draw_levels(trigger, prev_t, o, h, l, c, prefix, w, s_str, show_lbl, col_o, col_h, col_l, col_c) =>
if trigger and not na(o)
line_style = f_get_style(s_str)
// 繪製向右無限延伸的線條 (從觸發當下的前一根K線開始延伸,以確保 X 軸差異)
line.new(time[1], o, time, o, xloc=xloc.bar_time, color=col_o, width=w, style=line_style, extend=extend.right)
line.new(time[1], h, time, h, xloc=xloc.bar_time, color=col_h, width=w, style=line_style, extend=extend.right)
line.new(time[1], l, time, l, xloc=xloc.bar_time, color=col_l, width=w, style=line_style, extend=extend.right)
line.new(time[1], c, time, c, xloc=xloc.bar_time, color=col_c, width=w, style=line_style, extend=extend.right)
// 繪製標籤並存入陣列
if show_lbl
date_str = str.format("{0,date,MM/dd}", prev_t)
lbl_o = label.new(time, o, prefix + "開 " + date_str, xloc=xloc.bar_time, color=color.new(color.white, 100), textcolor=col_o, size=size.small, style=label.style_label_left)
lbl_h = label.new(time, h, prefix + "高 " + date_str, xloc=xloc.bar_time, color=color.new(color.white, 100), textcolor=col_h, size=size.small, style=label.style_label_left)
lbl_l = label.new(time, l, prefix + "低 " + date_str, xloc=xloc.bar_time, color=color.new(color.white, 100), textcolor=col_l, size=size.small, style=label.style_label_left)
lbl_c = label.new(time, c, prefix + "收 " + date_str, xloc=xloc.bar_time, color=color.new(color.white, 100), textcolor=col_c, size=size.small, style=label.style_label_left)
array.push(all_labels, lbl_o)
array.push(all_labels, lbl_h)
array.push(all_labels, lbl_l)
array.push(all_labels, lbl_c)
// 確保標籤數量不超過系統上限
while array.size(all_labels) > 490
label.delete(array.shift(all_labels))
// 判斷是否開啟對應周期的顯示,每當遇到新的 RTH 時段,就會畫出前一個 RTH 週期的線條
if show_d
f_draw_levels(is_new_d, prev_d_t, prev_d_o, prev_d_h, prev_d_l, prev_d_c, "日", d_w, d_s, show_date, d_c_o, d_c_h, d_c_l, d_c_c)
if show_w
f_draw_levels(is_new_w, prev_w_t, prev_w_o, prev_w_h, prev_w_l, prev_w_c, "周", w_w, w_s, show_date, w_c_o, w_c_h, w_c_l, w_c_c)
if show_m
f_draw_levels(is_new_m, prev_m_t, prev_m_o, prev_m_h, prev_m_l, prev_m_c, "月", m_w, m_s, show_date, m_c_o, m_c_h, m_c_l, m_c_c)
// 在最新的一根 K 線時,統一將所有歷史標籤移動到可見畫面的最左邊
if barstate.islast
left_edge = chart.left_visible_bar_time
if array.size(all_labels) > 0
for lbl in all_labels
label.set_x(lbl, left_edge)
// =========================================================================
// 5. 繪製移動平均線 (SMA)
// =========================================================================
plot(show_sma5 ? ta.sma(close, 5) : na, title="SMA 5", color=col_sma5, linewidth=wid_sma5)
plot(show_sma10 ? ta.sma(close, 10) : na, title="SMA 10", color=col_sma10, linewidth=wid_sma10)
plot(show_sma20 ? ta.sma(close, 20) : na, title="SMA 20", color=col_sma20, linewidth=wid_sma20)
plot(show_sma60 ? ta.sma(close, 60) : na, title="SMA 60", color=col_sma60, linewidth=wid_sma60)
plot(show_sma120 ? ta.sma(close, 120) : na, title="SMA 120", color=col_sma120, linewidth=wid_sma120)
plot(show_sma240 ? ta.sma(close, 240) : na, title="SMA 240", color=col_sma240, linewidth=wid_sma240)
// =========================================================================
// 6. 繪製均線扣抵標籤 (Koudi)
// =========================================================================
// 建立只會在當下最新 K 線顯示的浮動標籤
var label kd_lbl_5 = label.new(na, na, text="5", style=label.style_label_up, size=size.small)
var label kd_lbl_10 = label.new(na, na, text="10", style=label.style_label_up, size=size.small)
var label kd_lbl_20 = label.new(na, na, text="20", style=label.style_label_up, size=size.small)
var label kd_lbl_60 = label.new(na, na, text="60", style=label.style_label_up, size=size.small)
var label kd_lbl_120 = label.new(na, na, text="120", style=label.style_label_up, size=size.small)
var label kd_lbl_240 = label.new(na, na, text="240", style=label.style_label_up, size=size.small)
// 確保圖表上有足夠的 K 線數量才繪製對應的標籤,並定位到 N-1 的位置
if barstate.islast
// SMA 5 扣抵
if show_sma5 and show_kd5 and bar_index >= 4
label.set_xy(kd_lbl_5, bar_index[4], low[4])
label.set_color(kd_lbl_5, color.new(col_sma5, kd_trans))
label.set_textcolor(kd_lbl_5, color.white)
else
label.set_xy(kd_lbl_5, na, na)
// SMA 10 扣抵
if show_sma10 and show_kd10 and bar_index >= 9
label.set_xy(kd_lbl_10, bar_index[9], low[9])
label.set_color(kd_lbl_10, color.new(col_sma10, kd_trans))
label.set_textcolor(kd_lbl_10, color.white)
else
label.set_xy(kd_lbl_10, na, na)
// SMA 20 扣抵
if show_sma20 and show_kd20 and bar_index >= 19
label.set_xy(kd_lbl_20, bar_index[19], low[19])
label.set_color(kd_lbl_20, color.new(col_sma20, kd_trans))
label.set_textcolor(kd_lbl_20, color.white)
else
label.set_xy(kd_lbl_20, na, na)
// SMA 60 扣抵
if show_sma60 and show_kd60 and bar_index >= 59
label.set_xy(kd_lbl_60, bar_index[59], low[59])
label.set_color(kd_lbl_60, color.new(col_sma60, kd_trans))
label.set_textcolor(kd_lbl_60, color.white)
else
label.set_xy(kd_lbl_60, na, na)
// SMA 120 扣抵
if show_sma120 and show_kd120 and bar_index >= 119
label.set_xy(kd_lbl_120, bar_index[119], low[119])
label.set_color(kd_lbl_120, color.new(col_sma120, kd_trans))
label.set_textcolor(kd_lbl_120, color.white)
else
label.set_xy(kd_lbl_120, na, na)
// SMA 240 扣抵
if show_sma240 and show_kd240 and bar_index >= 239
label.set_xy(kd_lbl_240, bar_index[239], low[239])
label.set_color(kd_lbl_240, color.new(col_sma240, kd_trans))
label.set_textcolor(kd_lbl_240, color.white)
else
label.set_xy(kd_lbl_240, na, na)