Pineスクリプトで「東京時間だけシグナルを出したい」「ロンドン時間の背景色を変えたい」と思ったとき、最初に困るのが時間の扱い方だ。TradingViewのチャートはタイムゾーンが取引所やユーザー設定で異なるため、hour変数を使って単純に時間判定すると、環境が変わったときにズレる。
Pineスクリプトには、タイムゾーンを正しく処理する専用の仕組みがある。time()関数とセッション文字列、そしてIANAタイムゾーン指定だ。これを使えば、夏時間の切り替わりも含めて完全自動で正しい時間判定ができる。
この記事では、時間指定の正しい方法をv6ベースで体系的に解説する。東京・ロンドン・ニューヨークの3市場セッションを題材に、コピペで動くコード例を付けた。
時間指定の2つの方法
Pineスクリプトで時間を扱う方法は大きく2つある。
方法①: time()関数+セッション文字列(推奨)。タイムゾーンを明示的に指定でき、夏時間にも自動対応する。セッション(時間帯)の判定に最適だ。
方法②: hour / minute変数。現在のバーの時・分を取得する。単純だが、チャートのタイムゾーン設定に依存するため、環境が変わるとズレるリスクがある。
結論から言えば、市場セッションの判定には方法①を使うべきだ。方法②はデバッグや簡易的な用途に留めるのが安全だ。
time()関数の基本構文
time()関数は、現在のバーが指定した時間帯に含まれるかどうかを判定する。
//@version=6
indicator("time()の基本", overlay=true)
// time(時間足, セッション文字列, タイムゾーン) → 含まれればUNIX時刻、含まれなければna
inSession = not na(time(timeframe.period, "0900-1500", "Asia/Tokyo"))
bgcolor(inSession ? color.new(color.red, 90) : na)
time()の戻り値は、バーがセッション内ならUNIXタイムスタンプ(数値)、セッション外ならnaを返す。not na()で真偽値に変換するのが定番のパターンだ。
3つの引数を分解して説明する。
第1引数: 時間足 — timeframe.periodを指定すると、現在のチャートの時間足で判定する。"15"(15分足)のように固定することもできる。
第2引数: セッション文字列 — "HHMM-HHMM"の形式で開始時刻と終了時刻を指定する。"0900-1500"なら9時00分から15時00分まで。24時をまたぐ場合は"2200-0600"のように書ける。
第3引数: タイムゾーン — IANA形式で指定する。"Asia/Tokyo"、"Europe/London"、"America/New_York"など。この指定があるため、チャートのタイムゾーン設定に関係なく正しい判定ができる。
セッション文字列の書き方
セッション文字列にはいくつかのルールと拡張機能がある。
基本形は"HHMM-HHMM"。例えば"0930-1600"はAM 9:30からPM 4:00まで。
曜日を限定するには、末尾に曜日コードを付ける。"0930-1600:23456"で月曜〜金曜のみ(1=日曜、2=月曜、…、7=土曜)。FXのように土日休みの市場では":23456"を付けておくと安全だ。
複数のセッションをカンマで区切ると、OR条件として扱える。"0900-1200,1300-1500"は午前セッションと午後セッションの両方に反応する。
24時をまたぐ場合は"2200-0600"のように開始時刻が終了時刻より大きい値で書く。Pineスクリプトが自動的に日付をまたいだ判定をしてくれる。
//@version=6
indicator("セッション文字列の例", overlay=true)
// 平日のみ、9:00-15:00(東京時間)
tokyo = not na(time(timeframe.period, "0900-1500:23456", "Asia/Tokyo"))
// 午前と午後を分離
tokyoAM = not na(time(timeframe.period, "0900-1130:23456", "Asia/Tokyo"))
tokyoPM = not na(time(timeframe.period, "1230-1500:23456", "Asia/Tokyo"))
bgcolor(tokyoAM ? color.new(color.red, 90) : tokyoPM ? color.new(color.orange, 90) : na)
東京・ロンドン・NYの3セッション表示
FXトレーダーが最もよく使う、3大市場のセッション時間を背景色で可視化するインジケーター。
//@version=6
indicator("3市場セッション", overlay=true)
// パラメータ
showTokyo = input.bool(true, "東京", group="表示")
showLondon = input.bool(true, "ロンドン", group="表示")
showNY = input.bool(true, "NY", group="表示")
tokyoCol = input.color(color.new(color.red, 90), "東京色", group="色")
londonCol = input.color(color.new(color.green, 90), "ロンドン色", group="色")
nyCol = input.color(color.new(color.blue, 90), "NY色", group="色")
// セッション判定
isTokyo = not na(time(timeframe.period, "0900-1500:23456", "Asia/Tokyo"))
isLondon = not na(time(timeframe.period, "0800-1630:23456", "Europe/London"))
isNY = not na(time(timeframe.period, "0930-1600:23456", "America/New_York"))
// 背景色
bgcolor(showTokyo and isTokyo ? tokyoCol : na, title="東京")
bgcolor(showLondon and isLondon ? londonCol : na, title="ロンドン")
bgcolor(showNY and isNY ? nyCol : na, title="NY")
タイムゾーンを"Asia/Tokyo"、"Europe/London"、"America/New_York"で指定しているため、ロンドンとニューヨークは夏時間(DST)に自動対応する。3月の第2日曜や11月の第1日曜に時間がズレる心配がない。
各セッションの開始・終了時間は以下の通り。
東京セッションは9:00〜15:00(JST固定、夏時間なし)。ロンドンセッションは8:00〜16:30(GMT/BST、夏時間で1時間前倒し)。ニューヨークセッションは9:30〜16:00(EST/EDT、夏時間で1時間前倒し)。
セッション開始ラインの追加
セッションの背景色だけでなく、各セッションの開始時刻に縦線を引くバージョン。トレンドの転換ポイントを確認しやすくなる。
//@version=6
indicator("セッション開始ライン", overlay=true, max_lines_count=500)
// セッション判定
isTokyo = not na(time(timeframe.period, "0900-1500:23456", "Asia/Tokyo"))
isLondon = not na(time(timeframe.period, "0800-1630:23456", "Europe/London"))
isNY = not na(time(timeframe.period, "0930-1600:23456", "America/New_York"))
// セッション開始(前のバーがセッション外、現在のバーがセッション内)
tokyoStart = isTokyo and not isTokyo[1]
londonStart = isLondon and not isLondon[1]
nyStart = isNY and not isNY[1]
// 縦線を描画
if tokyoStart
line.new(bar_index, high, bar_index, low, color=color.red, style=line.style_dotted, extend=extend.both, width=1)
if londonStart
line.new(bar_index, high, bar_index, low, color=color.green, style=line.style_dotted, extend=extend.both, width=1)
if nyStart
line.new(bar_index, high, bar_index, low, color=color.blue, style=line.style_dotted, extend=extend.both, width=1)
「前のバーがセッション外で、現在のバーがセッション内」という条件でセッション開始を検出している。not isTokyo[1]が前のバーの状態だ。max_lines_count=500でライン描画の上限を引き上げている。
特定時間帯だけシグナルを出す
移動平均線のクロスシグナルを、指定したセッション内でのみ表示する。セッション外のノイズを排除するフィルターとして使える。
//@version=6
indicator("セッション限定シグナル", overlay=true)
// セッション設定
sessionStr = input.string("0800-1630", "セッション時間", tooltip="HHMM-HHMM形式")
sessionTZ = input.string("Europe/London", "タイムゾーン", options=["Asia/Tokyo", "Europe/London", "America/New_York", "Etc/UTC"])
// EMA設定
fastLen = input.int(12, "短期EMA")
slowLen = input.int(26, "長期EMA")
// 計算
emaFast = ta.ema(close, fastLen)
emaSlow = ta.ema(close, slowLen)
inSession = not na(time(timeframe.period, sessionStr, sessionTZ))
// セッション内のみシグナルを出す
bullSignal = ta.crossover(emaFast, emaSlow) and inSession
bearSignal = ta.crossunder(emaFast, emaSlow) and inSession
// 描画
plot(emaFast, "EMA Fast", color.blue)
plot(emaSlow, "EMA Slow", color.red)
bgcolor(inSession ? color.new(color.gray, 95) : na)
plotshape(bullSignal, "買い", shape.triangleup, location.belowbar, color.green, size=size.small)
plotshape(bearSignal, "売り", shape.triangledown, location.abovebar, color.red, size=size.small)
ポイントはand inSessionでシグナル条件にセッション判定を加えている部分だ。これだけで「ロンドン時間のみのEMAクロスシグナル」のように限定できる。input.stringでタイムゾーンを選択式にしているので、設定画面から切り替えも可能だ。
セッション別の高値・安値レンジ
各セッションの高値と安値をリアルタイムで追跡し、レンジとして表示する。ブレイクアウト戦略の基準として使える。
//@version=6
indicator("セッションレンジ", overlay=true)
// セッション選択
sessionStr = input.string("0900-1500", "セッション", options=["0900-1500", "0800-1630", "0930-1600"])
sessionTZ = input.string("Asia/Tokyo", "タイムゾーン", options=["Asia/Tokyo", "Europe/London", "America/New_York"])
// セッション判定
inSession = not na(time(timeframe.period, sessionStr, sessionTZ))
sessionStart = inSession and not inSession[1]
// セッション内の高値・安値を追跡
var float sessionHigh = na
var float sessionLow = na
if sessionStart
sessionHigh := high
sessionLow := low
else if inSession
sessionHigh := math.max(sessionHigh, high)
sessionLow := math.min(sessionLow, low)
// 描画(セッション内のみ表示)
plot(inSession ? sessionHigh : na, "Session High", color.red, 2, plot.style_stepline)
plot(inSession ? sessionLow : na, "Session Low", color.green, 2, plot.style_stepline)
bgcolor(inSession ? color.new(color.gray, 95) : na)
varで宣言した変数はバーをまたいで値を保持する。セッション開始時にリセットし、セッション中はmath.max()とmath.min()で最高値・最安値を更新し続ける。
構文の基礎をもっと体系的に学びたい方はこちら。
→ Pineスクリプトの書き方|基本構文をコード付きで完全解説
hour / minute変数を使う方法(注意点あり)
time()関数ではなく、hourとminuteの組み込み変数で時間を取得する方法もある。シンプルだが、注意点がある。
//@version=6
indicator("hour/minuteの例", overlay=true)
// hour / minute はチャートのタイムゾーン設定に依存する
currentHour = hour
currentMinute = minute
// タイムゾーンを指定してhourを取得(v6の推奨方法)
tokyoHour = hour(time, "Asia/Tokyo")
londonHour = hour(time, "Europe/London")
// 東京時間9時〜15時を判定
isTokyoTime = tokyoHour >= 9 and tokyoHour < 15
bgcolor(isTokyoTime ? color.new(color.red, 90) : na)
hourを引数なしで使うと、チャートのタイムゾーン設定に依存する。ユーザーがチャートのタイムゾーンをUTCに変更しただけで判定がズレてしまう。
v6ではhour(time, "Asia/Tokyo")のように第2引数でタイムゾーンを指定できる。これならtime()関数と同等の安全性がある。ただし、セッション文字列のように曜日指定や複数セッションの結合はできないため、市場セッションの判定にはtime()関数のほうが適している。
timestamp()で特定日時を指定する
「何月何日以降のみバックテストする」のように、特定の日時を基準にしたフィルタリングにはtimestamp()を使う。
//@version=6
strategy("期間限定ストラテジー", overlay=true)
// 開始日時と終了日時
startDate = input.time(timestamp("2024-01-01"), "開始日")
endDate = input.time(timestamp("2024-12-31"), "終了日")
// 期間内かどうか
inRange = time >= startDate and time <= endDate
// EMAクロス戦略(期間内のみ)
fast = ta.ema(close, 12)
slow = ta.ema(close, 26)
if inRange and ta.crossover(fast, slow)
strategy.entry("Long", strategy.long)
if inRange and ta.crossunder(fast, slow)
strategy.close("Long")
bgcolor(inRange ? color.new(color.green, 95) : color.new(color.gray, 95))
plot(fast, "EMA12", color.blue)
plot(slow, "EMA26", color.red)
timestamp("2024-01-01")はISO形式の文字列からUNIXタイムスタンプを生成する。input.time()と組み合わせると、設定画面にカレンダーUIが表示され、マウスで日付を選択できる。
仲値トレード(9:55 JST)の実装例
FXで有名な「仲値トレード」のように、特定の時刻にエントリー・決済するストラテジーの実装例。
//@version=6
strategy("仲値ストラテジー", overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=100)
// パラメータ
entryHour = input.int(0, "エントリー時(UTC)", tooltip="JST-9で指定。JST 0:00 = UTC 15:00前日")
entryMinute = input.int(0, "エントリー分")
exitHour = input.int(0, "決済時(UTC)")
exitMinute = input.int(55, "決済分")
// 時刻判定(タイムゾーン指定で安全に)
tokyoH = hour(time, "Asia/Tokyo")
tokyoM = minute(time, "Asia/Tokyo")
isEntry = tokyoH == entryHour and tokyoM == entryMinute
isExit = tokyoH == exitHour and tokyoM == exitMinute
// エントリー・決済
if isEntry and strategy.position_size == 0
strategy.entry("Nakahe", strategy.long)
if isExit and strategy.position_size > 0
strategy.close("Nakahe")
// 仲値時刻にマーク
plotshape(isEntry, "Entry", shape.arrowup, location.belowbar, color.green, size=size.small)
plotshape(isExit, "Exit", shape.arrowdown, location.abovebar, color.red, size=size.small)
hour(time, "Asia/Tokyo")で東京時間の時刻を安全に取得している。hour変数を直接使う方法よりも確実だ。仲値の9:55を狙う場合はexitHour=9、exitMinute=55に設定する。
時間指定のシグナルにアラートを付けたい場合はこちらが参考になる。
→ Pineスクリプトアラート実装|alertcondition()の使い方
夏時間(DST)の自動処理
Pineスクリプトで"Europe/London"や"America/New_York"を指定すると、夏時間への切り替えは自動で処理される。手動でオフセットを変える必要はない。
ロンドンは3月最終日曜にBST(UTC+1)へ、10月最終日曜にGMT(UTC+0)へ切り替わる。ニューヨークは3月第2日曜にEDT(UTC-4)へ、11月第1日曜にEST(UTC-5)へ切り替わる。東京は夏時間がないため、"Asia/Tokyo"は通年UTC+9だ。
//@version=6
indicator("DST確認", overlay=true)
// ロンドン時間の「時」を表示(DSTで自動的に変わる)
londonH = hour(time, "Europe/London")
var table t = table.new(position.top_right, 2, 2, bgcolor=color.new(color.black, 80))
if barstate.islast
table.cell(t, 0, 0, "London Hour", text_color=color.gray, text_size=size.small)
table.cell(t, 1, 0, str.tostring(londonH), text_color=color.white, text_size=size.small)
table.cell(t, 0, 1, "Tokyo Hour", text_color=color.gray, text_size=size.small)
table.cell(t, 1, 1, str.tostring(hour(time, "Asia/Tokyo")), text_color=color.white, text_size=size.small)
3月と10月の切り替わりをまたぐチャートを表示して確認すると、londonHが自動で1時間シフトしているのがわかる。hour + オフセットのような手動計算では、この切り替わりを正しく処理できない。
IANAタイムゾーン一覧(よく使うもの)
time()やhour()の第3引数・第2引数に指定するタイムゾーン文字列の一覧。
東京は"Asia/Tokyo"(UTC+9、夏時間なし)。香港は"Asia/Hong_Kong"(UTC+8、夏時間なし)。シンガポールは"Asia/Singapore"(UTC+8、夏時間なし)。シドニーは"Australia/Sydney"(UTC+10/+11、夏時間あり)。ロンドンは"Europe/London"(UTC+0/+1、夏時間あり)。フランクフルトは"Europe/Berlin"(UTC+1/+2、夏時間あり)。ニューヨークは"America/New_York"(UTC-5/-4、夏時間あり)。シカゴは"America/Chicago"(UTC-6/-5、夏時間あり)。UTCは"Etc/UTC"(固定)。
夏時間ありの地域はIANA形式で指定すれば、Pineスクリプトが自動で切り替えを処理する。"GMT+9"のような固定オフセット形式では夏時間に対応できないので、IANA形式を使うこと。
よくあるミスと対処法
ミス①: hour変数を直接使って時間判定する。チャートのタイムゾーン設定に依存するため、設定が変わるとズレる。time()関数またはhour(time, "タイムゾーン")を使う。
ミス②: UTC+9を手動で加算する。hour + 9のような計算は夏時間のある市場で破綻する。IANA形式のタイムゾーン指定を使えば自動で処理される。
ミス③: セッション文字列のフォーマットミス。"9:00-15:00"はエラーになる。正しくは"0900-1500"(コロンなし、4桁ゼロ埋め)。
ミス④: 日足以上の時間足でセッション判定する。日足は1日1本なので、セッション内かどうかの判定は意味をなさない。セッション判定は4時間足以下で使うのが前提だ。
ミス⑤: 曜日指定を忘れる。FX市場は土日休みだが、仮想通貨は24時間365日動いている。対象市場に応じて":23456"(平日のみ)を付けるかどうかを判断する。
まとめ
Pineスクリプトで時間指定するなら、time()関数+セッション文字列+IANAタイムゾーンの3点セットが鉄板だ。hour変数の手動オフセット計算は避ける。この方法なら、チャートのタイムゾーン設定に依存せず、夏時間にも自動対応する。
セッション文字列は"HHMM-HHMM"のシンプルなフォーマット。曜日制限は":23456"。複数セッションはカンマで結合。この3つのルールだけ覚えれば、あらゆる時間帯指定に対応できる。
















