Pineスクリプト入門 3 ストラテジーコードを一緒に読み解く

Pine Script入門

Pineスクリプト入門記事第3弾です。

前回はPineスクリプト周りのTrading viewの使い方について説明しました。


今回はいよいよPineスクリプトの内容に入っていきます。

Pineスクリプトを触ったことがないところから急に作ってみましょうといってもハードルが高いと思います。

なので今回は「空のストラテジー」を開いたときに表示されるサンプルコードを一緒に読み解いていきましょう。
「空のストラテジー」の開き方は前回記事でご説明してますのでそちらを参照ください。

スポンサーリンク

ストラテジーコード

さっそくストラテジーコードを見ていきましょう。

こちらが今回見ていくストラテジーのサンプルコードです。

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © loGieBlog

//@version=4
strategy("マイストラテジー", overlay=true)

longCondition = crossover(sma(close, 14), sma(close, 28))
if (longCondition)
    strategy.entry("My Long Entry Id", strategy.long)

shortCondition = crossunder(sma(close, 14), sma(close, 28))
if (shortCondition)
    strategy.entry("My Short Entry Id", strategy.short)


この内容を細かく分けてそれぞれの意味について解説していきながら進めていきます。

1〜4行目

// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © logieBlog

//@version=4

まず1〜4行目について見ていきます。

入門1でも説明しましたように、ここはコメントになっているので実際になにか処理が実行されるということはありません。


ちなみに1行目と2行目はライセンスと著作権に関する記述です。

4行目はPineスクリプトのバージョン4を使うことを宣言しています。
バージョン3などの以前のバージョンも指定できるようですが特にこだわりがなければ自分で何か作るときもバージョン4を設定した方がいいと思います。

7行目

左辺

longCondition = crossover(sma(close, 14), sma(close, 28))

次に7行目について見ていきます。
この行から実際に処理が実行されます。

7〜9行目が今回の山場、特にこの7行目が一番の挫折ポイントだと思うので少し気合をいれて頑張りましょう。


この行では longCondition という変数を定義しています。

ここでは longCondition に右辺のcrossoverメソッドの結果を代入してます。

復習
・変数を定義するというのは「この変数名で右辺の値を入れて使います」と宣言すること
・メソッドとは処理をまとめたもの

右辺

では右辺を見ていきましょう。

少し複雑な形をしていますが大丈夫です。
分解して考えれば初学者でも理解できますので、ゆっくり見ていきましょう。


右辺を理解するのに必要なポイントは2つです。

  1. メソッドに引数が定義されている場合、メソッドを呼び出す時に引数(インプットとなるデータ)を設定する必要がある
  2. メソッドに戻り値がある場合、メソッドを呼び出して処理されるとそこが戻り値のデータに置き換わる

それぞれ説明します。

1. メソッドに引数が定義されている場合、呼び出す時に引数を設定する必要がある

1つめの「メソッドに引数が定義されている場合、メソッドを呼び出す時に引数(インプットとなるデータ)を設定する必要がある」という点について説明します。

入門1でも説明しましたようにメソッドが引数を受け取るように定義されている場合、メソッドを呼び出す時に引数を設定する必要があります。

引数とは処理をするにあたってインプットとなるデータのことで、このように渡すことができます。

method(hikisuu1, hikisuu2, hikisuu3)


サンプルコードに話を戻します。

右辺の crossover(〜〜) と sma(〜〜) はどちらもTrading viewが用意してくれているメソッドです。

そして crossover も sma もどちらも引数が定義されています。
メソッドにどんな引数が定義されているか、他にどんな変数やメソッドが用意されているかについてはドキュメントに書いてあるので興味のある人は見てみてください。
(読み方については記事の最後に書いてます)


例えば sma はその名の通りSMAを計算してくれるメソッドなのですが、定義は下のようになっていて、SMAを計算する時の「価格データを何にするか」と「計算する期間」を引数として渡す必要があります。

sma(source, length)

右辺の1つめのsmaの場合は source に close(終値)、length に 14 を設定しているので、14期間の終値でSMAを計算してくれます。
同じように2つめのsmaは28期間の終値でSMAを計算してくれます。

復習
・メソッドに引数が定義されている場合、引数を設定する必要がある

2. メソッドに戻り値がある場合、メソッドが処理されるとそこが戻り値に置き換わる

では crossover の引数はどうなっているでしょうか。
ここで2つめのポイントである「メソッドに戻り値がある場合、メソッドを呼び出して処理されるとそこ戻り値のデータに置き換わる」ということについて説明します。


戻り値が何か覚えていますか?

戻り値とはメソッドが何かしら処理をして出た結果を、メソッドを呼び出したところに返す値のことです。

  引数(インプット) -> 処理 -> 戻り値(アウトプット)

先ほどのsmaメソッドでいえば14期間の終値でSMAを計算してくれますが、その計算結果を呼び出し元(7行目)に返します。

つまりsmaメソッドの場合、戻り値はSMAの計算結果ということです。


このメソッドが呼び出し元に戻り値を返すというのが、2つめのポイントである「メソッドが処理されるとそこが戻り値のデータに置き換わる」ということです。

なのでもし14期間SMAの計算結果が1700円で、28期間SMAの計算結果が2000円だった場合はsmaメソッドの処理前後で下のようになります。

# smaメソッド処理前
crossover(sma(close, 14), sma(close, 28))
↓
# smaメソッド処理後
crossover(1700, 2000)

右辺の謎も解けてきましたね。
このように整理すると2つのsmaメソッドはcrossoverメソッドの引数に設定されていたということがわかります。

ちなみに crossover メソッドの定義は下のようになっていて、x の値が y の値を上回った(ゴールデンクロス)ときに true を返し、それ以外は false を返すという処理をしてくれます。

crossover(x, y)

なのでゴールデンクロスした時の7行目は最終的にこのようになります。

longCondition = true


7行目の処理内容をまとめると、
「14期間SMAが28期間SMAに対してゴールデンクロスした場合は変数 longCondition に true を入れ、それ以外の場合は false を入れる」ということになります。

・メソッドに戻り値がある場合、メソッドが処理されると戻り値のデータに置き換わる

8〜9行目

if (longCondition)
    strategy.entry("My Long Entry Id", strategy.long)

少し7行目が長くなってしまったので疲れてしまった人もいるかもしれません。
このセクションに入る前に一度休憩を入れてもいいと思います。


次の8〜9行目が終わればほぼ終わりなのでもう一踏ん張り頑張っていきましょう。

8行目

まずは8行目です。

8〜9行目ではif文という書き方が使われています。if文の書き方はこちらです。

if 条件式1 (ex. name == "太郎")
    条件式1がtrueだった時に実行したい処理 (ex. gender = "男")
    うんたら
else if 条件式2 (ex. name == "花子")
    条件式2がtrueだった時に実行したい処理 (ex. gender = "女")
    かんたら
else
    条件式1にも2にもあてはまらない時に実行したい処理 (ex. gender = "-")
# if文終了

if文は条件に当てはまる場合にだけ実行したい処理がある時に使います。
if の後に処理を分岐させるための条件を記述します。

条件式は処理した最終結果が論理値になる必要があります。下に例を書いてます。
条件式には and や or をつけて複数の条件を組み合わせることもできます。

# OK
if age == 10
if true
if price <= 100000 and (maker == "hp" or maker == "NEC")

# NG
if "サンプル" # 文字列型だからダメ
if "true" # true だけど文字列型だからダメ
if 5 # 整数型だからダメ
if fish == "Tuna" and 3.5 # and の前は論理値だけど後ろは整数型だからダメ

条件式の結果が true ならインデントされた(TAB文字を入れて書かれた)処理が実行され、false ならスキップされます。

else if は複数の条件分岐をしたい時に使います。
基本的には if と同じですが注意点としてその前のifで true になっている場合、その後のelse ifで true になっても処理は実行されません。

else はそれまでの if と else if で true にならなかった場合に実行される処理を書きます。

else if と else は省略可能なので、8〜9行目のように if のみで書くこともできます。


if文がわかったところで8行目を見ると、条件式の部分には longCondition が指定されています。

longCondition は7行目で見たようにゴールデンクロスした時にのみ true が入るようになっています。
なのでこのif文はゴールデンクロスした時にif文の中の処理を実行するということになります。

・if文を使うことで条件によって違う処理を書ける
・if文の条件式は処理した最終結果が論理値になる必要がある
・if文内の処理はインデントして書く


次に9行目の処理内容を見ていきます。

strategy.entry(~~~) も sma などと同様に用意されたメソッドで、買い/売りを注文するメソッドです。
今回も定義をのせておきます。

strategy.entry(id, long, qty, limit, stop, oca_name, oca_type, comment, when, alert_message)

今回は引数がたくさんあって大変そうに見えますが、sma や crossover と違って全ての引数を指定する必要はなく、必須の引数は id と long のみです。
主な引数だけピックアップして紹介します。

  • id:必須。注文をキャンセルしたりする時に指定するための注文ID。
  • long:必須。true または strategy.long を指定すれば買い、false または strategy.short を指定すれば売り注文を出す。
  • qty:オプション。注文数を指定。
  • limit:オプション。注文の指値価格を指定。
  • stop:オプション。注文の逆指値価格を指定。

9行目のコードを見ると long に strategy.long を指定しているので買い注文を行っているとわかります。


ここまでの7〜9行目の処理内容をまとめると、
「14期間SMAが28期間SMAをゴールデンクロスした時に買い注文を入れる処理」ということになります。


ここまで読めたあなたなら11〜13行目は簡単だと思いますのでラストスパート頑張りましょう。

11〜13行目

shortCondition = crossunder(sma(close, 14), sma(close, 28))
if (shortCondition)
    strategy.entry("My Short Entry Id", strategy.short)

このコードを見れば分かる通り11〜13行目は7〜9行目とかなり似てます。
力試しにこれらの処理が何をしていてどんな引数を指定しているからどういう処理になるのか考えてみてもいいかもしれません。

自力で考えてみる人の参考に各メソッドのドキュメントだけ置いておきます。
ドキュメントの読み方はこの後に書いてますのでそちらを読んでから、ドキュメントを参考に考えるのも勉強になると思います。

.
.
.
.
.
.
.
.

では解説していきます。といってもほとんど解説する内容もありません。

7〜9行目との一番の違いは11行目が crossunder メソッドになっていることですね。
crossunder メソッドの定義はこちらです。

crossunder(x, y)

名前からなんとなく察した人もいるかもしれませんが、これは crossover メソッドの逆で x が y を下抜いた時(デッドクロス)に true を返すメソッドです。
なので変数 shortCondition にはデッドクロス時に true 、それ以外では false が入ります

12行目のif文の条件式には shortCondition が指定されているのでデッドクロスした時にインデント内の処理が実行されることがわかります。

13行目の strategy.entry は9行目と同じメソッドですが、よく見ると引数が少し違いますね。
引数 id は注文キャンセルする時に使う注文のIDなのでスルーでOKです。

引数 long には strategy.short が指定されています。
先ほどの引数の説明にもあったように long に false または strategy.short が指定されている場合、売り注文を出します。


なので11〜13行目の処理内容をまとめると、
「14期間SMAが28期間SMAをデッドクロスした時に売り注文を出す処理」ということになります。

自力で考えてみた皆さんどうでしたか?自力で読めましたか?

終わりに

今回はみなさんと一緒にストラテジーのサンプルコードを読んでみました。
プログラミング初心者の人でもわかるようにできるだけ噛み砕いて細かく説明したのでかなり長くなってしまいましたが。。

この記事を読んで「もしかしたら自分にもPineスクリプトできそうかも」と思ってもらえたら嬉しいです。

次の第4回ではRSIメソッドを使って一緒に簡単なストラテジーを作っていくような内容にしたいと思います。

では最後にこの記事で出てきたポイントをまとめます。

復習まとめ
[ 変数 ]
・変数を定義するというのは「この変数名で右辺の値を入れて使います」と宣言すること
[ メソッド ]
・メソッドとは処理をまとめたもの
・メソッドに引数が定義されている場合、引数を設定する必要がある

ポイントまとめ
[ メソッド ]
・メソッドに戻り値がある場合、メソッドが処理されると戻り値のデータに置き換わる
[ if文 ]
・if文を使うことで条件によって違う処理を書ける
・if文の条件式は処理した最終結果が論理値になる必要がある
・if文内の処理はインデントして書く


またこちらの記事では今回一緒に読み解いたMAのゴールデンクロス・デッドクロスストラテジーを Quant Zone を使って自動売買Botとして作ってみたので合わせて読んでみてください。


記事としてなにか取り上げて欲しいトピックやPineスクリプトでわからないところ等ありましたら質問箱に投稿してもらえたらと思います。

匿名で聞けちゃう!けいと@独学エンジニアさんの質問箱です
3年目エンジニア🖥 Go言語で実装した自動売買Bot稼働💰💰 今はブログ制作中 #ブログ制作ダイアリー #セルフ辞書


今回はここまでです。お疲れ様でした。


補足:ドキュメントの読み方

補足としてドキュメントの読み方について説明します。

一人で書くには必要な能力ですが、初心者には少しハードルが高いと思いますので少しずつ慣れてもらうのがいいと思います。

今回は strategy.entry メソッドを例に読んでいきます。

上から見ていきます。

1番はメソッドの説明です。
どんな処理をするメソッドなのか、どういう使い方をするのかについての概要が書かれています。

2番はメソッドの定義です。
括弧内に 引数 を、-> の後に 戻り値 を示しています。
ちなみに strategy.entry の戻り値に書いてある void というのは戻り値なしを意味する言葉です。

3番は実際にこのメソッドを使う時の記述例を示しています。
はじめはドキュメントや定義を見てもどう書けばいいのかわからないと思いますのでここを参考にしてみてください。

4番は引数の説明です。
ここではその引数がなにに使われるデータか、なにを指定するものかということが説明されています。
また本文で id と long だけが必須の引数と説明しましたが、それはこの引数説明欄に書かれています。

今回の strategy.entry には戻り値の説明欄がありませんでしたが、4番の引数と同じような記述になっています。


以上でざっくりとですがドキュメントの見方を説明しました。

急に読もうとしてもわけがわからないと思いますので、入門記事で出てきたメソッドの説明を読んだ後に少しドキュメントを眺めてみてちょっとずつ読めるようになっていきましょう。

コメント

  1. 匿名 より:

    初学者に対してとてもわかりやすい説明で助かりました。

タイトルとURLをコピーしました