こんにちは!スナフキンです.昨日チャネルブレイクアウト戦略botを投稿しましたが,ほぼ解説なしでコードをぶん投げた(すみません...笑)ので,プログラム初心者(ただしpythonの言語仕様が最低限分かる程度)の方にもbotを動かせるよう説明していきます.ただし,いっぺんにたくさんの文量を書くと疲れるので何日かに分けて解説します.今日はチャネルブレイクアウト戦略の説明と,純粋なチャネルブレイクアウト戦略を動かすためのパラメタ設定がテーマです.
チャネルブレイクアウト戦略とは何か
そもそもチャネルブレイクアウト戦略とは何かという話をしましょう.いわゆるテクニカル分析というものは価格が上昇するか,下降するかを予測しその予測をもとにトレードを行うためのものです.これまで状況に応じて価格を予測するために,様々なテクニカル指標が開発されてきました.(移動平均線,MACD,RSI...etc)基本的にテクニカル指標というのは価格データを何らかの数式に従って加工したものですが,チャネルブレイクアウト戦略は最も基本的な「価格データ」を使って将来の予測とトレードを行う戦略です.(注釈[1]参照)
具体的には次のようなルールで売買を行います.
- n期間高値を更新(ブレイクアウト)したら買いシグナル点灯,n期間安値を更新したら売りシグナル点灯.(ここで,期間高値・期間安値を決めるパラメタnは売り買いともに共通のものである.)
- 初回のエントリー以降は買いシグナル点灯,売りシグナル点灯のたびにドテン売買を行う.(最近有名なドテン君はこのロジックを採用しているのではないかと予測しています.)
これを2018/3/27のBitFlyerFX1分足で試すと次のようなバックテスト結果になります.
1日で187回トレードを行い,35000円程度の値幅を取っています.(ただし遅延やスリッページの影響が大きいため,1分足ではバックテスト通りの結果にはなりづらいです)
そして勝率は30%程度と低めで,いわゆる損小利大で最終的には勝つという戦略になります.チャネルブレイクアウト戦略と呼ばれる理由は,安値と高値のchannel(英語で水路・通路などの意味)を価格が上下のどちらかにbreakしたらシグナルが点灯するためです.
純粋なチャネルブレイクアウト戦略を動かすためのパラメタの設定
さて,ここまででチャネルブレイクアウト戦略の概要を説明したので,純粋なチャネルブレイクアウト戦略を先日のbotで動かすためのパラメタ設定を説明します.(全てChannelBreakOutクラスのインスタンス変数です)
- entryTermおよびcloseTermを同じ数字(好きな数字でよいが,数字によって結果が変わる)に設定する.
- rangeThとrangeTermをNoneに設定する.
- waitTermを0に設定する.
- バックテストを行う場合は成り行き注文のスリッページ値幅を自由にcostに設定する.
- candleTermに時間軸を設定する.(1分足なら1T,5分足なら5Tなど)
- その他のインスタンス変数はなんでもOK.

たとえば1分足で5期間高値・安値を用いるならこのように設定する
以上を行い,loop関数を回せば実際にBitFlyerで注文を行い,describeResult関数を回せばバックテストを行います.
本日の記事は以上になります.
今回は間に合わせのような記事で使用方法を書いただけですが,今後は本戦略の実装方法や弱点を補強するために行った実装についての解説記事(間に合わせではなくきちんとした「解説」)を書いていく予定です.ありがとうございました!
注釈
[1]トレードには複雑なテクニカル指標ではなく,シンプルで純粋な価格データを使うのが良いという主張があります.これは賛否両論ある意見だと思いますが,詳細については以下の書籍に説明がなされており,反論しづらい説明がなされています.ぼくにとっては良書でしたが,内容が資金管理法に偏っていたりややくどい節もあったりとくせの強い本です.(ので決して全ての人におすすめではありません)
コメント
はじめまして、最適化の項目はどのようなときに有効なのでしょうか?
最適化は今のところ手動に近い方法でやってます.for文で大体のあたりをつけた各パラメタを回しているので.本当はもっと良いやり方をしたいのですが,いずれ実装したら載せますね.
いつも拝見させていただいております。
まだまだプログラミングを始めたばかりの初心者で、色々と調べながらやっているのですが、「loop関数を回せば実際にBitFlyerで注文を行い,describeResult関数を回せばバックテストを行います.」
の方法が分からず困っています。
特にバックテストの方法です。
もしよろしければ、次のブログ更新時に詳しく記載していただけませんでしょうか?
よろしくお願い致します。
つまずいている部分がプログラム言語を学ぶいい題材なので,調べてみてください.キーワードは「クラス」「インスタンス化」「インスタンスメソッド」です.
ありがとう御座います。
357行目あたりのstart_timestamp = datetime.datetime(2018, あたりを変えてもどうもバックテストが直近から過去1日までしか遡れないのですが、範囲の変更はこちらであっていますでしょうか。
CryptoWatchの仕様で1日分ずつしか取れないようですね.何日分かのデータを使ってテストしたい場合は,for文で回してデータをつなげていくしかなさそうです.
記事の更新ありがとうございます。
動かせるようになり注文もできるようになりました!
本当に厚かましいとは思いますが細かい数値等のご説明もいただきたいです!
記事の更新楽しみにしています!
動いたということで良かったです!次回記事で少しずつ解説しますね.ありがとうございます.
設定次第では数値出せますね
以下バックテストを試した結果です。
=======
3/25
==========
Total pl: 42388JPY
The number of Trades: 16
The Winning percentage: 68.75%
The profitFactor: 4.926
The maximum Profit and Loss: 12002.0JPY, -4307.0JPY
3/26
==========
Total pl: 8233JPY
The number of Trades: 11
The Winning percentage: 63.64%
The profitFactor: 2.332
The maximum Profit and Loss: 5378.0JPY, -4333.0JPY
3/27
==========
Total pl: 22324JPY
The number of Trades: 13
The Winning percentage: 84.62%
The profitFactor: 12.079
The maximum Profit and Loss: 13000.0JPY, -1450.0JPY
3/28 22:59まで
==========
Total pl: 16810JPY
The number of Trades: 7
The Winning percentage: 71.43%
The profitFactor: 40.103
The maximum Profit and Loss: 13250.0JPY, -245.0JPY
※1分足、全てコスト1000円込
はじめまして。
素晴らしい記事、コードをありがとうございます。
Python学習中なのですが、以下のようなエラーが出てしまい解決できずにいます。
ライブラリを再インストールしたり、グーグルで調べながら思いつくことは試しているのですが原因がわかりません。
どのような原因が考えられますでしょうか?
よろしければアドバイスお願いします。
Traceback (most recent call last):
File “breakout.py”, line 836, in
channelBreakOut.describeResult(entryTerm=channelBreakOut.entryTerm, closeTerm=channelBreakOut.closeTerm, rangeTh=channelBreakOut.rangeTh, rangeTerm=channelBreakOut.rangeTerm, riginalWaitTerm=channelBreakOut.waitTerm, waitTh=channelBreakOut.waitTh, candleTerm=channelBreakOut.candleTerm,showFigure=True, cost=channelBreakOut.cost)
File “breakout.py”, line 360, in describeResult
candleStick = self.getSpecifiedCandlestick(number, “60”, start_timestamp, end_timestamp)
File “breakout.py”, line 703, in getSpecifiedCandlestick
length = len(row)
TypeError: object of type ‘NoneType’ has no len()
度々失礼します。
TypeError: object of type ‘NoneType’ has no len() の件、解決しました!
358行、359行(describeResult関数内)にある datetime の日付を最新や昨日の日付に変えることで動くようになりました。
Pythonでバックテストを行えることに感動しつつコードを読んでいます。
ありがとうございます。
クラビア様
お返事遅くなりました.Cryptowatchは5日前までしかデータをとれないようで,おそらくそれが原因でデータが取得できていなかったようです.初めてコードを動かすと感動しますよね.