Pineスクリプト入門 5 元祖ドテン君を作ってみる

Pine Script入門

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

前回はRSIを使った有名な手法をストラテジーとして作ってみました。

今回は仮想通貨界隈では有名なドテン君をPineスクリプトを使ってストラテジー化させてみたいと思います。

今回のポイントは 系列for文 です。

ぜひ一緒に手を動かしながら読み進めてもらえたらと思います。

スポンサーリンク

ドテン君

ドテン君とは

皆さんはドテン君をご存知でしょうか?

2018年3月から4月くらいにUKIさん(@blog_uki)やAKAGAMIさん(@akagami_channel)を中心として話題になったビットコインの自動売買Botの1つです。
UKIさんが元祖ドテン君を作り、1ヶ月で2000万円から1億円へと増やし、その後ドテン君の売買ロジックをTwitterで公開したことで一気に話題が広まりました。

その時のことをUKIさん自身がまとめた記事はこちらです。

その後AKAGAMIさんが類似Botとしてドテン君 AKAGAMI ver. を作り、多くの人が利用していました。

今回のこのドテン君をストラテジーとして作成していきます。

ドテン君のロジック

UKIさんが公開したドテン君の売買ロジックのツイートはこちらです。

オープニングレンジ・ブレイクアウト という手法のようで、丁寧な資料まで添付されています。

これをもとに手法整理すると以下になります。

買い条件

  • 現在の高値が (始値 +(直近5本の高値 – 安値の平均)× 1.6) を上回った時

売り条件

  • 現在の安値が(始値 -(直近5本の高値 – 安値の平均)× 1.6)を下回った時

ちなみにこの手法はドテン(買い->売り、売り->買い)しか行わないのでクローズロジックはありません。

今回のポイント

ストラテジー作成に入る前に今回作成する上でのポイントを見ていきます。

系列について

まずは系列についてです。

Pineスクリプト入門1のデータ型 のところでよく出てくる型は 文字列/整数/小数/論理値 と言いましたが、今回の系列はそれ以外のデータ型の1つです。

系列は過去のバーのデータが並んで入っているデータ型で、例えば close[1] とすると現在のバーの1本前の終値を取得することができます。
この系列によりPineスクリプト上で過去の価格データやそこから算出した値(SMAなど)を簡単に扱うことができます。

Pineスクリプトのドキュメント上では series[XXX] と記載されています。(例 SMAの戻り値
XXX は系列の中身のデータ型で float(小数) などが入ります。

ドテン君を作成するためには直近5本の高値と安値の値が必要なのでこの系列を使って作成します。

for文について

次はfor文についてです。

for文というのは繰り返し行う処理を実装するときに使う構文です。

for counter = 1 to 5
    処理の内容
    処理の内容
    処理の内容

上のように書くと中の処理の内容が5回繰り返し実行されます。

カウンター変数(上の例のcounter)には1回目の処理実行時には1が入り、2回目には2が入るようになっていますので、fo文内でその値を使うことができます。
このカウンター変数は i がよく使われます。

また今回は使いませんが、continue や break で処理の途中で次の繰り返しにスキップしたり、繰り返し処理を打ち切ることができます。

for文はif文と並んでよく使う構文の1つなので覚えておきましょう。

ストラテジー実装

それではストラテジー実装に入っていきます。
実装する内容は以下です。

  1. レンジ幅(高値 – 安値)の平均の計算
  2. エントリー処理

レンジ幅の平均の計算

最初にレンジ幅の平均の計算をしていきます。

過去の高値と安値はそれぞれ high[i] 、low[i] で取得できますので、このように書いても意図したレンジ幅を計算することはできます。

// レンジ幅の平均
range = (high[1] - low[1] + high[2] - low[2] + ... - low[5]) / 5

しかしこれではあまりに1文が長すぎて読みづらいですし、もし直近5本じゃなくて直近10本の場合の成績を見たいとなったら同じ長さの足し引きを書かなくてはいけません。

これではあまりに読みづらく、変更しづらいださいコードになってしまいます。


そこで先ほどのfor文を使って、期間を変更しやすいコードで書きたいと思います。

// calculate range wide
period = 5
sum = 0.0

for i = 1 to period
    sum := sum + (high[i] - low[i])

range = sum / period

解説すると、まず最初に過去何本分の価格データで計算するかという period 変数とfor文内で使う sum 変数を宣言しています。

次のfor文では1から period 変数(5)まで繰り返し処理を実行しています。
その中ではカウンター変数(i)を使って高値と安値の差分を sum 変数に足し込んでいます。
i は繰り返し回数によって 1 から 5 まで入っていくのでこのコードで直近5本分を計算できるというわけですね。

最後に足し込んだ sum 変数を期間で割ってあげることでレンジ幅の平均を計算することができます。

このコードであれば過去10本分にした時の成績を見たい場合、period に 10 を入れてあげるだけで済みます。


ここからさらに変更しやすくするにはinput関数を使います。

// calculate range wide
period = input(title="period", defval=5, type=input.float)
sum = 0.0

以下同じ

input関数は画面から変数に値を変えられるようにする関数です。

引数の内容はこのようになっています。

  • title:表記名
  • defval:初期値
  • type:入れる値のデータ型(type.floatやtype.integerなど頭に type をつける)
  • step:矢印ボタンで数値を変えるときに何単位で足し引きするか

ついでにrange変数宣言のあとに係数kもinput関数を使って宣言してあげるとレンジ計算の最終版はこのようになります。

// calculate range wide
period = input(title="period", defval=5, type=input.float)
sum = 0.0

for i = 1 to period
    sum := sum + (high[i] - low[i])

range = sum / period
k = input(title="k", defval=1.6, type=input.float, step=0.1)

期間と係数の変更はこんな感じになります。

エントリー処理

続いてエントリー処理を実装していきます。

といってもここまで入門3と入門4をやってきた皆さんなら瞬殺だと思います。

// entry logic
longCondition = high >= open + range * k
if (longCondition)
    strategy.entry("My Long Entry Id", strategy.long)

shortCondition = low >= open - range * k
if (shortCondition)
    strategy.entry("My Short Entry Id", strategy.short)

特に解説することもないですね。笑


これでドテン君のストラテジー作成完了です。
最後にコード全体を載せたいと思います。

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

//@version=4
strategy("Doten-kun", overlay=true)


// calculate range wide
period = input(title="period", defval=5, type=input.float)
sum = 0.0

for i = 1 to period
    sum := sum + (high[i] - low[i])

range = sum / period
k = input(title="k", defval=1.6, type=input.float, step=0.1)


// entry logic
longCondition = high >= open + range * k
if (longCondition)
    strategy.entry("My Long Entry Id", strategy.long)

shortCondition = low >= open - range * k
if (shortCondition)
    strategy.entry("My Short Entry Id", strategy.short)

ドテン君の成績

それでは作ったストラテジーをチャートに追加して、バックテストの結果を見てみましょう。

今回もアセットは bitFlyer の FXBTCJPY で時間足は2時間足で見ていきます。
利用可能なデータが2019年1月1日からだったので、そこからの成績となります。

めっちゃ負けてますね。。笑

ただ私が少し前に見た2018年の成績は序盤すごい利益を出していたので、恐らくその後元祖ドテン君の手法は通用しなくなったのでしょう。
UKIさん引き際も完ぺきです。

追記 2021/05/19

ソースコードにバグが。。。

この記事を読んでくださった方からコメントで「ショートの条件文の不等号が逆ではないか」とご指摘をいただき、確認してみたところたしかに逆になってしまっていました。。

# 誤り
shortCondition = low >= open - range * k

# 正しくは
shortCondition = low <= open - range * k


なので正しいソースコードは下記になります。

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

//@version=4
strategy("Doten-kun", overlay=true)


// calculate range wide
period = input(title="period", defval=5, type=input.float)
sum = 0.0

for i = 1 to period
    sum := sum + (high[i] - low[i])

range = sum / period
k = input(title="k", defval=1.6, type=input.float, step=0.1)


// entry logic
longCondition = high >= open + range * k
if (longCondition)
    strategy.entry("My Long Entry Id", strategy.long)

shortCondition = low <= open - range * k
if (shortCondition)
    strategy.entry("My Short Entry Id", strategy.short)

間違ったコードを載せてしまい、すいませんでした。

修正後のドテンくんの成績

コードを修正した上で改めてドテンくんの真の成績を確認したいと思います。


まずは前と同じく bitFlyer の FXBTCJPY で時間足は2時間足で見てみます。
利用可能なデータが前回と違い2020年1月1日になってしまっている点だけご留意ください。

成績のボラティリティがすごいですが、結果はバグを仕込んでしまっていた前回とは一転して、トータルで勝ってますね。


念の為、別の取引所での成績も確認しておきましょう。
こちらは当ブログが推しているFTXの BTCUSD での成績です。


こちらでもボラはすごいもののトータルで勝ってるので、ドテンくんはいまなお現役の売買ロジックと言えそうです。

「めっちゃ負けてますね。。」とか言ってすいませんでした!


成績のボラが大きいことに関してはそもそもドテンくんがトレンドフォロー系の手法なので、成績がコツコツドカンになってしまうのは当然とも言えます。


FTXでは Quant Zone という誰でも自動売買Botを作れるサービスを提供しているので、今回のドテンくんを実装してみるのもおもしろいかもしれません。

追記おわり。

おわりに

今回はUKIさんが作成した元祖ドテン君をPineスクリプトで作成してみました。

系列はPineスクリプトで価格データを扱う上では必ずと言っていいほど必要になってくる知識なので、今回でぜひマスターしてください。

またレンジ計算ではクソコードを例にfor文を使ってよりよいコードを書くということも体験してもらいました。
ただ動けばいいと言うのではなく検証するのに適したコードを意識してもらえたらと思います。


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

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


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

コメント

  1. rapneel より:

    こんにちは。
    Pineスクリプトの学習を兼ねて参考にさせていただきました。

    成績が悪いという点、ショートのエントリタイミングが明らかに不自然だったので確認したところ、ソースコードのshortConditionでの判定時は、 low <= open ~ の符号の誤りではないでしょうか?(記載のものと逆)
    符号を変えたところ期間やパラメタによっては良い成績になる場合も出てきました。
    もし勘違いでしたら申し訳ありません。

    • けいと より:

      rapneelさん
      コメントありがとうございます。
      コードを確認しましたところ、rapneelさんのおっしゃるとおりショートの条件式の不等号が逆になっていました。
      ご指摘本当にありがとうございます!この内容で本文や成績等修正します。

  2. […] Pineスクリプト入門 5 元祖ドテン君を作ってみるUKIさんが作り、ロジックを公開した元祖ドテン君をTrading viewのPineスクリプトでストラテジーを作成したいと思います。その中で系列とfor […]

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