既刊のcci-signal-arrow-indicator.md等では、
矢印を出さないバーの値を、SetIndexEmptyValue()で指定した、
EMPTY_VALUEという数値で表してきました。
この記事では、Pine Scriptが同じ「値が無い状態」をどう表すか、
MQL4との違いを対比しながら解説します。
・既刊EMPTY_VALUE/SetIndexEmptyValue()のおさらい
・naという言語レベルの特別な値
・nz()で欠損値を置き換える方法
・v6でbool型がnaを持てなくなった変更点
既刊EMPTY_VALUEとPine Scriptのnaのおさらい
まず、MQL4側とPine Script側、それぞれの前提を振り返ります。
MQL4のEMPTY_VALUEの書式(おさらい)
SetIndexEmptyValue(0, EMPTY_VALUE); UpArrow[i] = EMPTY_VALUE; //この位置には矢印を描かない
バッファの該当する値をEMPTY_VALUEにしておくと、そのバーには何も描画されません。
Pine Scriptのna
float lastSignal = na
naは「値が決まっていない・無い」ことを表す、
Pine Script自体が持つ特別な値です。
EMPTY_VALUEとnaの一番の違い
EMPTY_VALUEは「とても大きい、普通あり得ない数値」
という、実はただのdouble型の値です。
naは、数値そのものではなく、言語レベルで「値が無い」ことを表す専用の状態です。
なぜMQLは特定の数値、Pine Scriptは専用の値を使うのか
同じ「値が無い」という状態でも、表現方法の前提が異なります。
MQL4: 「あり得ない数値」を目印にする設計
・EMPTY_VALUEの実体は非常に大きい数値(おおむね2147483647)
・チャート描画ソフト側が「この値は描画しない」と約束として扱う
・あくまで数値の一種であり、型としては普通のdoubleと同じ
Pine Script: 値そのものに「無い」状態を持たせる設計
naは数値でもbooleanでもなく、どの型の変数にも代入できる、
特別な「状態」として言語に組み込まれています。
比較演算の挙動の違い
・EMPTY_VALUEは普通の数値なので==で比較できる
・naは==で比較しても安定した結果にならないことがある
・naかどうかの判定には専用のna()関数を使う
naを判定・置き換えるna()とnz()
naを扱うための、2つの基本的な関数です。
| 関数 | 役割 | MQL4での相当処理 |
|---|---|---|
| na(value) | valueがnaかどうかをtrue/falseで返す | value == EMPTY_VALUEの比較 |
| nz(value) | naならゼロに、値があればそのまま返す | 自分でif文を書いて0に置き換える処理 |
| nz(value, repl) | naならreplに、値があればそのまま返す | 自分でif文を書いて任意の値に置き換える処理 |
na()でnaかどうかを判定する
if na(ma)
label.new(bar_index, close, "計算中")
計算対象の本数が足りずまだ値が出ていないバーを、na()で検出してラベルを出す例です。
nz()で欠損値を置き換える
safeMa = nz(ma, close)
maがnaの間はcloseの値で代用し、計算処理が途中で止まらないようにします。
MQL4で同じことをする場合
MQL4には専用の判定関数が無いため、
if(value == EMPTY_VALUE)のような比較を、
自分でコードに書く必要があります。
v6でbool型がnaを持てなくなった変更点
Pine Script v6で、na絡みの仕様に変更が入りました。
v5まではbool型の変数もnaになれた
これまでのバージョンでは、boolean型の変数にもnaを代入できていました。
v6ではbool型はtrue/falseのどちらかに固定
・v6ではbool型の変数はnaを持てない
・na()/nz()/fixnan()もbool型の引数を受け付けない
・v5時代のコードをv6へ移行する際は、bool変数へのna代入を削除する必要がある
MQL4のbool型は元からnaの概念を持たない
MQL4のbool型は常にtrueかfalseのどちらかで、
「値が無い」状態自体が存在しないため、
この変更はMQL4ユーザーにとってむしろ馴染みのある挙動です。
実際に動くPine Scriptのサンプルコード
計算対象の本数が足りない序盤のバーをna()で検出し、
nz()で安全に処理を続けるサンプルです。
//@version=6
indicator("NA Sample", overlay = true)
length = input.int(20, title = "期間", minval = 1)
ma = ta.sma(close, length)
if na(ma)
label.new(bar_index, close, "計算中", style = label.style_label_up, color = color.gray)
safeMa = nz(ma, close)
plot(safeMa, title = "安全化したMA", color = color.blue)
maがまだ計算できていない間はラベルで知らせ、
plot()にはnzで置き換えた安全な値を渡す設計です。
TradingViewでの貼り付け・実行手順
実際にTradingViewで動かすまでの手順です。
- TradingViewのチャート画面下部にある「Pineエディタ」タブを開く
- 新規スクリプトを作成し、上のコードを貼り付ける
- 「保存」してから「チャートに追加」をクリックする
- チャートの左端(表示本数が期間に満たない部分)に「計算中」ラベルが出ることを確認する
- それ以降のバーでは、安全化したMAの線が途切れずに表示されることを確認する
よくあるエラーと注意点
実装でつまずきやすいポイントをまとめます。
naのまま四則演算すると結果もnaになる
na + 1のような計算は、エラーにはならず、結果がそのままnaになります。
plot()にnaをそのまま渡すと、その点だけ描画されない
これはEMPTY_VALUEと同じ目的で使える挙動のため、
既刊の「矢印を出さないバーだけEMPTY_VALUEにする」パターンは、
naにそのまま置き換えて移植できます。
v5のコードでbool変数にnaを使っている箇所を見落とす
・古いサンプルコードをv6で動かす際によく出るエラーの1つ
・bool型のna代入を、tureまたはfalseの初期値に書き換える
・数値型
・文字列型のnaはv6でも変わらず使える
よくある質問
na値とnz()について、よく検索される疑問に回答します。
・plot()で点を出したくない位置には、EMPTY_VALUEの代わりにnaを渡す
・計算結果をそのまま使う前に、na()で欠損の可能性を確認する
・boolean型のna対応コードは、v6移行時に必ず見直す
nz()はゼロ以外の値に置き換えることもできますか?
できます。
nz(value, repl)のように第2引数を指定すると、
naだった場合にreplの値で置き換えられます。
fixnan()とnz()は何が違いますか?
nz()はその場でnaを置き換えますが、
fixnan()は直近の有効な値(naでなかった最後の値)を、
naの位置まで引き継いで埋める関数です。
MQL5にもEMPTY_VALUEと同じ仕組みはありますか?
あります。
MQL5のインジケーターバッファもMQL4と同じEMPTY_VALUEの考え方を使い、
PlotIndexSetDouble()のPLOT_EMPTY_VALUEで指定します。
【Pine Script入門】na値とnz()の扱いをMQLユーザー向けに解説してみた(EMPTY_VALUEとの比較):まとめ
Pine Scriptのnaは、MQL4のEMPTY_VALUEが「あり得ない数値」
という約束で表していた、「値が無い」状態を、言語レベルの専用の値として持たせたものです。
na()での判定・nz()での置き換え、
そしてv6でbool型がnaを持てなくなった変更点は、
MQL4のEMPTY_VALUEには無い、
Pine Script側で意識すべきポイントです。
コメント