初歩的な仮想通貨自動トレードPythonBOTを作成しながらプログラミングを学習しよう!

初歩的な仮想通貨自動トレードPythonBOTを作成しながらプログラミングを学習しよう!

仮想通貨の自動トレードPythonBOTの作成講座第二回です。
(関連:第一回 環境構築編

今回は、実際の簡易売買プログラムを作成するとともに、
プログラムに用いているPythonのご作法を詳しく解説していきます。

本記事を最後まで読めば、ある程度のプログラムを作れるようになるかと思います。

Pythonをより体型的に学びつつ、自動トレードBOT作成もやりたいという方には、
みんなのPythonをおすすめします。

トレードプログラムの概要

いかなる場合においても、どんなトレードを実施するプログラムにするかを検討する必要があります。

今回は、

  • MACDで初期取得ポジション決定
  • ショート時、MACDゴールデンクロスでドテンロング
  • ロング時、MACDデッドクロスでドテンショート

というロジックで作成してみます。

なお、本プログラムをそのまま使用しても利益がでることはまずないと考えてください。
おそらく、無限損益が発生します。

MACDとは?
Moving Average Convergence Divergence(移動平均収束拡散法)の略です。

2つの異なる期間(例えば、12日と26日)における価格の移動平均線の交差状態から売買の判断をするテクニカル指標です。
移動平均線にはEMA(Exponential Moving Average:指数平滑移動平均線)を用います。

EMAは単純な平均ではなく、至近の価格変動に重みを与えた平均です。

ゴールデンクロスとは、EMA短期間>長期間となった状態で「買い時」を示します。
デッドクロスとは、EMA短期間<長期間となった状態で「売り時」を示します。

その他の用語解説
【ショート】
「売り」のポジションを持つことをショートといいます。

【ロング】
「買い」のポジションを持つことをロングといいます。

【ドテン】
保有しているポジションを決済し、同時に逆のポジションを取得することをいいます。
ドテンロングといえば、ショート保有時にショートを決済し、
ロングにポジションチェンジすることを指します。

プログラムの作成

それでは、いよいよプログラムを作っていきましょう。
少しずつ書き足しながら解説します。

実行環境については、AWS(Cloud9)またはAnaconda3を想定しています。

先にプログラムの全貌が見たいという方は、本記事最後のコード全文を参照ください。

冒頭の記述(インポートするライブラリの設定)

まずは以下を記述してください。

冒頭の「#!/usr/bin/python3」はAWSにPython3のプログラムであることを知らせています。
Anacondaであれば不要です。

importとは?
Pythonに対応したライブラリを呼び出すコマンドです。
ライブラリとは、ある機能をソースコード上に記述することなく使用できるようにする拡張機能とお考え下さい。Pythonはソースコードを上から順番に読み込みますので、
全体にかかるimportコマンドは冒頭に記述必要があります。

今回は以下を使用します。

  • requests:WEB上のページからデータを取得する
  • talib:テクニカル指標を計算する
  • time:時間計測や表示を行う
  • ccxt:取引所での売買や情報表示を簡単な命令で行う
  • numpy:配列計算を効率的に行う

なお、「・・・as ・・・」との記述については、コード内での命令の省略を意味します。

例えば、talib を使う場合、本来「talib.EMA(—)」といった記述が必要になりますが、
talib as ta」とすることで、「ta.EMA(—)」と表記できるようになります。

APIの設定

BitMEXとTESTNETのAPIを設定します。
APIの取得がまだの方は、コチラを参照ください。

次のコードを追記します。

まず、BITMEX_TESTNET = Trueですが、これはブーリアン型変数といいます。
この記述が真(True)か偽(False)かを入力します。

変数そのものの意味については、次の変数と関数の定義にて詳しく説明します。

この記述は、以降のif文とあわせてBitMEXをTESTNETに繋ぐか、それとも本体サイトに繋ぐかを任意で決定します。ひとまず、安全のために「True」に設定しておきましょう。

if以降の記述ですが、ccxtを使ってBitMEXにアクセスする際に必要となるAPIキーと秘密鍵(secret)を入力します。IDとPasswordみたいなものです。

とりあえず、TESTNETのAPIキーとsecretだけ入れておけばOKです。

if文の意味については、後程詳細に解説しますが、ここでは

もしBITMEX_TESTNETが真(True)」なら、テストネットに接続し、
それ以外(BITMEX_TESTNETが偽(False))」なら、本体サイトに接続する

という意味になっています。

変数と関数の定義

次は以下の記述をしてください。

ここでは、プログラムの主要部で呼び出す変数の設定や関数の定義をしています。

変数とは?
AMT等は任意の名前に数値等を紐付けます。
例えば、あとでAMTと記述すれば、10が代入されるわけです。
これを変数といいます。今回は、

  • AMT:ポジション取得時の量
  • period:トレードに用いる時間足の設定=60分足
  • span:過去何本の足を使うか=30本=60分*30本のデータを使う

の3点を変数に設定しています。

関数とは?
関数(def…)を使うと、returnの内容を今後簡単に呼び出せるようになります。
本来、マーケット(成行)取引をする際、ccxtから
bitmex.create_order(‘BTC/USD’, type=’market’, side=side, amount=size)
を呼び出す必要があります。

そして、side(どのポジション?:buyかsellか)と、amount(どれだけ?:取引量)を入力します。

例えば、ロングで10取得するとしたら、
bitmex.create_order(‘BTC/USD’, type=’market’, side=’buy’, amount=10)
と記述する必要があります。

一方で、market(side,size)という関数を定義すると、この命令は、
market(‘buy’,10)という簡単な記述で済んでしまいます。

関数のカッコ内は、指定したい変数(sideとsize)を抜き出しているということです。
通貨ペアと成行注文(market)は変更する必要がないので省略しています。

プログラミングでは、コードの記述をスマートにすることも重要ですので、関数を使っていきましょう。

Advertisement

プログラムの主要部(ループ文)

いよいよ主要部に切り込んでいきます。
以下を追記します。

While文とは?
その名のとおり、繰り返し(ループ)文です。while以降の記述をループし続けます(While内の一番下まで行ったらWhileの冒頭に戻る)。
今回の場合、While Trueとしています。

これは、While内の文章にエラー等が起こらない(正しくループし続ける)限り、
永久にループさせるという意味です。

例えば、

としてやれば、5周したらループが終了するようになります。

potisionについては、現在の保有ポジションをBitMEXから取得するコマンドを代入しているだけです。

[0]はBitMEX内の記録状態(取引した順番に通貨データが保存される)。
例えば、BTC/USDペアを最初に取引していれば[0]。
先にETH/BTCペアで最初に取引し、次にBTC/USDペアで取引していれば[1]といった具合です。

[‘currentQty’]はBitMEXが提示する情報のうち、現在の保有ポジションを指定するコマンドです。

価格データの取得とテクニカル計算

価格データを取得し、そこからta-libを用いてテクニカル計算を実施します。

プログラムは以下。

色々出てきましたね。

まず、nowですが、これはライブラリ:timeから、現在の時刻を呼び出しています。
また、時間はUNIXTIMEで小数第7位まで表示されるため、roundを使って小数点以下を四捨五入します。

UNIXTIMEとは?
簡単にいえば協定世界時における1970年1月1日0時0分ジャストからの経過秒数です(厳密には違いますが)。
コンピュータの時刻表記でよく出てきます。

since_timeは、価格データを取得する際に「いつから」を指定するために定義しています。
現在時刻(UNIXTIME)から遡りたい時間を引いてあげればOKです。

period*spanは60分が何本必要という意味で、nowは秒なので、さらに60をかけています。
さらに、since_timeはミリ秒にする必要があるため、最後に1000をかけて桁を合わせます。

次のdata_sは、BitMEXにおける指定期間のohlcvデータを取得するコマンドになっています。

timaframeには取得する時間足(今回は1時間のため、1h)を、sinceにはいつからデータを取得するかを入力します。
sinceは先程設定したsince_timeでOKです。

ohlcvとは?
チャートを取得する際のセットで、以下の頭文字をとっています。

  • Open:始値
  • High:高値
  • Low:安値
  • Close:終値
  • Volume:出来高

今回はCloseを使って計算しています。

いち早く相場の動きを察知して取引する場合は、Openをキックにすると良いでしょう。

data_sで取得したohlcvデータは、ただの数字の羅列ですので、
これを計算できるようnp.arrayを用いて計算可能な配列に変換します。

その結果をdataとしています。

そしてcloseにて、ohlcvにおける「c」の要素だけ取り出しています。

[:,4]の「:」は「全てのデータ」をあわらし、「4」は「c」が何番目の要素かを指定しています。

ohlcv。なるほど、「c」は4つ目か。

違います。

4つ目をあらわすのが[4]というわけではないのです(わかりにくいですね)。
Pythonの配列は1つ目を[0]とするため、実際「c」は5つ目の数値となります。

理由は、BitMEXから取得するohlcvデータの一番最初には時刻が入るためです。
省略するなら、tohlcvということになりますね。

これで、Closeについて指定した全ての期間(since_timeからnowまで)抽出したことになります。

最後に、テクニカル計算です。

ema12と26は、各々先に述べたMACDのクロス判定に使います。
12や26の期間設定は様々です。最適化ポイントでもあるかもしれません。

ta.EMAでtalibのEMA計算機能を呼び出し、
(close,timeperiod = 26) でcloseを使って、「この期間でEMAを計算してね」という指令を出します。

これでテクニカル計算は完了です。

Advertisement

初期ポジションの取得とトレード

さてさて、大詰めです。

トレードの指令を出す記述を作っていきましょう。

流れは、

① 最初のif文でノーポジション時に新たなポジションを取得する
② ロングポジション保有時、MACDがデッドクロスでショートにドテン
③ ショートポジション保有時、MACDがゴールデンクロスでロングにドテン

となっています。

if文とは?
もし~だったら。まさにそれです。

if position == 0:は、positionが0に等しいとき、if 内の記述を実行します。

elif …は、if(あるいは前段のelif)に当てはまらない場合に判定され、条件があえば次の実行候補になります。

elseは、どれにも当てはまらない場合に実行する記述です。

もし〇〇ならこう(if)、〇〇でなくて△△ならこう(elif)、△△でもなく××ならこう(elif)、全部違えばこう(else)。

といった感じです。慣れれば簡単ですね。

さて、1つ目のifですが、positionが0の場合、さらに条件が分岐します。

・MACDが短期長期であれば、ロングポジションを取得
・MACDが短期長期であれば、ショートポジションを取得

ema12[-1]等の[-1]ですが、emaはリストという形を持つため、
リストの中の最後の値(最新の値)を取り出すよう記述しています。
最新から1つ前なら、[-2]となります。

リストとは?
複数の要素をまとめたオブジェクトです。
例えば、list=[0,1,2,3,4,5]とすると、listは0~5の整数が入ったリストとなります。

ここでは、常に最新のデータが追記されていくものだと考えてください。

ポジションの取得については、先程解説したとおり、冒頭で定義した関数を使っています。
AMTには10が代入されますので、10ドル分買うか売るかせよという命令になります。

そして、print文にて実行結果が表示されます。

print文とは?
メッセージを表示するコマンドです。
例えば、

print(‘Hello World!’)

とインプットすれば、

> Hello World!

というアウトプットが返ってきます。

if文の中等に入れれば、「今その条件が実行されている(された)んだな」というのがわかります。

elifは、ドテン、即ち現在のポジションを決済して反対にポジションを持つ条件を記述しています。
ここでは、逆のポジションにAMTを2倍とることで、ポジションが逆になるようになっています。

if、elifのどちらの条件も満たさない時は、elseに辿り着き、「ポジション維持」してますよという表示を返します。

そして最後に、time.sleep(10)で、プログラムを一旦停止させ、whileの直後に戻りループします。

time.sleep(10)は10秒停止を意味します。
これは、高頻度でBitMEXからデータを取ろうとすると、アクセス制限がかかるためです。
10秒入れておけばアクセス制限はないでしょう。

以上でテストプログラム完成です!

TESTNETでの売買模擬

プログラムを作成したら、BitMEX TESTNETで動かしてみましょう。

動かす前に、プログラムの以下の記述を確認してください。

  • BITMEX_TESTNETがTrueになっていること
  • BITMEX_TESTNETのapi,secretが入力されていること
設定を確認したら、実行してみましょう。

実行すると、「成行(ポジション)取得」が最初に表示され、
以降「ポジション維持」が次の取引タイミングまで周期的に表示され続けます。

これで、自動トレードデビュー完了です!

あとは、プログラムに改良を重ね、実践投入するのみです。

なお、ポジションエラーが出る場合は、BitMEXに取引の基礎情報が記録されていないためですので、一度手動で最小単位の取引をしてください。
例えば、1ドル分ロングをとって、すぐに売るといった感じでOKです。

実際のトレードをする場合

さて、改良も済んだら、いよいよ実戦になります。

実戦の設定も簡単です。

  • BITMEX_TESTNETがFalseになっていること
  • else以降のbitmexのapi,secretが入力されていること
APIキーの設定等については、以下関連記事を参照ください。

関連記事:第1回 プログラム作成の準備(環境構築・APIキー取得)

設定ができたら、実行するのみです。
また、TESTNETと同様にポジションエラーが出る場合は、先述のとおり対処してください。

【必要材料取得の簡易リンク】

今回のコード全文

コード全文をまとめておきます。今後の叩き台にどうぞ。

まとめ

今回は、簡単な仮想通貨トレードを行うPythonBOTを通して、
Pythonプログラミングの初歩を解説しました。

今後も、このようにプログラム例を提示しつつ、登場するPythonの命令文を解説してきます。

なお、体系的にPythonを学びたい!という方には、みんなのPythonが圧倒的におすすめです。
プログラムの初歩から、機械学習の走りまでカバーしています。

最後に、当ブログで紹介するプログラムについては、自己責任での使用をお願いします。
当ブログを利用することで発生したトラブルや損失、損害に対して、ブログ管理者は一切責任を負いませんので、ご了承ください。

↓応援よろしくお願いします!