暗号資産(仮想通貨)取引の最も大きな特徴は「24時間365日取引可能」である点です。とりわけシステムトレードを行う上で全自動の自動売買が可能であれば、これほど適した市場は他にはありません。ここではRuby・Pythonプログラムのサンプルとともに、Coincheckでの暗号資産(仮想通貨)の自動売買方法を見てみましょう。
仮想通貨の自動売買の魅力
仮想通貨取引の特徴のひとつが「24時間365日」取引可能であるという点です。株式市場や為替市場であれば基本的に取引可能なのが平日のみですから、全自動で自動売買ができるのであれば仮想通貨市場はとても魅力的です。
また、仮想通貨といえば大きなボラティリティが特徴です。価格の変動こそが自動売買の利益の源泉となりますからボラティリティは重要です。これだけ短期間に価格が大きく動く資産はそう多くありません。
自動売買の仕組み
自動売買とは
ここでいう自動売買とは、システムが自動で売買指値を決め、注文から決済まで全てシステムが行い、人間が行うことはシステムのON・OFFのみという完全な自動売買です。
自動売買に必要なものといえば、
- 情報取得、売買注文を機械的に行える仕組み
- 売買ロジックの検証(バックテスト)が行える仕組み
が、欲しいところです。
「1」については、仮想通貨を取り扱う各業者が提供するAPIを利用することで解決できます。例えばCoincheckであれば、こちらにAPIのソースが記載されています。
「2」については、株式やFXでは多く存在していますが、仮想通貨ではあまり充実していない状況です。株価や為替は情報ベンダー(例えば日経平均なら日経やQuick社など)が価格情報を公開していますが、仮想通貨はそもそも業者ごとに価格が異なるので仕方ありません。
自動売買の考え方
実は自動売買プログラムは市販のものが提供されています。例えば「QUOREA」「コインネオ」が有名で、マイナーなものだと「マネコ」「CoinTrader」「CRYPTOTRADER」「bittrade24」「COIN FX 365(提供は終了)」などがあります。
ツール | コスト | 対応業者 | 通貨ペア | 特徴 | 評価 |
---|---|---|---|---|---|
QUOREA | 無料 | Liquid・Zaif | BTC | リスクとリターンの予想値が可視化 でき、独自ボット作成が可能 | |
コインネオ | 3万円/月 | bitFlyer・Liquid・ Coincheck・Zaif・ bitbank・BTCBOX | BTC | AI活用型の裁定取引がメイン | |
マネコ | 無料 | Liquid | BTC・ ETH | 優秀なトレーダーをフォロー する形で取引する(提供終了) | |
CoinTrader | 1,200円〜/月 | 38ヶ所 | 2,500以上 | 対応取引所・対応通貨ペアが国内最大 | |
CRYPTOTRADER | 0.0024BTC〜/月 | 13ヶ所 | 1,000以上 | 海外の自動売買プラットフォーム | |
bittrade24 | 26万円 ※購入 | bitFlyer・Liquid・ Coincheck | BTC | 仮想通貨の裁定取引ツール | |
COIN FX 365 | ー | ー | ー | (提供終了) |
しかし市販のプログラムは「使える仮想通貨の取引所・販売所がツールに対応しているところに限られる」「利用料が高額」「カスタムしにくい」などのデメリットが大きく、ここでは自前で作ることを考えていきましょう。
自動売買システムを作るにあたり、まずはどのようにイベントを起動するかを考えなければなりません。イベント起動とは、「どのようなトリガーでプログラムを動かすのか?」ということです。
ざっくりいうと、イベント起動の方法としては
- タスクスケジューラやcronを用い、プログラムを定期的に実行
- ループ処理をエンドレスに行い、処理を繰り返し実行
の2通りの実装方法があると思います。前者ではWindowsならタスクスケジューラを使えば簡単に実装できそうですが、自身の環境により利用可否が異なります。今回は後者のようにループ処理を延々と続ける方法で実装することを考えてみましょう。
自動売買ができる業者
上記を踏まえ、どの業者を使っていくか考えてみましょう。
まず国内業者でAPIを公開しているのは以下に挙げたものです。(BITPointは新規口座開設が停止)
業者 | 使える言語 | 日本語対応 |
---|---|---|
bitbank | Javascript, Java, Python, Ruby | ○ |
bitFlyer | Javascript, Java, Python, Ruby | ○ |
BITPoint | Javascript | × |
BTCBOX | Javascript | × |
Coincheck | Javascript, Java, Python, Ruby | ○ |
DeCurret | Javascript, Python, Ruby | × |
GMOコイン | Javascript | × |
Huobi Japan | Javascript | × |
Liquid by FTX | Javascript, Python, Ruby | × |
Zaif Exchange | Javascript | × |
さて、自動売買を行う上で考えておきたいのが、取引コストです。自動売買では、少額の利益を取引回数によって積み上げていく戦略を取ることになります。必然的に取引回数が多くなりますから、より取引コストが低い方法を採用することになります。
ここでは取引コストが事実上存在しない、Coincheckのビットコイン現物の取引所取引を考えていきましょう。レバレッジ取引では建玉手数料が1日のポジション保有でも無視できず、取引のたびに取引手数料がかからない(Maker/Taker手数料が0)である、ある程度の流動性が存在するという点を考慮した結果です。
現物取引なら建玉手数料はかかりません。Coincheckであれば取引手数料がかからない(Maker/Taker手数料が0)ですし、ビットコインならば現物で取引所取引が存在しある程度の取引量が存在するというメリットがあるからです。
Coincheckの口座をまだ開設していない方はこちらから申請することができます。

Coincheck自動売買の実装
APIキーの取得
まずはAPIキーを取得していきますが、その前にここまであまり説明していなかった点について説明しましょう。そもそもAPIにはPublic APIとPrivate APIの2種類があります。
Public APIとはアカウントに紐づかない、他の人も参照している情報を見るために利用するものです。例えば取引所の注文状況や公開されている取引の履歴、板情報などが該当します。
一方、Private APIとはアカウントなどに紐づく、自分しか見ることのできない情報を操作するために利用するものです。例えば取引所での新規注文や注文キャンセル、自分の残高などを確認することなどが該当します。
つまり自動売買のためには、Private APIを利用することが必要です。そのためには個人のアカウント画面からAPIキーを取得することが必要です。
CoincheckのAPIキー取得方法
APIキーは「アクセスキー」と「シークレットキー」の2つに分けられ、どちらも新たに取得する必要があります。
CoincheckでAPIキーの取得をしたことがない方はここから紹介するイメージを参考にしてみてください。以下のイメージは英語ですが、登録時に日本語登録していればちゃんと日本語で表示されますから安心してくださいね。
まず、ページ上部の「設定」をクリックします。一番右のSetteing(日本語では「設定」)です。

「設定」ページから、「APIキー」をクリックしましょう。

「新たにAPIキーを追加する」をクリックします。一番下の「Add another API key」のところです。

下記のようにAPIキーの権限にチェックをつけて選択します。日本語だと「新規注文」「未決済の注文一覧」「注文のキャンセル」「取引履歴」「残高」です。

必要な権限にチェックを入れたら、パスワードを入力して「OK」をクリックします。すると、以下の用に新しいAPIキーが表示されます。デフォルトではシークレットキーは表示が隠されています。

繰り返しますが、上記に表示されるAPIキーは「アクセスキー」ですので、「シークレットキー」はクリックして表示させてくださいね。
Ruby
まずは指値注文するためのスクリプトを書いてみましょう。
USER_KEYに取得した「アクセスキー」、USER_SECRET_KEYに取得した「シークレットキー」をセットしてください。
require 'ruby_coincheck_client' USER_KEY = "アクセスキー" USER_SECRET_KEY = "シークレットキー" BASE_URL = "https://coincheck.jp/" SSL_FLAG = true cc = CoincheckClient.new(USER_KEY, USER_SECRET_KEY, {base_url: BASE_URL, ssl: SSL_FLAG}) loop do response = cc.read_positions(status: "open") positions = JSON.parse(response.body)["data"] # step1 btc_jpy 595,000円で0.01BTCロング発注 if positions.empty? # ポジションがない場合 response = cc.create_orders(order_type: "leverage_buy", rate: 595000, amount: 0.01, market_buy_amount: nil, position_id: nil, pair: "btc_jpy") else # ポジションがある場合 # step2 step1のポジションを持っていたら600,000円で決済注文 response = cc.create_orders(order_type: "close_long", rate: 600000, amount: positions.first["amount"], market_buy_amount: nil, position_id: positions.first["id"], pair: "btc_jpy") # 1秒待機 sleep 1 end end
これを次のようにコンソールで実行することで、ビットコインに対し595,000円でロングを持ち、600,000円で決済(売却)することを繰り替えす自動売買ができます。
$ ruby first_trade.rb
停止させたくなったら「Ctrl-C」「Ctrl-B」「Ctrl-Break」「Ctrl-Alt-Del」「Esc」「Ctrl-Esc」などで抜け出します。または、Windowsであればタスクマネージャーを起動し「ruby.exe」のプロセスを終了すると良いでしょう。
いよいよボリンジャーバンドを使ったシステムを組んでみましょう。Coincheckのgemにはテクニカル分析を行うような機能はありません。別のライブラリ(例えばこちら)を探すまたは、自分で作ることになります。
以下はあくまでサンプルです。ボリンジャーバンドの正しい使い方をしておらず、この方法で取引をすることはおすすめしません。
require 'ruby_coincheck_client' require 'bigdecimal' require './technical_analysis_services/bollinger_band_service' USER_KEY = "your user key" USER_SECRET_KEY = "your secret_key" INTERVAL_TIME = 1 BASE_URL = "https://coincheck.jp/" SSL = true cc = CoincheckClient.new(USER_KEY, USER_SECRET_KEY, {base_url: BASE_URL, ssl: SSL}) bollinger_band_service = BollingerBandService.new() loop do # 現在のレートを確認 puts "count:#{count}" rate_res = cc.read_ticker btc_jpy_bid_rate = BigDecimal(JSON.parse(rate_res.body)['bid']) # 現在の買注文(bid) btc_jpy_ask_rate = BigDecimal(JSON.parse(rate_res.body)['ask']) # 現在の売注文(ask) btc_jpy_rate = (btc_jpy_bid_rate + btc_jpy_ask_rate)/2 bollinger_band_service.set_rate(rate: btc_jpy_rate) # ポジションの確認 response = cc.read_positions(status: "open") positions = JSON.parse(response.body)["data"] # 証拠金の確認 response = cc.read_leverage_balance margin_available = JSON.parse(response.body)['margin_available']['jpy'] if positions.empty? # ポジションがない場合 result = bollinger_band_service.check_signal_exec(btc_jpy_rate) # ボリンジャーから注文内容を決定 if [BollingerBandService::PLUS_SIGNAL_LV_3, BollingerBandService::MINUS_SIGNAL_LV_3].include?(result) if result == BollingerBandService::PLUS_SIGNAL_LV_3 # +2σを超えた場合、逆張りでショート order_rate = btc_jpy_bid_rate.to_i order_type = "leverage_sell" else # -2σを超えた場合、逆張りでロング order_rate = btc_jpy_ask_rate.to_i order_type = "leverage_buy" end order_amount = (margin_available / order_rate * 5).to_f.round(2) cc.create_orders(order_type: order_type, rate: order_rate, amount: order_amount, market_buy_amount: nil, position_id: nil, pair: "btc_jpy") end else open_rate = positions[0]["open_rate"] # 1.5%以上の含み益で利確 # -5.0%以下の含み損発生で損切り if positions[0]["side"] == "buy" gain_rate = (open_rate * 1.015).to_i loss_cut_rate = (open_rate * 0.95).to_i if gain_rate <= btc_jpy_ask_rate || loss_cut_rate>= btc_jpy_ask_rate # 現在の売り注文が利確金額以上なら利確 # 現在の売り注文が損切り金額以下なら損切り cc.create_orders(order_type: "close_long", rate: btc_jpy_ask_rate.to_i, amount: positions.first["amount"], market_buy_amount: nil, position_id: positions.first["id"], pair: "btc_jpy") end elsif positions[0]["side"] == "sell" gain_rate = (open_rate * 0.95).to_i loss_cut_rate = (open_rate * 1.015).to_i if gain_rate >= btc_jpy_bid_rate || loss_cut_rate <= btc_jpy_bid_rate # 現在の買い注文が利確金額以下なら利確 # 現在の買い注文が損切り金額以上なら損切り cc.create_orders(order_type: "close_short", rate: btc_jpy_bid_rate.to_i, amount: positions.first["amount"], market_buy_amount: nil, position_id: positions.first["id"], pair: "btc_jpy") end end end # INTERVAL_TIME秒だけ待機 sleep INTERVAL_TIME end
BollingerBandServiceについては以下を参照してください。
class BollingerBandService # データ不足 LACK_DATA = 0 PLUS_SIGNAL_LV_3 = 1 PLUS_SIGNAL_LV_2 = 2 PLUS_SIGNAL_LV_1 = 3 MINUS_SIGNAL_LV_1 = 4 MINUS_SIGNAL_LV_2 = 5 MINUS_SIGNAL_LV_3 = 6 def initialize @rates = [] @average_rates = [] @range = 0 # 平均 @avg = 0 @plus_one_std_dev = 0 @minus_one_std_dev = 0 @plus_two_std_dev = 0 @minus_two_std_dev = 0 end def set_rate(rate:) @rates.push(rate) rates_ary_size = @rates.size if rates_ary_size> 60 @rates = @rates[(rates_ary_size - 60)...rates_ary_size] @average_rates = @rates.each_slice(6).to_a.map { |ary| ary.inject(:+)/6 } # 平均 @avg = @rates.inject(:+)/@rates.size # 分散 var = @rates.reduce(0) { |a,b| a + (b - @avg) ** 2 } / (@rates.size - 1) # 標準偏差 sd = Math.sqrt(var) @plus_one_std_dev = @avg + sd @minus_one_std_dev = @avg - sd @plus_two_std_dev = @avg + (2 * sd) @minus_two_std_dev = @avg - (2 * sd) end end # 単純に現在のレートが def check_signal_exec(rate) # データ不足 return LACK_DATA if @rates.size < 60 if @plus_two_std_dev <= rate # +2σ以上 PLUS_SIGNAL_LV_3 elsif @plus_one_std_dev <= rate && @plus_two_std_dev> rate # +1σ以上、+2σ未満 PLUS_SIGNAL_LV_2 elsif @avg <= rate && @plus_one_std_dev> rate # 平均以上、+1σ未満 PLUS_SIGNAL_LV_1 elsif @minus_one_std_dev <= rate && @avg> rate # -1σ以上、平均未満 MINUS_SIGNAL_LV_1 elsif @minus_two_std_dev <= rate && @minus_one_std_dev> rate # -2σ以上、-1σ未満 MINUS_SIGNAL_LV_2 else # -2σ以下 MINUS_SIGNAL_LV_3 end end end
ここまでできれば売買ロジックを色々なケースに対応できるよう拡張していくだけです。
Python
Pythonで記述することも可能です。USER_KEYに取得した「アクセスキー」、USER_SECRET_KEYに取得した「シークレットキー」をセットしてください。
筆者はPythonでの取引をほぼしていないので、指値取引のみ記載します。
privateAPI.py import json import requests import time import hmac import hashlib class Coincheck: def __init__(self, access_key, secret_key, url='https://coincheck.com'): self.access_key = access_key self.secret_key = secret_key self.url = url def get(self, path, params=None): if params != None: params = json.dumps(params) else: params = '' nonce = str(int(time.time())) message = nonce + self.url + path + params signature = self.getSignature(message) return requests.get( self.url+path, headers=self.getHeader(self.access_key, nonce, signature) ).json() def post(self, path, params): params = json.dumps(params) nonce = str(int(time.time())) message = nonce + self.url + path + params signature = self.getSignature(message) return requests.post( self.url+path, data=params, headers=self.getHeader(self.access_key, nonce, signature) ).json() def delete(self, path): nonce = str(int(time.time())) message = nonce + self.url + path signature = self.getSignature(message) return requests.delete( self.url+path, headers=self.getHeader(self.access_key, nonce, signature) ).json() def getSignature(self, message): signature = hmac.new( bytes(self.secret_key.encode('ascii')), bytes(message.encode('ascii')), hashlib.sha256 ).hexdigest() return signature def getHeader(self, access_key, nonce, signature): headers = { 'ACCESS-KEY': access_key, 'ACCESS-NONCE': nonce, 'ACCESS-SIGNATURE': signature, 'Content-Type': 'application/json' # 必須 } return headers access_key = 'アクセスキー' secret_key = 'シークレットキー' # インスタンス作成 coincheck = Coincheck(access_key, secret_key) # 595,000円の指値で0,01ビットコインを現物取引買い注文 path_orders = '/api/exchange/orders' params = { "pair": "btc_jpy", "order_type": "buy", "rate": 595000, "amount": 0.01, } result = coincheck.post(path_orders, params) print(result)
Pythonではanacondaなど数値解析のためのライブラリが用意されており、活用することでより高度な自動化を設定できるかもしれませんね。
Coincheckの口座を活用し、ぜひ仮想通貨の自動売買に役立ててみてください。Coincheckの口座は以下から開設可能です。