[Python]ビットコイン自動売買プログラムをシミュレーションをしてパラメータを最適化する

自動売買

はじめに

前の記事で、単純移動平均のゴールデンクロス・デッドクロスを利用したビットコイン自動売買プログラムを公開しました

ビットコイン自動売買プログラムのアルゴリズムは、長期移動平均と短期移動平均のゴールデンクロスで全力買い、デッドクロスで全力売りとしました

ここで、長期移動平均は何分平均なのか、短期移動平均は何分平均なのかを決めておかなければないません

長期平均期間と短期平均期間がそれぞれ何分なのかによって、利益も変わってきます

もちろん利益が大きい方がいいので、利益が大きくなるような長期平均期間と短期平均期間を見つける作業をします

言い換えると、パラメータの最適化をしなければいけないということです

この記事で、シミュレーションによって利益が1番高くなるようなパラメータ

・長期移動平均期間

・短期移動平均期間

を決めます

シミュレーションの条件

シミュレーションを行う上で、この2つを条件にしました

1ヶ月分のデータを使う

10分〜1440分(=1日)の範囲で、10分ごとにシミュレーションしてみようと思います

期間は、2020年12月、2021年1月、2020年2月のそれぞれ1ヶ月分のデータを使います

シミュレーション後、これら3パターンの結果を照らし合わせます

分足データを使う

仮想通貨取引所bitbankの公式APIを使うことで、ビットコインのデータを取得することができます

取得できるデータの中で、最も細かい分足(1分ごと)のデータを使うことにします

手数料

手数料を考慮する必要があります

手数料には、取引手数料に加えて、スプレッドを考慮することにします

スプレッドとは、買い注文と売り注文の価格差のことです

取引手数料

bitbankの取引手数料は0.05%(テイカー)です

スプレッド

下のサイトで、各仮想通貨取引所のスプレッドを一覧で見ることができます

bitbankスプレッドは平均して1,000円くらいなので、

1,000[円] ÷ 6,000,000[円/BTC] = 0.000166 

大体0.0166%の影響があることがわかります

手数料の合計

これらを足した0.07%とすることにします

データの取得

まずはじめに、1ヶ月分のデータ×3を取得します

2020年12月分

2021年1月分

2021年2月分

データの取得方法について、詳しくはこの記事に書きました

シミュレーションで一番儲かるパラメータを探す

シミュレーションをすることで、一番儲かるような

長期移動平均期間(分)

短期移動平均期間(分)

の組み合わせを探していきます

パラメータを総当たり

パラメータである

・長期移動平均期間(以下長期)

・短期移動平均期間(以下短期)

を、長期20分・短期10分、長期30分・短期10分、長期30分・短期20分、、、と順に変えながら、それぞれ見込まれる利益を計算していきます

こういう形のデータフレームを作って、順に利益を計算し、利益を埋めていこうと思います

長期\短期 10 20 ・・・ 1420 1430
20 × × × ×
30 × × ×
・・・ × ×
1430 ×
1440

もっとも利益が高かったパラメータを採用しようと思います

シミュレーションで使ったPythonプログラムを載せておきます

#パラメータの設定
#何時間か
hours = 24
#何分ごとか
interval = 10

#単純移動平均smaを計算
price = df["Close"]
#この場合1日でやる
span_float = hours*60/interval
span = int(span_float)
for counter in range(span):
    the_span = (counter+1)*interval
    df["sma"+str(the_span)] = price.rolling(window=the_span).mean()

#条件
fee = 0.0007
jpy = 10000
btc = 0

#擬似的に購入する 引数:btc資産 jpy資産 レート 返り値:btc資産 jpy資産
def buy(btc, jpy, ratio):
    btc += jpy / ratio * (1 - fee)
    jpy = 0
    return(btc, jpy)


#擬似的に売却する 引数:btc資産 jpy資産 レート 返り値:btc資産 jpy資産
def sell(btc, jpy, ratio):
    jpy += btc * ratio * (1 - fee)
    btc = 0
    return(btc, jpy)

#データフレームの定義
list_for_index = []
for counter in range(span-1):
    list_for_index.append((counter+2)*interval)
    
list_for_column = []
for counter in range(span-1):
    list_for_column.append((counter+1)*interval)
    
df_result = pandas.DataFrame(index=list_for_index, columns=list_for_column)

#10分ごとに総当たりで計算し、データフレームを埋める
from tqdm import tqdm
#長期
for long in tqdm(range(span-1)):
    long_span = (long + 2) * interval
    
    
    #短期
    for short in range(long+1):
        short_span = (short + 1) * interval
        
        
        
        btc = 0
        jpy = 10000
        #longとshortをパラメータに計算する
        sim_days = len(df) - span
        for counter in range(sim_days):
            the_day = span + counter
            ratio = df.at[the_day,"Close"]
            if df.at[the_day,"sma"+str(short_span)] > df.at[the_day,"sma"+str(long_span)]:
                if jpy > 0:
                    res = buy(btc,jpy,ratio)
                    btc = res[0]
                    jpy = res[1]
            else:
                if btc > 0:
                    res = sell(btc,jpy,ratio)
                    btc = res[0]
                    jpy = res[1]
        asset = jpy + btc * ratio
        df_result.loc[long_span,short_span] = asset

シミュレーション結果

シミュレーション結果は下のようになりました

2020年12月分

2021年1月分

2021年2月分

このような表データ(2次元データ)のシミュレーション結果を得ることができました

この中から、1番利益が大きいパラメータを見つけていきます

しかし数字だらけの表で、見つけづらいので、見やすいようにグラフにして可視化していきます

2次元データの可視化

数字が羅列されていて見づらいので、データを可視化していこうと思います

データの可視化には、グラフ描画のライブラリであるmatplotlibを使います

matplotlibのpyplotクラスのpcolormeshメソッドを使うと、2次元データを可視化することができます

この記事を参考にしました

こういう等高線みたいなグラフを作っていきます

pcolormeshについて

plt.pcolormesh(X,Y,Z)

引数は

・X(x座標)

・Y(y座標)

・Z(z座標)

の三つです

(x,y,z)の三次元座標を引数として実行すれば、等高線のようなグラフがかけるらしいです

pcolormeshを使った可視化

さっき計算した2次元データを(x,y,z)の3次元データとして扱えるようにしてから、描画するようプログラムを書きました

#ライブラリ
import numpy 
import matplotlib.pyplot as plt


#データの加工
#nanを0にする
df_result_processed = df_result.fillna(10000)
#データ部分を配列として取り出す
a_df = df_result_processed.values



#第一引数X(x座標の設定)
x = []
for counter in range(len(df_result.columns)+1):
    x.append(counter) 
x_a = []
for counter in range(len(df_result.columns)+1):
    x_a.append(x)  
X = numpy.array(x_a)


#第二引数Y(y座標の設定)
y = []
for counter in range(len(df_result)+1):
    y.append(0)
y_a = []
for counter_1 in range(len(df_result)+1):
    y = []
    for counter_2 in range(len(df_result)+1):
        y.append(counter_1)
    y_a.append(y)
Y = numpy.array(y_a)



#第三引数Z(z座標の設定)
Z = a_df



#描画する
#軸ラベルの設定
plt.xlabel('short_span[hours]', fontsize=20)
plt.ylabel('long_span[hours]', fontsize=20)

#描画
plt.pcolormesh(X,Y,Z, cmap='magma')

#カラーバーの表示
pp=plt.colorbar (orientation="vertical") 
pp.set_label("asset[yen]",  fontsize=20)

可視化結果

2020年12月

2021年1月

2020年2月

シミュレーション結果より

3パターンのシミュレーション結果より、長期移動平均期間が1000分、短期移動平均期間が700分あたりがベストなパラメータなのではないかと思います

このパラメータだと、どの月でも月利が10%以上は見込めそうです

最後に

シミュレーション結果より、長期移動平均期間が1000分、短期移動平均期間が700分あたりがベストなパラメータだということが分かりました

このパラメータだと、どの月でも月利が10%以上は見込めそうです

しかし、パラメータが見込みの利益の観点で最適だということが分かりましたが、リスクについては一歳無視しています

このまま実装するのも怖いので、一度バックテストをしておこうと思います

コメント

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