Help us understand the problem. What is going on with this article?

CryptowatchのAPIを使用したBTC価格の取得と保存

More than 1 year has passed since last update.

やること

  • CryptowatchのAPIを使用して,ビットコインの価格データ(始値・高値・安値・終値)を取得し,csv形式で保存します.
  • n番煎じ?聞こえません!!!!!!!!!$ (n \geq 2, n \in N) $

環境

  • Python3系

単刀直入にソースコード

getBTCprice.py
#coding: utf-8

#sys.stderr.writeはただの標準エラー出力によるログなので消しても動く.
import sys
import urllib.request
from datetime import datetime, timedelta, timezone
import json

#python3 getBTCprice.py [period] [start(YYYY-mm-dd)] [end(YYYY-mm-dd/0)] [csvfile]

if len(sys.argv) != 5 or (sys.argv[1] != "1m" and sys.argv[1] != "5m" and sys.argv[1] != "1h" and sys.argv[1] != "4h" and sys.argv[1] != "1d" and sys.argv[1] != "1w"):
    sys.stderr.write("コマンドライン引数が不正です.\n")
    sys.exit()

#timezone
JST = timezone(timedelta(hours=+9), 'JST')

#取引所等パラメタ指定
market = "bitflyer/"
pricetype = "btcjpy/"
periodslist = {"1m":"60", "5m":"300", "1h":"3600", "4h":"14400", "1d":"86400", "1w":"604800"}
periods = ""#データの間隔

#期間指定
after = datetime.now(JST).timestamp()#ほんの初期化
#ここから
tstr = sys.argv[2].split("-")
after = datetime(int(tstr[0]), int(tstr[1]), int(tstr[2]), 0, 0, 0, 0, JST).timestamp()#コマンドライン引数の日付
#ここまで
before = datetime.now(JST).timestamp()#デフォルトは現在時刻
if sys.argv[3] != "0":
    tstr = sys.argv[3].split("-")
    before = datetime(int(tstr[0]), int(tstr[1]), int(tstr[2]), 0, 0, 0, 0, JST).timestamp()#コマンドライン引数の日付

#範囲・間隔・url指定
periods = periodslist[sys.argv[1]]
url = "https://api.cryptowat.ch/markets/" + market + pricetype + "ohlc?periods=" + periods + "&after=" + str(int(after)) + "&before=" + str(int(before))

#ただのログ
sys.stderr.writelines("after:" + str(datetime.fromtimestamp(after)) + "(" + str(after) + ")" + "\n")
sys.stderr.writelines("before:" + str(datetime.fromtimestamp(before)) + "(" + str(before) + ")" + "\n")
sys.stderr.write(url + "\n")

#apiにリクエストを送信し,レスポンスをcsv形式に変換し標準出力する.
with urllib.request.urlopen(url) as response:
    dat = response.read().decode("utf-8")
    dat = json.loads(dat)
    rows = dat['result'][periods]
    #売買代金を除いてcsvに出力したい.
    fp = open(sys.argv[4], "w")
    fp.write("time,start,high,low,close,Volume\n")
    for row in rows:#type(row)=list[int,int,int,int,int,float,float]
        dt = str(datetime.fromtimestamp(row[0])).split(" ")
        #価格取得失敗時には飛ばす
        if row[1] == 0 or row[2] == 0 or row[3] == 0 or row[4] == 0:
            pass
        #メンテ中の謎データは飛ばす
        elif dt[1] == "04:05:00" or dt[1] == "04:10:00":
            pass
        else:
            fp.write(str(datetime.fromtimestamp(row[0])) + "," + str(int(row[1])) + "," + str(int(row[2])) + "," + str(int(row[3])) + "," + str(int(row[4])) + "," + str(row[5]) + "\n")

    status = response.getcode()
    sys.stderr.write("Status code: " + str(status) + "\n")
    headers = response.info()
    sys.stderr.write(str(headers))

使い方

python3 getBTCprice.py [period] [start] [end/0] [csvfile]

コマンドライン引数について

  • period : データの間隔を指します.次のコマンドライン引数で指定する開始日から,
    • 1m : 1分ごと(1分足)
    • 5m : 5分ごと(5分足)
    • 1h : 1時間ごと(1時間足)
    • 4h : 4時間ごと(4時間足)
    • 1d : 1日(24時間)ごと(日足)
    • 1w : 1週間(7日)ごと(週足)

の価格データを取得します.

  • start : 指定された日付から価格データを取得します.日付の形式は,YYYY-mm-dd(2019年1月1日ならば2019-01-01)です.

  • end : 指定された日付までの価格データを取得します.日付の形式は[start]と同様です.このコマンドライン引数に,0を指定した場合は,現在日時までの価格データが取得されます.

  • csvfile : 出力先のcsvファイルのディレクトリを指します.

使用上の注意

  • およそ1年8ヶ月以前のデータは取得できません.(APIの仕様?)
  • およそ6000時点以前(1分ならおよそ6000分以上過去)のデータは取得できません.(APIの仕様?)
  • APIに送信するリクエストとしましては,start 00:00:00からend 00:00:00までの価格データですが,データの間隔が1m5mではうまく取得できませんでした.(start 00:00:00以前からのデータを取得し,end 00:00:00まで取得しきれない.)

仕様・解説

 ソースコードの解説が主となります.

リクエストの送信

APIによるリクエストの送信方法は以下の通り.

https://api.cryptowat.ch/markets/(取引所)/(取得対象データ)/(データの種類)?periods=(期間[sec])&after=(取得開始日時のUNIX時間)&before=(取得終了日時のUNIX時間)

ソースコード上での指定は以下の通り.詳細はコメントを参照ください.

#取引所等パラメタ指定
market = "bitflyer/" #取引所bitFlyer
pricetype = "btcjpy/" #取得対象データはBTC/JPY
periodslist = {"1m":"60", "5m":"300", "1h":"3600", "4h":"14400", "1d":"86400", "1w":"604800"} #このAPIでの間隔の単位は[秒]
periods = "" #データの間隔

#期間指定
after = datetime.now(JST).timestamp() #ほんの初期化
#ここから
tstr = sys.argv[2].split("-") #コマンドライン引数から年,月,日の値をsplit()で取得
after = datetime(int(tstr[0]), int(tstr[1]), int(tstr[2]), 0, 0, 0, 0, JST).timestamp() #コマンドライン引数の日付
#ここまで
before = datetime.now(JST).timestamp() #デフォルトは現在時刻
#終了日も指定している場合
if sys.argv[3] != "0":
    tstr = sys.argv[3].split("-") #コマンドライン引数から年,月,日の値をsplit()で取得
    before = datetime(int(tstr[0]), int(tstr[1]), int(tstr[2]), 0, 0, 0, 0, JST).timestamp() #コマンドライン引数の日付


#範囲・間隔・url指定
periods = periodslist[sys.argv[1]]
url = "https://api.cryptowat.ch/markets/" + market + pricetype + "ohlc?periods=" + periods + "&after=" + str(int(after)) + "&before=" + str(int(before))

データの種類 : ohlcに関しては,始値(Open)・高値(High)・安値(Low)・終値(Close)の4種類のデータを取得することを指します.

レスポンスとデータ保存.

レスポンスの例(日足 2019-01-01 00:00:00から2019-02-01 00:00:00の実行結果)
ソースコードを通して解説します.分かりにくかったらスンマセン.

#apiにリクエストを送信し,レスポンスをcsv形式に変換し標準出力する.
with urllib.request.urlopen(url) as response:
    dat = response.read().decode("utf-8") #レスポンスの取得,json形式のデータ構造ではあるが文字列である.
    dat = json.loads(dat) #文字列のレスポンスをjsonレスポンス通りの辞書型に変換
    rows = dat['result'][periods] #価格に関するデータのみを選択
    #売買代金を除いてcsvに出力したい.
    fp = open(sys.argv[4], "w")
    fp.write("time,start,high,low,close,Volume\n")
    for row in rows: #type(row)=list[int(UNIX時間),int(始値),int(高値),int(安値),int(終値),float(出来高),float(売買代金)]
        dt = str(datetime.fromtimestamp(row[0])).split(" ")
        #価格取得失敗時には飛ばす
        if row[1] == 0 or row[2] == 0 or row[3] == 0 or row[4] == 0:
            pass
        #メンテ中の謎データは飛ばす
        elif dt[1] == "04:05:00" or dt[1] == "04:10:00":
            pass
        else:
            fp.write(str(datetime.fromtimestamp(row[0])) + "," + str(int(row[1])) + "," + str(int(row[2])) + "," + str(int(row[3])) + "," + str(int(row[4])) + "," + str(row[5]) + "\n")

    #以下単なるステータスコードとレスポンスヘッダ
    status = response.getcode()
    sys.stderr.write("Status code: " + str(status) + "\n")
    headers = response.info()
    sys.stderr.write(str(headers))

終わりに

暗号通貨が近い将来どのように扱われているのか気になって夜と朝方しか眠れません.

NULLchar
データ解析に興味があります.
https://github.com/yyk458
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした