Pineスクリプトでチャートに水平線を引きたい。サポレジラインを自動表示したい。トレンドラインを動的に描画したい。
しかし、いざ書こうとすると選択肢が3つ出てくる。hline()、plot()、line.new()。どれを使えば目的の線が引けるのか、初めてだと迷う。
結論はこうだ。固定値の水平線ならhline()。計算値の水平線ならplot()。任意の2点を結ぶ線(水平線・斜め線・縦線すべて)ならline.new()。この3つの使い分けを理解すれば、あらゆるライン描画に対応できる。
この記事では、3つの関数の違いと使い分けから、前日高安ライン、ピボットポイント、ラウンドナンバーといった実用的なインジケーターまで、v6対応のコード付きで解説する。
- 1 3つの描画関数の使い分け
- 2 hline()で固定値の水平線を引く
- 3 plot()で動的な水平線を引く
- 4 line.new()の基本構文
- 5 line.new()で水平線を引く(extend付き)
- 6 line.delete()で古いラインを削除する
- 7 var宣言パターン(1本のラインを更新し続ける)
- 8 実用例①: 前日高値・安値・終値ライン
- 9 実用例②: ピボットポイント(S/R)ライン
- 10 実用例③: ラウンドナンバー(キリ番)ライン
- 11 実用例④: 当日の高値・安値レンジボックス
- 12 実用例⑤: ラベル付き水平線
- 13 line.set_*()でラインを後から更新する
- 14 box.new()でゾーンを描画する
- 15 よくあるミスと対処法
- 16 まとめ
3つの描画関数の使い分け
Pineスクリプトで線を引く関数は3つある。それぞれ得意な場面が異なる。
hline() — 固定値の水平線を引く専用関数。引数に定数のみ受け付ける。RSIの70/30ライン、ゼロラインなど、値が変わらない水平線に使う。fill()と組み合わせてゾーンを塗りつぶせるのが特徴。
plot() — シリーズ(バーごとに変わる値)を折れ線で描画する関数。SMAやEMAのようにバーごとに値が変わるラインに使う。plot.style_steplineを指定すれば階段状の水平ラインとしても使える。
line.new() — チャート上の任意の2点を指定して線を描画する関数。水平線、斜め線、縦線すべてに対応する。extendパラメータで線を左右に延長できる。描画オブジェクトなので、後から移動・削除・スタイル変更が可能。
迷ったときの判断基準はこうだ。
「RSI 70のように値が固定か?」→ hline()。「SMAのようにバーごとに値が変わるか?」→ plot()。「特定の価格に水平線を引きたい、または2点間に線を引きたいか?」→ line.new()。
hline()で固定値の水平線を引く
hline()は最もシンプルな水平線関数だ。引数に定数を1つ渡すだけで、チャート全体に水平線が描画される。
//@version=6
indicator("hlineの例", overlay=false)
rsi = ta.rsi(close, 14)
plot(rsi, "RSI", color.purple, 2)
// 固定値の水平線
h1 = hline(70, "買われすぎ", color.red, hline.style_dashed)
h2 = hline(30, "売られすぎ", color.green, hline.style_dashed)
hline(50, "中間", color.gray, hline.style_dotted)
// 2本のhlineの間を塗りつぶす
fill(h1, h2, color=color.new(color.purple, 90), title="RSIゾーン")
hline()の引数にはシリーズ(closeやta.sma()など)は使えない。定数またはリテラル値のみだ。「RSIの70ライン」「MACDのゼロライン」のように、値が永遠に変わらない水平線に使う。
hline.style_dashed(破線)、hline.style_dotted(点線)、hline.style_solid(実線)の3つのスタイルがある。
fill()に2つのhlineの戻り値を渡すと、その間の領域を塗りつぶせる。RSIの買われすぎ・売られすぎゾーンの可視化などに使う。
plot()で動的な水平線を引く
plot()はバーごとに値が変わるラインの描画に使う。plot.style_steplineを指定すれば、階段状の水平ラインとして表示できる。
//@version=6
indicator("plotで水平線", overlay=true)
// 前日の終値を水平線として表示
prevClose = request.security(syminfo.tickerid, "D", close[1])
plot(prevClose, "前日終値", color.orange, 2, plot.style_stepline)
// 当日の始値を水平線として表示
todayOpen = request.security(syminfo.tickerid, "D", open)
plot(todayOpen, "当日始値", color.blue, 1, plot.style_stepline)
plot.style_steplineは、値が変わるまで水平に線を引き、値が変わった瞬間に垂直にジャンプするスタイルだ。日足の前日終値を分足チャートに表示する場合など、日中は水平で日が変わるとジャンプする表示になる。
plot()で固定値(例: plot(100))を描画することもできるが、hline()との違いは「fill()での塗りつぶし方」だ。hline同士のfillと、plot同士のfillは引数の型が異なるので混在させないこと。
line.new()の基本構文
line.new()はチャート上の任意の2点を指定して線を描画する。水平線、斜め線、縦線すべてに対応する最も自由度の高い関数だ。
//@version=6
indicator("line.newの基本", overlay=true)
// 基本構文: line.new(x1, y1, x2, y2, ...)
// x = バーのインデックス(横軸)、y = 価格(縦軸)
if barstate.islast
// 現在のバーから左に50本分の水平線
line.new(bar_index - 50, close, bar_index, close, color=color.blue, width=2)
// 50本前の安値から現在の高値への斜め線(トレンドライン風)
line.new(bar_index - 50, low[50], bar_index, high, color=color.red, width=1, style=line.style_dashed)
// 縦線(同じx座標で異なるy座標)
line.new(bar_index - 25, low - syminfo.mintick * 50, bar_index - 25, high + syminfo.mintick * 50, color=color.gray, style=line.style_dotted)
line.new()の必須引数は4つ。x1(始点のバーインデックス)、y1(始点の価格)、x2(終点のバーインデックス)、y2(終点の価格)。
水平線を引くにはy1とy2を同じ値にする。斜め線を引くには異なる値にする。縦線を引くにはx1とx2を同じ値にする。
主要なオプション引数を整理する。
color — 線の色。width — 線の太さ(ピクセル)。style — line.style_solid(実線)、line.style_dashed(破線)、line.style_dotted(点線)、line.style_arrow_left(左矢印)、line.style_arrow_right(右矢印)、line.style_arrow_both(両矢印)。extend — extend.none(延長なし)、extend.left(左に延長)、extend.right(右に延長)、extend.both(両方に延長)。
line.new()で水平線を引く(extend付き)
extendパラメータを使えば、指定した2点を超えて無限に線を延長できる。サポレジラインの描画に最適だ。
//@version=6
indicator("水平線 extend", overlay=true, max_lines_count=500)
// 直近のピボットハイ・ローを検出して水平線を引く
pivotLen = input.int(5, "ピボット検出期間", minval=1)
pivHigh = ta.pivothigh(high, pivotLen, pivotLen)
pivLow = ta.pivotlow(low, pivotLen, pivotLen)
// ピボットハイに赤い水平線
if not na(pivHigh)
line.new(bar_index - pivotLen, pivHigh, bar_index, pivHigh, color=color.red, width=1, style=line.style_dashed, extend=extend.right)
// ピボットローに緑の水平線
if not na(pivLow)
line.new(bar_index - pivotLen, pivLow, bar_index, pivLow, color=color.green, width=1, style=line.style_dashed, extend=extend.right)
extend=extend.rightで線を右方向に無限に延長している。ピボットポイントが検出されるたびに新しい水平線が追加される。max_lines_count=500でライン描画の上限を引き上げている(デフォルトは50本)。
line.delete()で古いラインを削除する
ラインを無限に追加し続けるとチャートが見づらくなる。line.delete()で古いラインを消すパターンを覚えておこう。
//@version=6
indicator("最新N本のみ表示", overlay=true)
lookback = input.int(3, "表示するライン数", minval=1, maxval=20)
pivotLen = input.int(5, "ピボット検出期間")
// ラインを配列で管理
var array resistLines = array.new()
pivHigh = ta.pivothigh(high, pivotLen, pivotLen)
if not na(pivHigh)
// 新しいラインを追加
newLine = line.new(bar_index - pivotLen, pivHigh, bar_index, pivHigh, color=color.red, width=1, extend=extend.right)
array.push(resistLines, newLine)
// 古いラインを削除(N本を超えたら)
while array.size(resistLines) > lookback
oldLine = array.shift(resistLines)
line.delete(oldLine)
arrayにラインオブジェクトを蓄積し、上限を超えたらarray.shift()で最も古いラインを取り出してline.delete()で削除する。これで常に直近N本のラインだけが表示される。
var宣言パターン(1本のラインを更新し続ける)
「常に1本の水平線だけ表示し、バーが進むたびに位置を更新する」というパターンもよく使う。
//@version=6
indicator("1本の水平線を更新", overlay=true)
src = input.source(close, "ソース")
length = input.int(20, "期間")
highestPrice = ta.highest(src, length)
lowestPrice = ta.lowest(src, length)
var line highLine = na
var line lowLine = na
// 既存のラインを削除して新しいラインを作成
if not na(highLine)
line.delete(highLine)
if not na(lowLine)
line.delete(lowLine)
highLine := line.new(bar_index - length, highestPrice, bar_index, highestPrice, color=color.red, width=2)
lowLine := line.new(bar_index - length, lowestPrice, bar_index, lowestPrice, color=color.green, width=2)
varで宣言したライン変数は初回バーでのみ初期化される。毎バーline.delete()で前のラインを消し、line.new()で新しいラインを作り直す。結果として、常に最新の1本だけが表示される。
構文の基本を復習したい方はこちら。
→ Pineスクリプトの書き方|基本構文をコード付きで完全解説
実用例①: 前日高値・安値・終値ライン
デイトレーダー必須の、前日高値(PDH)・安値(PDL)・終値(PDC)を水平線で表示するインジケーター。
//@version=6
indicator("前日高安終値ライン", overlay=true)
showPDH = input.bool(true, "前日高値")
showPDL = input.bool(true, "前日安値")
showPDC = input.bool(true, "前日終値")
pdh = request.security(syminfo.tickerid, "D", high[1])
pdl = request.security(syminfo.tickerid, "D", low[1])
pdc = request.security(syminfo.tickerid, "D", close[1])
plot(showPDH ? pdh : na, "PDH", color.red, 2, plot.style_stepline_diamond)
plot(showPDL ? pdl : na, "PDL", color.green, 2, plot.style_stepline_diamond)
plot(showPDC ? pdc : na, "PDC", color.orange, 1, plot.style_stepline)
この例はplot()を使っている。request.security()で取得した日足の値は日中一定なので、plot.style_steplineで階段状の水平線として表示される。line.new()を使わなくても済むケースだ。
実用例②: ピボットポイント(S/R)ライン
フロアトレーダーズ・ピボットのS1/S2/R1/R2ラインを水平線で表示する。
//@version=6
indicator("ピボットポイント", overlay=true)
// 前日の四本値を取得
prevHigh = request.security(syminfo.tickerid, "D", high[1])
prevLow = request.security(syminfo.tickerid, "D", low[1])
prevClose = request.security(syminfo.tickerid, "D", close[1])
// ピボットポイント計算
pp = (prevHigh + prevLow + prevClose) / 3
r1 = 2 * pp - prevLow
s1 = 2 * pp - prevHigh
r2 = pp + (prevHigh - prevLow)
s2 = pp - (prevHigh - prevLow)
// 描画
plot(pp, "PP", color.yellow, 2, plot.style_stepline)
plot(r1, "R1", color.new(color.red, 30), 1, plot.style_stepline)
plot(r2, "R2", color.new(color.red, 0), 2, plot.style_stepline)
plot(s1, "S1", color.new(color.green, 30), 1, plot.style_stepline)
plot(s2, "S2", color.new(color.green, 0), 2, plot.style_stepline)
ピボットポイントは前日の四本値から算出するため日中は値が変わらない。plot()のsteplineで十分対応できる。
実用例③: ラウンドナンバー(キリ番)ライン
100円単位、50pips単位などのキリのいい価格に水平線を自動で引くインジケーター。line.new()の実用的な使い方がわかる例だ。
//@version=6
indicator("ラウンドナンバー", overlay=true, max_lines_count=500)
// パラメータ
interval = input.float(1.0, "間隔", tooltip="FXなら0.5や1.0、株なら100や500")
lineColor = input.color(color.new(color.gray, 50), "ライン色")
lineStyle = input.string("点線", "スタイル", options=["実線", "破線", "点線"])
// スタイル変換
style = switch lineStyle
"実線" => line.style_solid
"破線" => line.style_dashed
"点線" => line.style_dotted
=> line.style_dotted
// 表示範囲の上限・下限
visibleHigh = ta.highest(high, 200)
visibleLow = ta.lowest(low, 200)
// ラウンドナンバーの起点と終点を計算
startLevel = math.floor(visibleLow / interval) * interval
endLevel = math.ceil(visibleHigh / interval) * interval
// 最終バーでラインを描画
if barstate.islast
level = startLevel
while level <= endLevel
line.new(bar_index - 200, level, bar_index + 50, level, color=lineColor, width=1, style=style)
level := level + interval
math.floor()とmath.ceil()で表示範囲のラウンドナンバーを計算し、whileループで等間隔に水平線を描画している。barstate.islastで最新バーでのみ描画することで、毎バーラインが増殖するのを防いでいる。
実用例④: 当日の高値・安値レンジボックス
当日のここまでの高値・安値をリアルタイムで追跡し、line.new()でボックス状に表示する。
//@version=6
indicator("当日レンジボックス", overlay=true)
// 当日の高値・安値
todayHigh = request.security(syminfo.tickerid, "D", high)
todayLow = request.security(syminfo.tickerid, "D", low)
// 当日開始バーを検出
newDay = ta.change(time("D")) != 0
var int dayStartBar = na
if newDay
dayStartBar := bar_index
// ライン描画
var line topLine = na
var line bottomLine = na
var line leftLine = na
if not na(dayStartBar)
line.delete(topLine)
line.delete(bottomLine)
line.delete(leftLine)
topLine := line.new(dayStartBar, todayHigh, bar_index + 10, todayHigh, color=color.red, width=2)
bottomLine := line.new(dayStartBar, todayLow, bar_index + 10, todayLow, color=color.green, width=2)
leftLine := line.new(dayStartBar, todayHigh, dayStartBar, todayLow, color=color.gray, width=1, style=line.style_dotted)
ta.change(time("D"))で日付の変わり目を検出し、日中は当日の高値・安値に合わせてラインを更新し続ける。3本のlineで上辺・下辺・左辺を描画し、レンジボックスのように見せている。
実用例⑤: ラベル付き水平線
水平線に価格ラベルを付けて、何の価格なのかをチャート上で一目でわかるようにする。
//@version=6
indicator("ラベル付き水平線", overlay=true)
pdh = request.security(syminfo.tickerid, "D", high[1])
pdl = request.security(syminfo.tickerid, "D", low[1])
var line pdhLine = na
var line pdlLine = na
var label pdhLabel = na
var label pdlLabel = na
// 古い描画を削除
line.delete(pdhLine)
line.delete(pdlLine)
label.delete(pdhLabel)
label.delete(pdlLabel)
// 水平線
pdhLine := line.new(bar_index - 100, pdh, bar_index + 20, pdh, color=color.red, width=1, style=line.style_dashed)
pdlLine := line.new(bar_index - 100, pdl, bar_index + 20, pdl, color=color.green, width=1, style=line.style_dashed)
// ラベル
pdhLabel := label.new(bar_index + 20, pdh, "PDH " + str.tostring(pdh, format.mintick), style=label.style_label_left, color=color.new(color.red, 80), textcolor=color.red, size=size.small)
pdlLabel := label.new(bar_index + 20, pdl, "PDL " + str.tostring(pdl, format.mintick), style=label.style_label_left, color=color.new(color.green, 80), textcolor=color.green, size=size.small)
label.new()とline.new()を組み合わせることで、水平線の右端に「PDH 150.234」のような価格ラベルを表示できる。bar_index + 20で未来のバー位置にラベルを配置することで、現在のローソク足と重ならないようにしている。
コピペで動く実用インジケーターをもっと見たい方はこちら。
→ Pineスクリプトサンプルコード集|コピペで動く実用インジケーター10選
line.set_*()でラインを後から更新する
line.new()で作成したラインは、line.set_*()系の関数で後から属性を変更できる。毎バー削除・再作成するよりも効率的だ。
//@version=6
indicator("ラインの動的更新", overlay=true)
// 初回のみラインを作成
var line myLine = line.new(bar_index, close, bar_index, close, color=color.blue, width=2, extend=extend.both)
// 毎バー位置を更新(削除・再作成不要)
line.set_xy1(myLine, bar_index - 1, close)
line.set_xy2(myLine, bar_index, close)
主なset関数を整理する。line.set_xy1()は始点の座標を変更。line.set_xy2()は終点の座標を変更。line.set_color()は色を変更。line.set_width()は太さを変更。line.set_style()はスタイルを変更。line.set_extend()は延長設定を変更。
varで1回だけラインを作成し、setで位置を更新するパターンは、ラインの生成・削除コストを抑えられるため、パフォーマンスの面でも有利だ。
box.new()でゾーンを描画する
水平線ではなく「価格帯(ゾーン)」を可視化したい場合は、box.new()が便利だ。
//@version=6
indicator("サポレジゾーン", overlay=true)
pdh = request.security(syminfo.tickerid, "D", high[1])
pdl = request.security(syminfo.tickerid, "D", low[1])
pdc = request.security(syminfo.tickerid, "D", close[1])
// 終値を中心に前日レンジの10%をゾーンとして表示
zoneWidth = (pdh - pdl) * 0.1
var box resistZone = na
var box supportZone = na
box.delete(resistZone)
box.delete(supportZone)
resistZone := box.new(bar_index - 100, pdh, bar_index + 20, pdh - zoneWidth, bgcolor=color.new(color.red, 85), border_color=color.red, border_width=1)
supportZone := box.new(bar_index - 100, pdl + zoneWidth, bar_index + 20, pdl, bgcolor=color.new(color.green, 85), border_color=color.green, border_width=1)
box.new()は4つの座標(左上x, 左上y, 右下x, 右下y)で矩形を描画する。水平線1本では表現できない「価格帯」の可視化に最適だ。
よくあるミスと対処法
ミス①: hline()に変数を渡してエラーになる。hline(close)はエラー。hline()は定数のみ受け付ける。バーごとに変わる値を水平線にしたいならplot()かline.new()を使う。
ミス②: ラインが増殖して見づらくなる。line.new()をif文の中で条件なく毎バー実行すると、バーの数だけラインが生成される。barstate.islastで最新バーのみ描画するか、var + line.delete()パターンで古いラインを消す。
ミス③: max_lines_countの上限に達する。デフォルトでは同時に表示できるラインは50本。上限に達すると古いラインから自動削除される。indicator()の引数にmax_lines_count=500を指定して上限を引き上げるか、不要なラインを手動でline.delete()する。
ミス④: xloc.bar_timeとxloc.bar_indexを混在させる。line.new()のx座標はbar_index(バーの番号)がデフォルトだが、xloc=xloc.bar_timeを指定するとUNIXタイムスタンプで指定できる。両者を混在させるとラインが意図しない位置に表示される。
ミス⑤: 未来のバーにラインを延ばせない。bar_index + 20のように未来のバーインデックスを指定すれば、チャートの右側の余白にラインを延ばせる。ただしextend=extend.rightを使えば、終点を指定しなくても無限に延ばせる。
まとめ
Pineスクリプトでの水平線・ライン描画は3つの関数を使い分ける。固定値ならhline()、計算値ならplot()、自由な描画ならline.new()。
line.new()を使う場合は「var宣言 → 毎バーdelete → 再作成」のパターンか、「var宣言 → set_*で更新」のパターンを覚えておけば、ラインの増殖問題を回避できる。box.new()とlabel.new()を組み合わせれば、プロレベルのサポレジ表示も実現可能だ。















