見出し画像

【Python】コピペで動く仮想通貨自動売買ツールを紹介

エンジニアの端くれの僕。
「プログラミングでビットコインを自動で売買出来たら儲かるかも?」
と思い、いろんな紹介記事をあさって仕上げてみた。
一週間、ツールを動かしてみて儲かったかどうかはさておき・・・。

作ってみた記録として残しておきます。
コピペOKなので自由にカスタマイズするなり使っていいですよ。

注意事項

  • ツールを使用したことで発生する損益について、私は一切責任は持ちません、完全自己責任でお使いください

  • プライベートAPIキーの流出にはくれぐれもお気をつけください

自動売買ツールの特徴について

  • 必ずメイカー(Maker)注文となるため、手数料をゼロに抑えることが可能です

  • BB(ボリンジャーバンド)の指標を用いて売買サインを検知します

  • 取引量が圧倒的に多いバイナンスの板情報を参考価格としているため、より正確な取引価格の算出が可能です

【コピペOK】ソースコード

import time
import ccxt
import datetime
import calendar
import pandas as pd
import talib
import numpy as np
import python_bitbankcc
import math

#**************************************************************************
#変数定義
#**************************************************************************

# ビットコイン自動売買初期設定
symbol = "BTC/JPY"   # 購入通貨
amount = 0.001       # 購入数量[BTC]
sleep_time = 60 #秒
loss_line = 0.95 #損切ライン(5%の下落で損切)
tradeMode = "null"  #処理モード切り替え

# API情報
API_KEY     = '自身のAPIキーを入力'
SECRET_KEY  = '自身のシークレットキーを入力'

 #bitbank bb = ccxt.bitbank({
    'apiKey': API_KEY ,
    'secret': SECRET_KEY ,
})

#Binanceの板情報を使用する
binance = ccxt.binance()

#ビットバンクのパブリックapi インスタンス生成
pub = python_bitbankcc.public()
#ビットバンクのプライベートapi インスタンス生成
prv = python_bitbankcc.private(API_KEY,SECRET_KEY)

#価格リスト
btc_price_list = []

#**************************************************************************
#関数定義
#**************************************************************************

#初期セット
def get_ini_price(ticker='BTC/USDT', timeframe='1h',minute = sleep_time*60*20):
    # 現在時刻のUTC naiveオブジェクト
    now = datetime.datetime.utcnow()
    # UTC naiveオブジェクト -> UnixTime
    unixtime = calendar.timegm(now.utctimetuple())

    # 1200分前のUnixTime(ミリ秒)
    
    since = (unixtime - 60 * minute) * 1000
    ohlcvs = binance.fetch_ohlcv(symbol=ticker, timeframe=timeframe, since=since)
    #df化
    df = pd.DataFrame(ohlcvs, columns=['Time','Open','High','Low','Close','Vol'])
    df ['Time'] = pd.to_datetime(df ['Time'],unit='ms')
    df ['Time'] = df ['Time'] + datetime.timedelta(hours=+9) #日本時間に変更
    df.index = df ['Time'] 
    return df

#**************************************************************************
#関数①:ビットコインの板情報取得
#**************************************************************************
#新しい価格の取得
def get_new_price(ticker='BTC/USDT', timeframe='1h',minute = sleep_time*60*20):
    # 現在時刻のUTC naiveオブジェクト
    now = datetime.datetime.utcnow()
    # UTC naiveオブジェクト -> UnixTime
    unixtime = calendar.timegm(now.utctimetuple())

    # UnixTime(ミリ秒)
    since = (unixtime - 60 * minute) * 1000
    ohlcvs = binance.fetch_ohlcv(symbol=ticker, timeframe=timeframe, since=since)
    #df化
    df = pd.DataFrame(ohlcvs, columns=['Time','Open','High','Low','Close','Vol'])
    df ['Time'] = pd.to_datetime(df ['Time'],unit='ms')
    df ['Time'] = df ['Time'] + datetime.timedelta(hours=+9) #日本時間に変更
    df.index = df ['Time'] 
    return df.iloc[-1]

#**************************************************************************
#関数②:日本円残高情報取得
#**************************************************************************
def balance_jpy():
    JPY = float(bb.fetch_balance()['info']['data']['assets'][0]['free_amount'])
    return JPY

#**************************************************************************
#関数③:日本円残高チェック
#**************************************************************************
def check_jpy():
    # 初期残高
    initial_balance = balance_jpy()

    # 日本円残高が今回購入予定のビットコイン価格×数量を上回っているか確認
    balance_dif = int(initial_balance - (float(bb.fetch_ticker(symbol="BTC/JPY")["last"]) * amount))
    print("残高",initial_balance)

    # 残高判定
    if balance_dif > 0:
        message = "ビットコイン購入可能"
    
        
    else:
        message = "ビットコイン購入不可"
        
    return message   

#**************************************************************************
#関数④:ビットコイン購入判定
#**************************************************************************
def bb_band_buy(btc_price_list):

    # ボリンジャーバンド引数情報
    period  = 20  # データ取得期間
    bbup    = 2   # upper-band:標準偏差
    bbdwn   = 2   # down-band:標準偏差
    ma_type = 0   # 移動平均の種類(0:単純移動平均)
    
    # ボリンジャーバンド指標獲得
    bb_up, bb_middle, bb_down = talib.BBANDS(pd.Series(btc_price_list),  # 価格データ
                                             timeperiod=period,          # データ取得期間
                                             nbdevup=bbup,               # upper-band:標準偏差 
                                             nbdevdn=bbdwn,              # down-band:標準偏差
                                             matype=ma_type)             # 移動平均の種類(0:単純移動平均)

    # 買いサインの検出
    # ビットコイン価格 < -2σを満たす時とする
    if btc_price_list[len(btc_price_list)-1] < bb_down[len(bb_down)-1]:
        result = "購入サイン検知"
    else:
        result = "チャート分析中"

    print(result)
    return result

#**************************************************************************
#関数⑤:ビットコイン売却判定
#**************************************************************************
def bb_band_sell(btc_price_list,buy_btc_price):

    # ボリンジャーバンド引数情報
    period  = 20  # データ取得期間
    bbup    = 2   # upper-band:標準偏差
    bbdwn   = 2   # down-band:標準偏差
    ma_type = 0   # 移動平均の種類(0:単純移動平均)
    
    # ボリンジャーバンド指標獲得
    bb_up, bb_middle, bb_down = talib.BBANDS(pd.Series(btc_price_list),  # 価格データ
                                             timeperiod=period,          # データ取得期間
                                             nbdevup=bbup,               # upper-band:標準偏差 
                                             nbdevdn=bbdwn,              # down-band:標準偏差
                                             matype=ma_type)             # 移動平均の種類(0:単純移動平均)

    # ビットコイン価格 < 2σを満たす時とする
    if btc_price_list[len(btc_price_list)-1] > bb_up[len(bb_down)-1]:
        result = "売却サイン検知"
    
    elif buy_btc_price * loss_line > btc_price_list[len(btc_price_list)-1]:
        result = "売却サイン検知"
        print('損切')
    else:
        result = "チャート分析中"

    print(result)
    return result

#**************************************************************************
#メイン処理開始:売買処理を永遠に繰り返す
#**************************************************************************
while True:

    #残高チェック
    balance_check = check_jpy()
    if balance_check =="ビットコイン購入不可":
        print ("残高をチェックしました。ビットコインが購入できません。")

    #ビットコイン購入可能
    else:
         print ("ビットコイン購入可能")
         
         #売買モードを購入待ちに変更
         tradeMode = "購入待ち"

    #ビットコイン価格チェック
    btc_price_list_df  = get_ini_price(ticker='BTC/USDT', timeframe='1m',minute = 20)
    btc_price_list = btc_price_list_df['Close']

    #Bitbankにある自己資産情報の取得
    asset_data = prv.get_asset()
    asset_data = asset_data["assets"]

    #日本円の資産額を取得
    jpy_asset = float(asset_data[0]['free_amount'])
        
    #ビットコインの資産額を取得
    btc_asset = float(asset_data[1]['free_amount'])

    #購入判定
    trigger = bb_band_buy(btc_price_list)

    #購入サインを検知した場合、ビットコインを購入する
    if trigger ==  "購入サイン検知" and not balance_check == "ビットコイン購入不可":
        print("購入処理開始")
            
        #現在の取引価格を取得
        now_tradePrice = pub.get_ticker('btc_jpy')
        now_tradePrice = now_tradePrice["last"]
        
        #買う数量を計算
        order_vol = jpy_asset / float(now_tradePrice)
        order_vol = math.floor(order_vol * 10000) / 10000

        #新規注文を行う:'ペア', '価格', '注文枚数', '売or買', '指値or成行' ,"メイカー注文"
        prv.order('btc_jpy',str(now_tradePrice),str(order_vol),'buy','limit',post_only = True)
        
        #Bainanceの最新のビットコイン価格を取得
        buy_btc_price = binance.fetch_ticker(symbol="BTC/USDT")["ask"]
        #Bitbankの最新のビットコイン価格を取得
        jpy_buy_btc_price = bb.fetch_ticker(symbol="BTC/JPY")["ask"]
        
        #約定金額を出力する
        print('購入価格',jpy_buy_btc_price)
        
        new_btc_price_list_df = get_new_price(ticker='BTC/USDT', timeframe='1m',minute = 1)
        
        #売買モードを売却待ちに変更する
        tradeMode = "売却待ち"

        #ビットコインの資産額を取得
        btc_asset = float(asset_data[1]['free_amount'])

    #売却サインを検知するまで待機する
    elif trigger == "チャート分析中" and btc_asset > 0:
        tradeMode = "売却待ち"
        print("売却待ち")

    #日本円残高もビットコイン残高もない場合は処理を中断する
    elif balance_check == "ビットコイン購入不可" and btc_asset < 0:
        print("残高が足りないため、処理を中断します。")
        exit()

    #購入サインを検知するまで待機する
    else:
        print("購入サイン検知待ち")
        print("チャート分析中")

#**************************************************************************
#一時間ごとに売買判定を実施し、購入サインを検知するまで繰り返す
#**************************************************************************

    while tradeMode == "購入待ち":
        print("ただいま、購入サイン検知待ちです。")
        #1時間待機
        time.sleep(sleep_time)
        
        #Binanceからビットコインの最新価格を取得
        new_btc_price_list_df = get_new_price(ticker='BTC/USDT', timeframe='1m',minute = 1)
        btc_price_list_df.loc[new_btc_price_list_df['Time']] = new_btc_price_list_df
        btc_price_list = btc_price_list_df['Close']

        #Bitbankにある自己資産情報の取得
        asset_data = prv.get_asset()
        asset_data = asset_data["assets"]

        #日本円の資産額を取得
        jpy_asset = float(asset_data[0]['free_amount'])
        
        #ビットコインの資産額を取得
        btc_asset = float(asset_data[1]['free_amount'])

        #ボリンジャーバンドで売買判定
        trigger = bb_band_buy(btc_price_list)

#**************************************************************************
#購入サインを検知できた場合、購入処理を開始
#**************************************************************************
        if trigger ==  "購入サイン検知":
            print("購入処理開始")
            
            #現在の取引価格を取得
            now_tradePrice = pub.get_ticker('btc_jpy')
            now_tradePrice = now_tradePrice["last"]
        
            #日本円の資産額を取得
            jpy_asset = float(asset_data[0]['free_amount'])
            
            #買う数量を計算
            order_vol = jpy_asset / float(now_tradePrice)
            order_vol = math.floor(order_vol * 10000) / 10000

            #新規注文を行う:'ペア', '価格', '注文枚数', '売or買', '指値or成行' ,"メイカー注文"
            prv.order('btc_jpy',str(now_tradePrice),str(order_vol),'buy','limit',post_only = True)
            
            #Bainanceの最新のビットコイン価格を取得
            buy_btc_price = binance.fetch_ticker(symbol="BTC/USDT")["ask"]
            #Bitbankの最新のビットコイン価格を取得
            jpy_buy_btc_price = bb.fetch_ticker(symbol="BTC/JPY")["ask"]
            
            #約定金額を出力する
            print('購入価格',jpy_buy_btc_price)
            
            new_btc_price_list_df = get_new_price(ticker='BTC/USDT', timeframe='1m',minute = 1)
            #売買トリガーを売却待ちに変更する
            tradeMode = "売却待ち"

        btc_price_list_df.loc[new_btc_price_list_df['Time']] = new_btc_price_list_df

        #ビットコインの資産額を取得
        btc_asset = float(asset_data[1]['free_amount'])

    #約定待ち
        while (btc_asset < 0):
            print("約定待ちです")
            time.sleep(5)
            btc_asset = float(asset_data[1]['free_amount'])

#**************************************************************************
#売却できるまで処理を回す
#**************************************************************************
    while tradeMode == "売却待ち":
        
        print("ただいま、売却サイン検知待ちです。")
        #1時間待機
        time.sleep(sleep_time)

        #Binanceからビットコインの最新価格を取得
        new_btc_price_list_df = get_new_price(ticker='BTC/USDT', timeframe='1m',minute = 1)
        btc_price_list_df.loc[new_btc_price_list_df['Time']] = new_btc_price_list_df
        btc_price_list = btc_price_list_df['Close']

        #Bitbankにある自己資産情報の取得
        asset_data = prv.get_asset()
        asset_data = asset_data["assets"]

        #日本円の資産額を取得
        jpy_asset = float(asset_data[0]['free_amount'])
        
        #ビットコインの資産額を取得
        btc_asset = float(asset_data[1]['free_amount'])

        #Bainanceの最新のビットコイン価格を取得
        buy_btc_price = binance.fetch_ticker(symbol="BTC/USDT")["ask"]

        #売買判定
        trigger = bb_band_sell(btc_price_list,buy_btc_price)

#**************************************************************************
#売却サインを検知した場合、売却処理を開始
#**************************************************************************
        if trigger ==  "売却サイン検知":
            print("売却")
            
            #現在の取引価格を取得
            now_tradePrice = pub.get_ticker('btc_jpy')
            now_tradePrice = now_tradePrice["last"]
        
            #ビットコインの資産額を取得
            btc_asset = float(asset_data[1]['free_amount'])
            
            order_vol = btc_asset
            order_vol = math.floor(order_vol * 10000) / 10000

            #売り注文を実施
            prv.order('btc_jpy',str(now_tradePrice),str(order_vol),'sell','limit',post_only = True)
            
            #order('sell',amount)

            #Bainanceの最新のビットコイン価格を取得
            sell_btc_price = binance.fetch_ticker(symbol="BTC/USDT")["ask"]
            #約定価格を取得
            jpy_sell_btc_price = bb.fetch_ticker(symbol="BTC/JPY")["ask"]

            #約定価格を出力
            print('売却価格',jpy_sell_btc_price)
            
            #トリガを購入待ちに変更
            tradeMode =  "購入待ち"
    
    #ビットコインの資産額を取得
    btc_asset = float(asset_data[1]['free_amount'])
    ret_balance_jpy = balance_jpy()
    
    #約定待ち
    while (ret_balance_jpy < 0):
        print("約定待ちです")
        time.sleep(5)
        btc_asset = float(asset_data[1]['free_amount'])
        ret_balance_jpy = balance_jpy()

    btc_price_list_df.loc[new_btc_price_list_df['Time']] = new_btc_price_list_df

↑ソースコードを任意のテキストエディタに張り付けて、「XXXXX.py」の拡張子で保存するだけ。

# ビットコイン自動売買初期設定
symbol = "BTC/JPY"   # 購入通貨
amount = 0.001       # 購入数量[BTC]
sleep_time = 60 #秒
  • 「symbol」は売買対象の銘柄です

  • 「amount」は購入数量です ※指値注文のため使用しておりません、成行注文に変更したい場合に使用します

  • 「sleep_time 」は処理の待機時間です ※もしプログラムを1時間間隔で処理を走らせたい場合は3600に値を変更してください

後はAPI情報を入力するだけでOK

# API情報
API_KEY     = '自身のAPIキーを入力'
SECRET_KEY  = '自身のシークレットキーを入力'

ビットバンクのAPIキーとシークレットキーを取得し、
カンマとカンマの間に入力してください。


この記事が気に入ったらサポートをしてみませんか?