TradingViewのPineスクリプト言語を利用してインジケーターやストラテジーを作成する方法

#インジケーターやストラテジーを作成する方法
##はじめに
売買ロジックの紹介はしていません。
作成の仕方についての解説のみになります。
記事内のコードを利用して投資する方は自己責任でお願いいたします。
##この記事の対象の方
- TradingViewを知っている方
- 言語は問わないが、最低限のプログラミング構文がわかる方(if文、関数、引数....)

##何故この記事を書いたのか？
普段はPythonメインでシステムトレードをしております。
TradingViewで実際にできることを知るまでは
自作の売買ロジックが、実際のトレードでどこまで使えるものなのか？を
貯蓄している価格データを元にテスト環境を一から構築し検証していたので大変でしたが、
少ないコード量で割と簡単に思っていることができたので
誰かの参考になればと、自分のメモを含め記事にしようと思います。

既にTradingViewを使ってる方はたくさんいらっしゃると思いますが、
TradingView内で実装できる特にPineスクリプト言語についての記事が
意外とが少ないと感じました。(私の調べ方が悪いのか......ww)

##Pineスクリプト言語
### Pineスクリプト言語とは
Pineスクリプトとは、TradingViewで使えるトレード専用の簡易的なプログラムのことです。
インジケーターを作成したり、既存インジケーターを利用した売買ロジック部分の作成、
実際に作成したロジックが有効なものかバックテストで確認したりすることができます。

[PINEスクリプト言語リファレンスマニュアル](https://jp.tradingview.com/pine-script-reference/)

>インジケーターとは、為替や仮想通貨等のデータ(価格や取引量など)を
有効だと思われる計算方法で加工しその結果を視覚的に見やすい形で
チャート上に描写し売買の判定に使おうというものです。
これをインジケーターもしくはテクニカル指標といいます。

　
>ストラテジーとは、インジケーターに売買サインなどを出す
プログラムのことを指します。
アルゴリズムに従って、バックテストやフォワードテストを
実行することができます。

###Pineスクリプトの基本構造
- デフォルトの`インジケータースクリプト`

```text:Pineエディタ
//@version=4
study("マイスクリプト")
plot(close)
```
- デフォルトの`ストラテジースクリプト`

```text:Pineエディタ
//@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行目でPineスクリプトのバージョンを指定します。
現在(執筆時)はバージョン４になります。
バージョンによっては記述方法が違ったりとありますが、
私は基本的には最新のものを使うようにしています。

- 2行目ではインジケーターかストラテジーかの定義をします。
インジケーターであれば`study関数`
ストラテジーなら`strategy関数`を定義します。
パラメーターには多くの種類があり、通常複数のパラメーターを渡すことが多いです。

例)　デフォルトの場合だと、必須のパラメーターである
インジケーターウィジェットに表示されるタイトル名を
`"タイトル名"`という形で第一引数に渡しています。
省略せずに書くとこのように記載されていることになります。
`study(title="マイスクリプト")`、
`strategy(title="マイストラテジー", overlay=true)`
そしてstrategy関数には、`overlay=true`というパラメーターも渡されており
チャート内で表示するか別チャート(サブウインドウ)で表示するかを設定します。
trueであればチャート内で表示するということになります。
ここでは他の引数の説明は、割愛しますがリファレンスに全てのっています。
[study( )関数](https://jp.tradingview.com/pine-script-reference/#fun_study)
[strategy( )関数](https://jp.tradingview.com/pine-script-reference/#fun_strategy)

- 3行目以降にそれぞれの内容を記述していきます。
ここからがメインの処理部分です。
デフォルトのコードについては解説していますが、
基本的には実現したいことに応じてリファレンスを見て実装する形になります。

例)　こちらもデフォルトのstudy関数の場合だと、
シンプルに終値のみをグラフで表示させるということになります。
strategy関数の場合だと、まず`sma関数`で
過去14日間の終値の単純移動平均(SMA 14 CLOSE)と
過去２８日間の終値の単純移動平均(SMA 28 CLOSE)を求めています。
その戻り値を引数に`crossover関数`を用いて
２つの移動平均線がクロスして下から上に抜けたのかを判定しています。
要は代表的な売買サインである`ゴールデンクロス`したかを判定しています。
`crossover関数`の戻り値(true or false)を
`変数longCondition`に代入し
`if文`で戻り値が**true**の場合(ゴールデンクロスした場合)は、
`strategy.entry関数`でポジションを持たせるように実行しています。
その際引数には、必須パラメーターの注文の識別子`"My Long Entry Id"`と
買い注文でエントリーを意味する`strategy.long(ビルトイン変数)`を渡しています。
よって買い注文でエントリーしてポジションを持たせるという意味になります。
`strategy.entry関数`実行時にはオプションパラメーターで、
指値注文や指値価格などを指定したりすることができます。

最後の3行に関しては、`crossunder関数`で`デッドクロス`を判定して、
`デッドクロス`した場合は、売り注文でエントリーしてポジションを持つという意味になり
反対の動作時のことをコーディングしています。
よって詳細については、繰り返しになるので割愛します。

ビルトイン変数
[close](https://jp.tradingview.com/pine-script-reference/#var_close)
[strategy.long](https://jp.tradingview.com/pine-script-reference/#var_strategy{dot}long)
[strategy.short](https://jp.tradingview.com/pine-script-reference/#var_strategy{dot}short)
ビルトイン関数
[plot( )関数](https://jp.tradingview.com/pine-script-reference/#fun_plot)
[sma( )関数](https://jp.tradingview.com/pine-script-reference/#fun_sma)
[crossover( )関数](https://jp.tradingview.com/pine-script-reference/#fun_crossover)
[crossunder( )関数](https://jp.tradingview.com/pine-script-reference/#fun_crossunder)
[strategy.entry( )関数](https://jp.tradingview.com/pine-script-reference/#fun_strategy{dot}entry)

##ストラテジー
###バックテスト期間の指定方法
```text:Pineエディタ
//@version=4
strategy("ChannelBreakOutStrategy", overlay=true)

length = input(title="Length", type=input.integer, minval=1, maxval=1000, defval=5)

//追記ここから
fromYear = input(title="From Year", type=input.integer, minval=2000, maxval=2100, defval=2020)
fromMonth = input(title="From Month", type=input.integer, minval=01, maxval=12, defval=01)
fromDay = input(title="From day", type=input.integer, minval=01, maxval=31, defval=01)
toYear = input(title="To Year", type=input.integer, minval=2000, maxval=2100, defval=2020)
toMonth = input(title="To Month", type=input.integer, minval=01, maxval=12, defval=01)
toDay = input(title="To day", type=input.integer, minval=01, maxval=31, defval=31)
startTime = timestamp(fromYear, fromMonth, fromDay, 00, 00)
endTime   = timestamp(toYear, toMonth, toDay, 00, 00)
testPeriod = startTime <= time and time <= endTime
bgcolor(testPeriod ? color.black : color.white, title="テスト期間")
//ここまで

upBound = highest(high, length)
downBound = lowest(low, length)

if (not na(close[length]) and testPeriod)
    strategy.entry("ChBrkLE", strategy.long, stop=upBound + syminfo.mintick, comment="ChBrkLE")
    strategy.entry("ChBrkSE", strategy.short, stop=downBound - syminfo.mintick, comment="ChBrkSE")

//plot(strategy.equity, title="equity", color=color.red, linewidth=2, style=plot.style_areabr)
```
コードはTradingView内蔵のストラテジーでチャネルブレイクアウト・ストラテジーを利用しています。
チャネルブレイクアウトとは、過去の安値高値を目安にエントリーポイントを決めていくシンプルな手法です。
コード通りなので簡単に解説すると、`input関数`でテスト期間の指定をできるようにしています。
その入力値を`timestamp関数`でUNIX時刻に変換し対象の期間を計算してから
`testPeriod変数`に格納しています。
最後にエントリー条件のチェックと合わせて確認しています。
`bgcolor関数`では、分かりやすいようにテスト対象期間の背景を塗りつぶしています。

デフォルトでは、時間軸に併せて遡れる所まで遡り自動でバックテストしてくれますが、
自身が想定している相場状況でロジックが本当に有効かなどの検証もよりしやすくなります。