[NOTICE & LICENSE]
・僅供學習與提供資訊之用,不構成投資建議。對於因使用本工具而產生之任何經濟損失,概不負責。
・已於 Pine Script v6 測試運作。以「現狀 (As-is)」提供,不保證因未來 TradingView 系統規格變更而進行更新,亦不接受個別的安裝支援或修改請求。
・適用 MIT 授權條款。
// SPDX-FileCopyrightText: 2026 NK-report https://www.nk-report.com/
// SPDX-License-Identifier: MIT
//
// Disclaimer: This script is for educational purposes only and does not constitute investment advice.
//@version=6
// ※ダイナミックグリッドの描画上限を確保するため、linesとlabelsの上限を拡張しています
indicator("NK-Horizon Round", shorttitle="NK-Horizon", overlay=true, max_lines_count=500, max_labels_count=500)
// ==============================================================================
// 【01】 免責・ライセンス
// ==============================================================================
//
// 本指標免費公開: https://www.nk-report.com/p/tw-tradingview.html
//
// 免責聲明:本腳本僅供學習與資訊參考之用,不構成任何投資建議。
//
// 1. 本程式碼截至 2026 年,已在 Pine Script v6 環境下完成運作測試。
// 日後若因規格變動而導致任何異常,恕不提供個別的技術支援或修改服務。
// 2. 本腳本係基於一般的計算邏輯,並透過 LLM 獨立編寫而成。
// 本程式碼採用 MIT 授權條款 (MIT License) 進行發布。
// ------------------------------------------------------------------------------
// MIT License
//
// Copyright 2026 NK-report https://www.nk-report.com/
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
// of the Software, and to permit persons to whom the Software is furnished to do
// so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
// ==============================================================================
// 【02】 UI設定と言語
// ==============================================================================
const string GRP_GENERAL = "▼ 基本設定"
const string GRP_MAIN = "▼ 主層級 (整數關卡)"
const string GRP_SUB = "▼ 次層級 (半數關卡)"
const string OPT_STY_S = "實線"
const string OPT_STY_D = "虛線"
const string OPT_STY_DT = "點線"
const string OPT_POS_L = "左"
const string OPT_POS_C = "中"
const string OPT_POS_R = "右"
// 基本設定
i_step = input.float(1.0, title="間距大小 (整數關卡的單位)", step=0.1, group=GRP_GENERAL, tooltip="請指定目標商品的基準數值。例如:美日兌(USDJPY)可設為 1 或 0.5,日經指數可設為 500 或 100 等。")
i_num_lines = input.int(10, title="上下繪製數量 (單側)", minval=1, maxval=50, group=GRP_GENERAL, tooltip="從當前價格向上及向下繪製 X 條線。在預設值(10)的情況下,總共會有 21 條線跟隨當前價格移動。")
i_show_lbl = input.bool(true, title="顯示價格標籤", group=GRP_GENERAL, inline="lbl")
i_lbl_pos = input.string(OPT_POS_R, title="位置", options=[OPT_POS_L, OPT_POS_C, OPT_POS_R], group=GRP_GENERAL, inline="lbl")
i_lbl_offset = input.int(22, title="滑動調整 (K線數)", minval=0, group=GRP_GENERAL, tooltip="選擇「左」或「右」時,調整標籤距離最新 K 線的遠近。\n※若選擇「中」,則忽略此數值。")
// メインレベル設定
i_show_main = input.bool(true, title="顯示", group=GRP_MAIN, inline="main1")
i_col_main = input.color(color.black, title="顏色", group=GRP_MAIN, inline="main1")
i_wid_main = input.int(1, title="粗細", minval=1, maxval=5, group=GRP_MAIN, inline="main1")
i_sty_main = input.string(OPT_STY_S, title="樣式", options=[OPT_STY_S, OPT_STY_D, OPT_STY_DT], group=GRP_MAIN, inline="main1")
// サブレベル設定
i_show_sub = input.bool(false, title="顯示", group=GRP_SUB, inline="sub1")
i_col_sub = input.color(color.black, title="顏色", group=GRP_SUB, inline="sub1")
i_wid_sub = input.int(1, title="粗細", minval=1, maxval=5, group=GRP_SUB, inline="sub1")
i_sty_sub = input.string(OPT_STY_DT, title="樣式", options=[OPT_STY_S, OPT_STY_D, OPT_STY_DT], group=GRP_SUB, inline="sub1")
// ==============================================================================
// 【03】 全コード共通仕様(時間・インフラ処理)
// ==============================================================================
// ※該当コードなし
// (本ツールは時間枠に依存せず、常に現在の価格のみを参照して水平線を引くため、時間の変換処理は不要です)
// ==============================================================================
// 【04】 各カテゴリ共通仕様 (描画インフラと判定ロジック)
// ==============================================================================
f_get_style(sty_str) =>
sty_str == OPT_STY_S ? line.style_solid : sty_str == OPT_STY_D ? line.style_dashed : line.style_dotted
// ==============================================================================
// 【05】 このコード固有の計算仕様 (Specific Indicator Logic)
// ==============================================================================
// エレベーター方式の描画オブジェクトを格納する配列群 (Object Pooling)
var array<line> a_main_l = array.new<line>()
var array<label> a_main_lbl = array.new<label>()
var array<line> a_sub_l = array.new<line>()
var array<label> a_sub_lbl = array.new<label>()
// 初回ロード時:必要な本数分のオブジェクトを1セットだけ生成し、配列に格納・待機させる
if barstate.isfirst
int total_lines = (i_num_lines * 2) + 1
for i = 0 to total_lines - 1
// メインライン用
a_main_l.push(line.new(na, na, na, na, extend=extend.both, color=i_col_main, width=i_wid_main, style=f_get_style(i_sty_main)))
a_main_lbl.push(label.new(na, na, text="", color=color.new(color.white, 100), textcolor=i_col_main, style=label.style_none, size=size.small))
// サブライン用
a_sub_l.push(line.new(na, na, na, na, extend=extend.both, color=i_col_sub, width=i_wid_sub, style=f_get_style(i_sty_sub)))
a_sub_lbl.push(label.new(na, na, text="", color=color.new(color.white, 100), textcolor=i_col_sub, style=label.style_none, size=size.small))
// ==============================================================================
// 【06】 描画と出力 (Rendering & Outputs)
// ==============================================================================
// リアルタイム更新:過去の足では計算せず、最新の足でのみ配列内の座標をスライド更新する
if barstate.islast
// 剰余算による「最も近いラウンドナンバー」の数学的特定
float center_p = math.round(close / i_step) * i_step
int total_lines = (i_num_lines * 2) + 1
// 最新足(最前線)をアンカーにしたラベルX座標の決定
int lbl_x = bar_index
if i_lbl_pos == OPT_POS_L
lbl_x := bar_index - i_lbl_offset
else if i_lbl_pos == OPT_POS_R
lbl_x := bar_index + i_lbl_offset
for i = 0 to total_lines - 1
int offset = i - i_num_lines
float p_main = center_p + (offset * i_step)
// --- メインレベルの更新 ---
line l_m = a_main_l.get(i)
label lbl_m = a_main_lbl.get(i)
if i_show_main
line.set_xy1(l_m, bar_index, p_main)
line.set_xy2(l_m, bar_index + 1, p_main)
line.set_color(l_m, i_col_main)
line.set_width(l_m, i_wid_main)
line.set_style(l_m, f_get_style(i_sty_main))
if i_show_lbl
label.set_xy(lbl_m, lbl_x, p_main)
label.set_text(lbl_m, str.tostring(p_main, format.mintick))
label.set_textcolor(lbl_m, i_col_main)
else
label.set_xy(lbl_m, na, na)
else
line.set_xy1(l_m, na, na)
line.set_xy2(l_m, na, na)
label.set_xy(lbl_m, na, na)
// --- サブレベル (半値) の更新 ---
line l_s = a_sub_l.get(i)
label lbl_s = a_sub_lbl.get(i)
if i_show_sub
float p_sub = p_main + (i_step * 0.5)
line.set_xy1(l_s, bar_index, p_sub)
line.set_xy2(l_s, bar_index + 1, p_sub)
line.set_color(l_s, i_col_sub)
line.set_width(l_s, i_wid_sub)
line.set_style(l_s, f_get_style(i_sty_sub))
if i_show_lbl
label.set_xy(lbl_s, lbl_x, p_sub)
label.set_text(lbl_s, str.tostring(p_sub, format.mintick))
label.set_textcolor(lbl_s, i_col_sub)
else
label.set_xy(lbl_s, na, na)
else
line.set_xy1(l_s, na, na)
line.set_xy2(l_s, na, na)
label.set_xy(lbl_s, na, na)
// ※本ツールは「背景グリッド」としての役割に徹するため、ノイズ防止の観点からデータウィンドウへの出力は行いません。
* 設定好喜歡的顏色配置後,請在設定分頁中點擊「儲存為預設值」。
* 若未按照「新增 → 指標 → 貼上」的順序操作,可能無法正確顯示。
