見出し画像

TradingViewのfloat大小比較の残念な点とその修正方法(その2)


はじめに

TradingViewのfloat(浮動小数点数)の大小比較についての2回目です。
1回目はこの記事でfloatと0との比較を扱いました。

今回は0との比較に限定せず一般的な比較を扱います。例もcloseとその移動平均の比較という、よく出てくるものにします。

残念な動作

次の図では、JPYBTC(BTCJPYの逆数)の終値cを丸で、その移動平均smaを黒線で描画させています。

cがsmaより大きいかどうかで赤/青に色分けしたいなら、
c > sma ? color.red : color.blue
と書くと思いますが、smaより大きいと判定されるのは、赤丸だけです。大きいと判定されるのは、なぜか薄緑の帯より上のときだけなのです。移動平均より上で果敢に売ってしまうことになります。

赤丸のみが黒線の移動平均より大きいと判定される

一見同じ意味な気もしますが、
c < sma ? color.blue : color.red
と書いた場合、smaより小さいと判定されるのは、青丸だけです。小さいと判定されるのは、なぜか薄緑の帯より下のときだけなのです。移動平均より下で買うことになります。特に15:00からしばらく移動平均の下で買い続けてしまいます。

青丸のみが黒線の移動平均より小さいと判定される

誰でも結果を確認できるようにソースを公開します。
最初の例のソースは次のものです。
「cがsmaを上回れば強気」「cがsmaを下回れば弱気」とある行のコメントアウトを入れ替えると、2つ目の例のソースになります。

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © dig_dig_11

//@version=5
indicator("JPYBTC", precision=11)

c = 1 / request.security("BTCJPY", timeframe.period, close) // BTCJPYのcloseの逆数

sma = ta.sma(c, 10)

col = c > sma ? color.red : color.blue // cがsmaを上回れば強気
// col = c < sma ? color.blue : color.red  // cがsmaを下回れば弱気

plot(c, style=plot.style_line, linewidth=1, color=col)
plot(c, style=plot.style_circles, linewidth=3, color=col)

plot(sma, color=color.black)

p0 = plot(sma-1e-10, color=na)
p1 = plot(sma+1e-10, color=na)
fill(p0, p1, color=color.new(color.green, 80))

実は上の例のようにグラフで問題点がよく見えるのは、値が小さいときです。1に近い値だと影響は減ります。値が小さいときであっても上のような結果になるのはいやなので、どうにかして直したいです。

修正方法と修正結果

最初の例の修正では、前回作ったpositive(f)を使います。fが正の数かどうか(f>0かどうか)を表す関数です。

前回は f > 0 という判定を positive(f) に置き換えることで修正しました。
今回は c > sma という判定があります。c > sma は c - sma > 0 と同じはずなので、positive(c - sma) に置き換えればいいと予想できます。修正後のソースは次のものになります。

// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © dig_dig_11

//@version=5
indicator("JPYBTC fixed", precision=11)

c = 1 / request.security("BTCJPY", timeframe.period, close) // BTCJPYのcloseの逆数

sma = ta.sma(c, 10)

var pine_fixed_epsilon = 1e-10
positive(float f) => f > -pine_fixed_epsilon // f > 0 かどうか
negative(float f) => f < pine_fixed_epsilon // f < 0 かどうか

col = positive(c - sma) ? color.red : color.blue // cがsmaを上回れば強気
// col = negative(c - sma) ? color.blue : color.red  // cがsmaを下回れば弱気

plot(c, style=plot.style_line, linewidth=1, color=col)
plot(c, style=plot.style_circles, linewidth=3, color=col)

plot(sma, color=color.black)

p0 = plot(sma-1e-10, color=na)
p1 = plot(sma+1e-10, color=na)
fill(p0, p1, color=color.new(color.green, 80))

このソースを動かした結果は次の通りです。意図通り、黒線より上のときに赤丸になっています。

正しく赤丸が黒線の移動平均より大きいと判定される

2つ目の例の修正は、前回作ったnegative(f)を使います。fが負の数かどうか(f<0かどうか)を表す関数です。

前回は f < 0 という判定を negative(f) に置き換えることで修正しました。
今回は c < sma という判定があります。c < sma は c - sma < 0 と同じはずなので、negative(c - sma) に置き換えればいいと予想できます。上の修正ソースで、「cがsmaを上回れば強気」「cがsmaを下回れば弱気」とある行のコメントアウトを入れ替えると、残念な動作の2つ目の例を修正したものになります。

動かした結果は次の通りです。意図通り、黒線より下のときに青丸になっています。今回の修正後の例は2つとも同じ結果に見えます。黒線の真上に丸が来るのは珍しいことを考えると妥当な結果です。

正しく青丸が黒線の移動平均より小さいと判定される

おわりに

positive(f)、negative(f)を使った修正で、期待した動作になりました。めでたしめでたし。

前回も書きましたが、わんわんは中の人ではないので、推測で処置しただけです。TradingViewのPineがどう実現されているかを中から見れませんのではずれてるかもしれませんし、いつ仕様変更されるかも分かりません。

ここから先は

0字

メンバー特典記事、メンバー限定掲示板が、他のnoteメーンバーシップと同様にあります。 このメンバ…

スタンダードプラン

¥500 / 月
初月無料

プレミアムプラン

¥1,500 / 月

この記事が気に入ったらサポートをしてみませんか?