「TradingView」のインジケーターを自作する ~ ①移動平均線を3本同時表示する
Pineスクリプト® 言語リファレンスマニュアル
何が作りたいのか?
ある期間の出来高の平均値と当該出来高を比較してその増減率を描画したい
具体的には
過去5日間で
日経平均が上昇した日の出来高÷過去20日間の出来高平均 ー 日経平均が下落した日の出来高÷過去20日間の出来高平均
※上昇した日はそれぞれ加算し、下落した日は減算する
よって算出する数値は
※数字は任意
①過去20日間の出来高の平均値を算出
日足の出来高平均と寄り付きからの出来高を表示
float DayVolumeMA = ta.sma(DayVolume, VolumeMALength)
// 日付変更のタイミングで日足出来高平均値を更新
dayvolume=ta.sma(volume,25)
plot(dayvolume)
②日経平均の終値前日比+の日の出来高を①で割る
③日経平均の終値前日比-の日の出来高を①で割る
④過去5日間の②ー③を合計
である。
なので描画されるのは④となる。
ゴールから逆算して考える
従って
plot(④, color=#2962FF)
ゼロになるところにラインを引いて分かりやすくする
hline(0, color = #787B86, title="Zero")
また、当該数値をパーセント表示にしたい
④ = 100 * (② - ③) / ④
②と③の定義をしなくてはならないが②は上昇日のみ③は下落日のみなのでここがめんどくさい
まず、上昇下落はおいておき出来高の平均をとるには
① = ta.sma(volume, length) lengthの部分はパラメータ設定で変更できるようにしたい
②を分解すると
(上昇日のみ出来高)を①で割る ということは
まず上昇日の出来高をupvolとする
参照期間は過去5日
だが、
rocという関数がある
roc(source, length) roc()
現在値とN本前の値との変化率(%)を取得するための関数 らしい
とはいえ、過去5日までの値なので
roc(volume, 1) 当日と前日になるが、volumeは現在の足なので、2としてしまうと2日前の出来高との差になってしまう。
取得したいのは結局
当日の出来高と前日の出来高の差
1日前の出来高と2日前の出来高
2日前と3日前
3日前と4日前
4日前と5日前
で、かつ日経平均が前日比で上昇した場合の差はプラス、下落した場合の差はマイナスとして合計する
加減乗除
過去の足のデータは”[ ]”で参照しよう
考え方としては
=当日出来高/1日前 なので
1day = (volume/volume[1])
2day = (volume[1]/volume[2])
3day = (volume[2]/volume[3])
2day = (volume[3]/volume[4])
2day = (volume[4]/volume[5])
だろうか?しかし、日経平均が前日比上昇した日はプラスで下落した日はマイナスにして計算するためにはそれを判定しなければならない
1day2dayから上昇下落を抽出するのではなく
前日比上昇日の出来高と前日比下落日の出来高と分けて抽出したほうが早そうだ
前日比下落の出来高はマイナスを付加し全部を合算
前日比上昇日下落日の出来高
Volume Ratio=(Vu+Vs / 2)/(Vu+Vd+Vs)×100
Vu:期間内株価上昇日の出来高合計
Vd:期間内株価下降日の出来高合計
Vs:期間内株価が前日比変わらずの日の出来高合計
//ボリュームレシオの書き方
//@version=4
study(title="Volume Ratio", overlay=false)
len = input(25, title="期間")
src = input(close, title="ソース")
vr = 100 * sum(change(src) > 0 ? volume : change(src) == 0 ? volume/2 : 0, len) / sum(volume, len)
plot(vr)
いずれにしろ
当日と前日
前日と前々日 。。。のように比較して上昇と下落を区別してその日の出来高を取得しなければならない
1day = (close/close[1])
2day = (close[1]/close[2])
3day = (close[2]/close[3])
2day = (close[3]/close[4])
2day = (close[4]/close[5])
考え方としてはこれで前日比の値を取得
その上で上昇した日の出来高と下落した日の出来高を取得するには、上昇した日を特定し(例えば3dayとか)3dayは要するに3日前なので3日前の出来高を取得ってめんどくさすぎるな(笑)
株価連続上昇日数/株価連続下落日数をチャートに自動表示してくれるTradingView用インジケーター
//@version=5
indicator("$TTOSample_ConsUpDn", overlay=true, max_labels_count=500)
over_counter_up = input.int(3, title="何回以上の連続上昇を表示するか?")
over_counter_down = input.int(3, title="何回以上の連続下落を表示するか?")
var counter_up = 0
var counter_down = 0
counter_up := 代入close > close[1] ? nz(counter_up[1]) + 1 : 0
counter_down := close < close[1] ? nz(counter_down[1]) + 1 : 0
なんで変数が変化しないのか
Pineは宣言されている変数はバーが変わる度にコードが上から再実行されると考えておく。
つまりバーが新しくなるたび n = 0 となるため nは+1しても1のままなのだ
if counter_up >= over_counter_up
label_counter = label.new(bar_index, high, style=label.style_none, size=size.huge, text=str.tostring(counter_up), textcolor=color.orange, yloc=yloc.abovebar)
if counter_down >= over_counter_down
label_counter = label.new(bar_index, low, style=label.style_none, size=size.huge, text=str.tostring(counter_down), textcolor=color.aqua, yloc=yloc.belowbar)
1日1日出来高差分と前日比を判定
いや、取得した出来高のうち、下落日の出来高差分のみマイナスを付け加えてやるほうがいいのか。とはいえ、日経平均の前日比マイナスを抽出しなければならないが。問題は当該マイナスの日の出来高差分をどう判定するのかという話になるのだが。
結局、1dayで出来高差分を取得し、日経平均前日比がマイナスだったらマイナスを付加と5日分繰り返してそれを合計するほうが早いのか。。
1dayvol = (volume/volume[1])
1dayprice = (close/close[1])
のような感じで
もしも1daypriceが<0だったら1dayvolにマイナスを付加して。。。合計みたいな
pineスクリプト条件分岐の話
どうしても条件分岐の話は避けて通れない。これはプログラミング言語を学ぶときにはついて回る。思うに、各プログラミング言語というはそのロジックの根底の部分は共通していて、書き方や使う文字、単語、用法などが違っているだけである。
語弊があるかもしれないが、英語とフランス語、イタリア語、みたいな違いかもしれない。基本的に文法構造が同じで単語も似ている。欧州人でよく何か国語もしゃべる事が出来てすごいですね~などと言われている人がいるが、博多弁と大阪弁と東京弁を喋る事ができるようなもんである(笑)
【Pineスクリプト道場】#6 条件分岐文(if文)によると条件分岐は3種類あるという。
特定の条件のときのみ処理を実施
特定の条件に当てはまらない場合には別の処理を実施
複数の条件が存在する場合
の3つらしい。要するに、ある条件に合致したら処理をするあるいはしないというふうに常に当該処理を行わせたくない場合に設定するものと言えそうだ。
まず、やりたい処理はなんなのかということになり、出来高差分を合計するということである。
このときに日経平均の終値価格が前日比マイナスの場合は当該出来高差分をマイナスして合計するということである。
これはまさしく条件であるが、他方で条件構文を使わずともこれをやろうと思えばやれそうな気もする。しかし、仮に前日比マイナスの出来高を特定し取得できたとしても最終的に出来高を合計する際にはその出来高をマイナスしなければならない。日経平均が前日比マイナスであっても出来高は増加している場合もあり、単純に計算すると全部プラスになってしまう。
今回のインジケーターの趣旨は出来高が直近の平均より増えている場合にそれが日経平均が上昇しているならプラス、下落しているならマイナスで表されるようにする、ということなので、出来高差分がプラスの場合は出来高が増加しているが、そのとき日経平均が下落しているのにプラスで加算してしまうとインジケーターそのものの数値はプラスになってしまう。
買い出来高と売り出来高
面白そうな記事発見
ティックデータには、
約定した時間
約定した金額
約定した数量
が含まれます。 約定した時間のBidとAskのどちらと約定した金額が等しいかを調べることで、 売りと買いのどちらの板が食われているかが判別可能です。
なるほど。とは言えティックデータには対応していないそうだ。
しかし、記事には続きがある。
買い出来高と売り出来高をそれぞれ「推測」して、それをプロットするインジケーターを作成
問題となるのは、価格の上昇に寄与したであろう出来高の推定をどう行うか
結局のところ上昇した(足)のみの出来高を抽出することはできないということか、な。いや多分できるだろう。
close > open で上昇日 条件をつければこの日の出来高を取得するはず 下落も同じだろう
また面白そうなの発見 クリンガーオシレーター:市場の脈動を明らかにする
それはおいておき、
相対ボリュームの算出法
相対ボリューム = 出来高 / 平均出来高
indicator("RelVol")
AvgVol = ta.sma(volume,10)
plot(volume/AvgVol[1], title="Relative Volume")
過去10本のバーでSMAを計算し、出来高をそのSMAで割ることで相対ボリュームが算出されます。
上昇下落の別を考慮しないのであれば勿論これで十分。
ta.sma(volume,10)のvolumeの部分に上昇日及び下落日のみの出来高を入れればとりあえずよいかな
移動平均線をpineでta.sma()
indicator("単純移動平均")
sum = close + close[1] + close[2] + close[3] + close[4] ave = sum/5
plot(ave, "average - 5", color = color.lime)で、これはトレーディングビューにある関数を使うと1文で書くことが出来ます。それが、「ta.sma()」関数
引数はta.sma(使う値,期間)
ボリュームレシオ(VR)|Trading Viewインジケーター
ボリュームレシオ(VR)は、一定期間における価格上昇時の出来高合計と価格下落時の出来高合計を百分率で算出した値
Volume Ratio=(Vu+Vs / 2)/(Vu+Vd+Vs)×100(上昇日出来高合計+変わらず日出来高合計 / 2)/(上昇+下落+変わらず)
Vu:期間内株価上昇日の出来高合計
Vd:期間内株価下降日の出来高合計
Vs:期間内株価が前日比変わらずの日の出来高合計
//ボリュームレシオの書き方
//@version=4
study(title="Volume Ratio", overlay=false)
len = input(25, title="期間")
src = input(close, title="ソース")
vr = 100 * sum(change(src) > 0 ? volume : change(src) == 0 ? volume/2 : 0, len) / sum(volume, len)
plot(vr)
※指定した値について、現在の値とN日前の値の差を計算します。
【計算方法】
価格 – 価格[n]
定義
change(source, length)※(length省略時は1)
なるほどsum(change(src) > 0 ? volumeはsrcが0より大きい場合に出来高を合計
srcにはcloseが代入されている
100 * sum(change(src) > 0 ? volume : change(src) == 0 ? volume/2 : 0, len)
なんか腑に落ちないが、とりあえず
出来高平均スクリプト
avvol = ta.sma(volume,20) で過去20期間の出来高平均がでる、はず
上昇日下落日出来高スクリプト
とりあえずこれで上昇日の出来高を取得できる、はず
src = input(close, title="ソース")
change(src) > 0 ? volume
下落日はこうなる、はず
change(src) < 0 ? volume
上昇日出来高から下落日出来高をマイナスして平均化するスクリプト
で、上昇日から下落日をマイナスし、その平均値を期間5の平均とする、でいいはず
が、この式がよく分からないな。。。
で次にこの平均をsmaで割ると。。。
やはりifを使った方が分かりやすいのかなというかそもそも分からんし(笑)
if change(src) > 0
upvol := volume/avvol
これで上昇日の出来高を出来高平均で割ることはできるものの、それを過去5期間のうちに上昇した日に限定せねばならない
むしろ上昇日の出来高をsumで合計するときに期間を5にするか
そうするとソースが上昇日の出来高になって上昇日の出来高を5回カウントするな。そうに違いない
そうすると考え方としては
if close > open
upvola:= volume/avvol
else if close < open
dwvola:= (volum/avvol)*-1
で1日目
if close[1] > open
upvolb:= volume/avvol
else if close[1] < open
dwvolb:= (volum/avvol)*-1
で2日目
みたいな感じで5日目まででどうだろうか
そして
upvola...
何を算出するのか忘れた(笑)
改めて確認
過去5日の上昇日の出来高を合算し下落日の出来高を合算したものをマイナスし、それを5日で割って平均化する
それを20日出来高平均で割って数値化する
めんどくさ
つーことは1回1回出来高平均で割ってもだめじゃん
if close > open
upvola:= volume/avvol
else if close < open
dwvola:= (volum/avvol)*-1
てな感じか
んで
upvol+...まで足して dwvol+...足したものを引く
それを20出来高平均で割ると
いや、なんか違うな(笑)
直近5日で買いが多いか売りが多いか、というのはそもそも分からないので相場上昇日の出来高を買い優勢、下落日の出来高を売り優勢と推測するので上昇日合計から下落日合計を差し引く
ただ差し引くだけだと単に買いが多いとか売りが多いとかしか分からない
出来高そのものが増加しているかどうかが分からなければならないから、差し引いたものを一旦平均化する
そうするとマイナスしている分平均値が低くでてしまう
例えば20日平均出来高が1万株で、上昇3日の合計出来高が5万株、下落2日の合計が1.5万株だと3.5万株を5日で割るので平均が0.7万株となるが、実際は1.3倍の出来高がある
こうなると直感的に買いが優勢だと分かりにくいので調整するために
過去5日の合計出来高を平均出来高×5で割ったもの1.3を0.7万株に乗じて0.91という数値にしてみる
なんかしっくりこない
例えば上昇が6万下落が6万だと差し引きゼロになるので出来高自体が増えていてもゼロになるが上昇6万で下落5万だと差し引き1万で平均0.2 20平均が1.5万だと0.13
いやまてよ
上昇出来高を下落出来高で割る 上昇出来高がゼロだとゼロになるだけか
あくまで直近5日の買いor売りがどれくらい強いのかを判別したいのでゼロ地点は拮抗していると考え、プラス側が大きくなれば買い優勢、マイナス側なら売り優勢というのが分かればいいのか
過去5日で上昇分4万下落分3万だとする
しかし上昇3日で平均1.3万で、下落2日で平均1.5万となって1日あたりでは下落日の出来高が大きい
4万-3万 差し引きをそのまま平均出来高で割るよりもやはり差し引きを5日平均して平均出来高で割るほうがよさそうだ
もしくは各出来高から平均出来高を差し引いた残りを合算、要するに1万になるそれを平均出来高×5日で割る 結局同じ(笑)
参考構文
相対ボリュームはどのように算出されますか?
Pineスクリプト(Pine Script)でボリンジャーバンドを作成する方法
出来高オシレータ
短期出来高MAから長期出来高MAを引いた値に対する長期出来高MAの比率が出来高オシレーターの値
//@version=5
indicator(title="Volume Oscillator", shorttitle="Volume Osc", format=format.percent, precision=2, timeframe="", timeframe_gaps=true)
var cumVol = 0.
cumVol += nz(volume)
if barstate.islast and cumVol == 0
runtime.error("No volume is provided by the data vendor.")
shortlen = input.int(5, minval=1, title = "Short Length")
longlen = input.int(10, minval=1, title = "Long Length")
short = ta.ema(volume, shortlen)
long = ta.ema(volume, longlen)
osc = 100 * (short - long) / long
hline(0, color = #787B86, title="Zero")
plot(osc, color=#2962FF)
- 投稿