ビットコインの自動売買システムを作ってみた|bitFlyer

ビットコイン自動売買システム

ブラックフライデーセールでUdemyの動画が軒並み1,200円になってたので、前から気になっていた「Rubyで作る! ビットコイン自動売買システム」を購入してチャレンジしてみました。

Udemyは動画でプログラミングなどが学べるオンライン教材です。

プログラミングの他にもデザインやビジネスマナーなど色々な動画があります。

ビットコイン自動売買システムを作る

動画は全部で3時間ほどなんですけど、毎日ちょっとずつ進めてトータル5時間ぐらいで完成できました。

解説動画を観ながら、実際にプログラミングしていく感じです。一時停止と巻き戻し必須です。

パソコンのディスプレイが小さいとこういう時に不便ですね。

動画ではかなり初歩の初歩から説明されていて、分かりやすかったです。

必要なサービスのアカウント登録、足し算・掛け算などからなので、プログラミングしたことない人でもなんとかなりそうな印象でした。

ビットコイン自動売買システム
1秒に30回注文を出しているところ

1秒ごとに勝手に注文が出されるところを眺めるとシステムトレードやってる感がすごいです!

一部エラーが出て動かなかったりすることがあったので、動画を進めたり戻したりググったりと頑張りました。以下はつまずいた所です。

売り買いの注文を出すとエラー

bitFlyerに注文を出すところで以下のエラーが出ました。

/home/ec2-user/environment/method.rb:99:in `+': no implicit conversion of Float into String (TypeError)

原因は関数に引数で渡した価格と注文数量が数値だからみたいです。

body部のpriceとsizeに、数値を文字列に変換するメソッドの「.to_s」を追加して解決。

    body = '{
      "product_code": "BTC_JPY",
      "child_order_type": "LIMIT",
      "side": "' + side + '",
      "price": ' + price.to_s + ',
      "size": ' + size.to_s + ',
      "minute_to_expire": 10000,
      "time_in_force": "GTC"
    }'

ボリンジャーバンドを追加する

せっかくなのでボリンジャーバンドの判定をシステムに組み込んでみました。

動画の最後の方で紹介されていた指標です。

ボリンジャーバンドには1σ、2σ、3σの3本の線が上下にあり、2σのボリンジャーバンド内に株価が推移する確率は95%にもなるそう。

ボリンジャーバンドについてはこちらのサイトが分かりやすかったです。

2σの下のバンドに近づいたらビットコインを買い、上のバンドに近づいたら売るみたいなプログラムが出来たら良さそうな気がします。

計算式

プログラムに組み込むために詳しい計算式を探していると英語のサイトが見つかりました。よく分からないけどこれだろう。

  * Middle Band = 20-day simple moving average (SMA)
  * Upper Band = 20-day SMA + (20-day standard deviation of price x 2) 
  * Lower Band = 20-day SMA - (20-day standard deviation of price x 2)
  * Middle Band = 単純移動平均線
  * Upper Band = 単純移動平均線 + (標準偏差(σ) x 2) 
  * Lower Band = 単純移動平均線 - (標準偏差(σ) x 2)

MiddleBandが上の図でいう「移動平均線」、UpperBandが2σバンドの上、LowerBandが下なのかな。

そうすると、計算に必要なのは「単純移動平均線」と「標準偏差(σ)」になります。

単純移動平均線

移動平均線は価格の平均値です。

現在価格を取得して、配列に格納し、その平均値を求める方法で計算できそうです。

  # 現在価格を取得
  price = get_price
  
  # 配列に追加
  prices.push(price)
  
  if prices.length > 20
    # 配列から一番古いものを削除
    prices.shift
    
    # 単純移動平均線
    middle_band = prices.mean

標準偏差(σ)

method.rbに以下を追加します。

class Array
  # 合計
  def sum
    reduce(:+)
  end
 
  # 平均
  def mean
    sum.to_f / size
  end
 
  # 分散
  def variance
    m = mean
    reduce(0) { |a,b| a + (b - m) ** 2 } / (size - 1)
  end
 
  # 標準偏差
  def standard_deviation
    Math.sqrt(variance)
  end
end

method.rbに追加したらbitcoin.rbで以下のようにして標準偏差が計算できます。

    # 標準偏差(σ)
    standard_deviation = prices.standard_deviation

ボリンジャーバンドもどきを算出

最終的に出来たbitcoin.rbファイルがこれ

require 'date'
require './method'

#値段を入れる配列
prices = []

# 現在価格
price = 0

# 注文数量
order_size = 0.01

# もうお金ない判定
stop_price = 25000

# 無限ループ開始
while(true)

  # 保有資産(JPY)
  jpy_amount = get_my_money("JPY")["amount"]
  # 保有資産(BTC)
  btc_amount = get_my_money("BTC")["amount"]

  # 現在価格を取得
  price = get_price
  
  # 配列に追加
  prices.push(price)
  
  if prices.length > 20
    # 配列から一番古いものを削除
    prices.shift
    
    # 単純移動平均線
    middle_band = prices.mean
    
    # 標準偏差(σ)
    standard_deviation = prices.standard_deviation
    
    # ボリンジャーバンド(σ)
    upper_bollinger_band = middle_band + standard_deviation
    lower_bollinger_band = middle_band - standard_deviation
    
    # ボリンジャーバンド(2σ)
    upper_bollinger_band_2 = middle_band + (standard_deviation * 2)
    lower_bollinger_band_2 = middle_band - (standard_deviation * 2)
    
    puts "now price : "  + price.to_s
    
    # 現在価格がボリンジャーバンドを下回ったら買い
    if (price <= lower_bollinger_band_2) && (jpy_amount > stop_price)
      puts "買い注文を発注します。"
      order("BUY", price, order_size)
      
    # 現在価格がボリンジャーバンドを上回ったら売り
    elsif (price >= upper_bollinger_band_2) && (btc_amount > 0.001)
      puts "売り注文を発注します。"
      order("SELL", price, order_size)
      
    end
    
    else
      p prices
  end
  
  sleep(1 * 60)
  
end

そもそもちゃんとボリンジャーバンドが計算されてるかも分かんないんですが、それもりもダメなところに気づきました。

このプログラムは1分ごとにビットコインの価格を取得して動いてるんですけど、これだと「20日移動平均線」どころか「20分移動平均線」という短すぎるスパンのものになっています…

ビットフライヤーのAPIは過去の価格は取れないみたいなんで、他のサービスで過去の価格を取得するやり方が良さそうですね。

とはいえ、ちょっとそれらしい自動売買システムができたのは嬉しいところ。

全く儲かってないですけども…