Pine Script™ (v6) の覚書 - 作ってみる:labelの表示位置を自動調整する関数 (2)
前回までの話
ma_labelでは、x座標を常に最新のbarの位置(bar_index)に設定するため、チャートを過去(左)にスクロールするとラベルが表示されなくなる。
そこで今回は、最新足が表示されていない場合でもラベルが更新されチャート中心に表示される、new_ma_labelについて考えてみる。
new_ma_labelの作成
任意の座標に対するma値を取得できるようにする
まず、表示されているローソクのの左端と右端のx座標は、
で取得できる。
変数名が示す通りこの値はbar_timeなので、xloc=xloc.bar_timeを前提に、bar_timeから過去のma値(過去チャートにおけるラベルが表示されるべきy座標)を取得する必要がある。
ここでは、表示されているローソク足の中心のx座標にラベルを表示することを考えてみる。
var a_bar_time=array.new_int(na,na)//処理したローソクのx座標を記録するための配列(int)
var a_y=array.new_float(na,na)//処理したローソクのx座標時点のma値を記録するための配列(float)
if a_bar_time.size()>0 and a_bar_time.get(-1)==time
a_y.set(-1,y)
else
a_bar_time.push(time)
a_y.push(y)
これで、a_bar_time(bar_time)とa_y(ma値)という同じ長さの配列が用意できた。
次に、チャートの表示されている部分の中心を求めてみる。
center=int(math.avg(chart.left_visible_bar_time,chart.right_visible_bar_time))
しかし、本当に欲しいのは、チャートで表示されている左端と右端の中心の時間ではなくて、配列a_bar_time内のindexの中心なので、array.indexofを用いて以下となる。
center=int(math.avg(a_bar_time.indexof(chart.left_visible_bar_time),a_bar_time.indexof(chart.right_visible_bar_time)))
これで求めたcenterは、配列a_bar_timeのindexなので、同じ長さである配列a_yのcenter番目の要素がma値(y座標)となる。
label.style_label_leftは右端でないと成立しない(線にかぶる)ため、スタイルを変更する。
ラベルはなるべく邪魔にならない(ローソク足と被らない)場所に配置したいため、移動平均線が右肩上がり↗の場合には右下(label.style_label_upper_left)
に、移動平均線が右肩下がり↘の場合には右上((label.style_label_lower_left)に配置する。
線の傾きは、centerの前後のma値から判断する。
if a_y.size()>1
center=int(math.avg(a_bar_time.indexof(chart.left_visible_bar_time),a_bar_time.indexof(chart.right_visible_bar_time)))
l.set_xy(a_bar_time.get(center),a_y.get(center))
if a_y.get(center-1)<a_y.get(center+1)
l.set_style(label.style_label_upper_left)
else
l.set_style(label.style_label_lower_left)
ma_label→new_ma_labelへの拡張
ma_labelは以下のような引数であった(y座標、ラベル文字列、ラベル色、テキスト色、書体)。
ma_label(float y,string t,color c,color ct,int s,string f)=>
// 以下略
これをnew_ma_label()として書き直してみる。
new_ma_label(float y,string t,color c,color ct,int s,string f)=>
var l=label.new(na,na,t,xloc.bar_time,color=c,textcolor=ct,size=s,style=label.style_label_left)
var a_bar_time=array.new_int(na,na)
var a_y=array.new_float(na,na)
if a_bar_time.size()>0 and a_bar_time.get(-1)==time
a_y.set(-1,y)
else
a_bar_time.push(time)
a_y.push(y)
switch f
'bold'=>l.set_text_formatting(text.format_bold)
'italic'=>l.set_text_formatting(text.format_italic)
'bold+italic'=>l.set_text_formatting(text.format_bold+text.format_italic)
=>l.set_text_formatting(text.format_none) // デフォルトは format_none
if time==chart.right_visible_bar_time
l.set_style(label.style_label_left)
l.set_xy(time,y)
else
center=int(math.avg(a_bar_time.indexof(chart.left_visible_bar_time),a_bar_time.indexof(chart.right_visible_bar_time)))+offset
l.set_xy(a_bar_time.get(center),a_y.get(center))
if a_y.get(center-1)<a_y.get(center+1)
l.set_style(label.style_label_upper_left)
else
l.set_style(label.style_label_lower_left)
l
x座標の調整
実際には、どうもラベルが重なってしまうことと、上位時間軸に対しての価格比較が現在足の+-1では不十分(同値になる)ため、調整用にoffset値を追加してみる。
これを使って、中心から左(-)右(+)に何本分かずらしたほうが良さそうである。
new_ma_label(float y,string t,color c,color ct,int s,string f,int offset=0)=>
var l=label.new(na,na,t,xloc.bar_time,color=c,textcolor=ct,size=s,style=label.style_label_left)
var a_bar_time=array.new_int(na,na)
var a_y=array.new_float(na,na)
if a_bar_time.size()>0 and a_bar_time.get(-1)==time
a_y.set(-1,y)
else
a_bar_time.push(time)
a_y.push(y)
switch f
'bold'=>l.set_text_formatting(text.format_bold)
'italic'=>l.set_text_formatting(text.format_italic)
'bold+italic'=>l.set_text_formatting(text.format_bold+text.format_italic)
=>l.set_text_formatting(text.format_none)
if time==chart.right_visible_bar_time
l.set_style(label.style_label_left)
l.set_xy(time,y)
else
if a_y.size()>(1+offset)*2
center=int(math.avg(a_bar_time.indexof(chart.left_visible_bar_time),a_bar_time.indexof(chart.right_visible_bar_time)))+offset
l.set_xy(a_bar_time.get(center),a_y.get(center))
o=offset!=0?offset:1
if a_y.get(center)<a_y.get(center+o)
l.set_style(label.style_label_upper_left)
else
l.set_style(label.style_label_lower_left)
l
new_ma_labelを使ってみる
最後に、offsetの引数が追加された、new_ma_labelを使ってみる。
追加した引数offsetはデフォルト値を持つため省略可能であり、
ma_labelをnew_ma_labelに置き換えるだけで使い方は同じとなっている。
ラベルの重なりが気になる場合には、offsetを設定して調整ができる。
if useLCTF and not na(sma20)
new_ma_label(sma20,ctf+":20SMA",cLSMA,cLTSMA,sCTF,fCTF)
if useLHTF1 and not na(sma20_1)
new_ma_label(sma20_1,htf1+":20SMA",cLSMA,cLTSMA,sHTF1,fHTF1,8)
if useLHTF2 and not na(sma20_2)
new_ma_label(sma20_2,htf2+":20SMA",cLSMA,cLTSMA,sHTF2,fHTF2,16)
if useLCTF and not na(ema20)
new_ma_label(ema20,ctf+":20EMA",cLEMA,cLTEMA,sCTF,fCTF)
if useLHTF1 and not na(ema20_1)
new_ma_label(ema20_1,htf1+":20EMA",cLEMA,cLTEMA,sHTF1,fHTF1,8)
if useLHTF2 and not na(ema20_2)
new_ma_label(ema20_2,htf2+":20EMA",cLEMA,cLTEMA,sHTF2,fHTF2,16)
完成!
続く(記事追加)
今回作成したコード全文は下の有料部分で見ることが出来ます。
ご覧頂いている皆様の中に、私達の活動を支援して頂ける方がいらっしゃいましたら、有料部分をクリックやコメントをして頂けると記事執筆の励みとさせていただきます。
<注意>
以下の有料部分に記載されるコードの内容は全てこれまでの内容と同じで追加される情報はありません。これまでに書いてきたコードを一つにまとめたものです。ご注意ください。
コード全文
ここから先は
¥ 500
Amazonギフトカード5,000円分が当たる
よろしければ応援お願いします!