見出し画像

Pythonでティッカー情報をデータベースへの格納に挑戦してみた

データベースとfor文 

仮想通貨取引所のAPIから取得したティッカー情報は膨大だ。それを加工するためには、ティッカー情報をデータベースに入れる方が処理速度が早い。

そして、暗号資産の銘柄ごとにデータベースへ格納するためには、for文を使って繰り返すのが効率的だ。

今回から、少しづつレベルが上がるけど、打倒資本家を目指して手を動かそう。

for文と配列

今回データベースを作るので、以前に書いたコードを大幅に書き直さないといけない。前に書いていたコードはこちら。

# -*- coding: utf-8 -*- #
"""
We crush capitalism.
"""

import pybitflyer
import csv
import time

"""
初期設定
"""
Start_time = time.perf_counter()

while True:
   print(Start_time)
   BTC_tick = pybitflyer.API().ticker(product_code="BTC_JPY")
   print("BTC_timestamp : " + str(BTC_tick["timestamp"]))
   print("BTC_ltp : " + str(BTC_tick["ltp"]))
   print("BTC_best_bid : " + str(BTC_tick["best_bid"]))
   print("BTC_best_ask : " + str(BTC_tick["best_ask"]))

   ETH_tick = pybitflyer.API().ticker(product_code="ETH_JPY")
   print("ETH_timestamp : " + str(ETH_tick["timestamp"]))
   print("ETH_ltp : " + str(ETH_tick["ltp"]))
   print("ETH_best_bid : " + str(ETH_tick["best_bid"]))
   print("ETH_best_ask : " + str(ETH_tick["best_ask"]))

   with open('furture.csv','a',newline=''as files:
      writer = csv.writer(files)
      writer.writerow(['TIME',str(ETH_tick["timestamp"]),'ltp',str(ETH_tick["ltp"]),'bid',(ETH_tick["best_bid"]),'ask',str(ETH_tick["best_ask"])])
   time.sleep((10 + Start_time ) - time.perf_counter())
   Start_time = Start_time + 10

今回は、暗号資産の銘柄ごとに繰り返しデータを抽出するコードを書こう。そうすれば、取引所がAPIで使える銘柄を増やしたとしても対応できる。
まずは、for文のおさらいだ。

pythonのfor文では、変数の後ろに「in」が付くことと、オブジェクトの後ろに「:」が付くことに注意しましょう。

まず、初期設定の下に次のコードを入れる。この、ビットコインとイーサリアムのシンボルであるBTCとETHをTicker_symbolという引数に配列として代入している。

Ticker_symbol = ["BTC""ETH"]

プログラムでいう配列は、データのまとまりのことを言うけど、Pythonの配列にはリストとタプルがある。今回は、リストを使うので[ ]で囲っているけど、タプルの場合は( )で囲う。

Pythonで配列を扱う際にはリストを使います。タプルも配列を扱うことができますが、タプルは要素を変更できないという違いがあります。

次は、以前書いたwhileからwithの間のコードを一気に書き直してしまおう。
for文の意味はこうだ。引数Ticker_symbolのリストの数だけ繰り返し実行し、引数の中にあるBTCやETHという文字列をSYMBOLという引数に代入するという命令だ。

   for SYMBOL in Ticker_symbol:
      """
      ティッカーからデータ取得
      """

一回、引数SYMBOLに代入されれば、BTCやETHを別々にコードに書かなくてもfor文で繰り返し実行してくれる。
次のコードは、3文字のシンボルに_JPYという文字列を加えることで、BTC_JPYかETH_JPYという新しい引数を作っている。

CODE = SYMBOL + "_JPY"

今回は、以前記事に書いた拡張モジュールpybitflyerを使って、bitflyer APIの全11情報を引数にしている。これは、データベース化するための前準備だ。
ちなみに、初期設定に暗号資産のシンボルコードを追加すれば、さらに繰り返し処理ができる。

      tick = pybitflyer.API().ticker(product_code=CODE)
      timestamp = tick["timestamp"]
      ltp = tick["ltp"]
      ask = tick["best_ask"]
      bid = tick["best_bid"]
      ask_size = tick["best_ask_size"]
      bid_size = tick["best_bid_size"]
      ask_depth = tick["total_ask_depth"]
      bid_depth = tick["total_ask_depth"]
      volume_product = tick["volume_by_product"]
      volume = tick["volume"]

データベースSQLite3を使う

本当は、pandasを使いたかったんだけど、携帯電話アプリPythonista3のlaunch_stashではエラーが出てインストールできなかった。だから、Python3内臓のSQLite3を使うことにした。

SQLiteを一言でいうと、オープンソースで軽量のRDBMS(データベース管理システム)です。SQLと名前が似ているため、データベース操作言語の一種と思う方もいますが、SQLiteはデータベースです。
データベースには、OracleをはじめMicrosoft SQL Serverなどの商用データベースが存在します。また、SQLiteと同じくオープンソースのMySQLやPostgreSQLも有名です。

いつものように、拡張モジュールとしてSQLite3をコードの初期設定の上に書く。

import sqlite3

次に、SQLite3のデータベースである拡張子.dbというファイルに接続する。SQLite3の命令文connectは、ファイルがない時に自動で新しいファイルを作ってくれる。

conn = sqlite3.connect('dbファイルパス')

指定したDBファイルが存在しない場合は自動で作成してくれるため、高い可搬性を実現することができます。また、特別な名前である :memory: を使うとRAM上にデータベース、いわゆるインメモリ(若しくはオンメモリ)で作ることもできます。

コードで書くとこうなる。Data_Baseという引数に、furtureというデータベースに接続するという命令だ。次に、coursor()の命令も代入する。おまじないみたいだけど、これをやらないとエラーになる。

"""
初期設定
"""
Data_Base = sqlite3.connect("furture.db")
Data_cur = Data_Base.cursor()

次は、データベースのテーブルの作成だ。Excelの中にあるデータ項目を入れるシートだと思ってくれればいいかな。次は、while文の下に入れるデータベースに情報を加える方法だ。

データベースにはさまざまな種類のデータが格納されています。そのデータはバラバラではなく、データの種類ごとに規則正しく保存されているのが特徴です。このデータベースの種類ごとの単位を「テーブル」と呼びます。
データベースのテーブルはExcelで例えられることが多く、Excelのシートがテーブルを表します。データベースは複数のテーブルを保持し、テーブルごとにデータを管理しています。

今回は、ティッカーの11情報全てをデータベースにするから、11項目作る必要がある。
CREATE TABLE IF NOT EXISTS furtureというのは、sqlite3でfurtureというテーブルがなければ新しく作りますという内容の命令文だ。
次は、データベースに書き込む命令。最後は、データベースを閉じる命令だ。

Data_Base.cursor().execute('CREATE TABLE IF NOT EXISTS furture(symbol text, timestamp datatime, lpt real, ask real, bid real, ask_size real, bid_size real, ask_depth real, bid_depth real, volume_product real, volume real)')
Data_Base.commit()
Data_Base.close()

書き込む命令と閉じる命令は、面倒だけどデータが変更された都度やらないといけないらしい。テーブルの準備ができたら、データベースにデータを差し込むための準備をする

データを挿入するSQLは以下の形をしています。
insert into テーブル名(列名、列名、…) values(値、値、…)
insert文を実行した後は、commitメソッドを実行する必要があります。テーブルへの挿入がcommitによりテーブルに反映されます。commitメソッドを実行しないとテーブルへの挿入は行われません。

最初の二行は、データベースを開いて、命令を出せる状態にしている。三行目は、11個の格納箱を作り、データベースへと情報を格納する命令だ。そして、最後が書き込みの処理になる。

Data_Base = sqlite3.connect("furture.db")
Data_cur = Data_Base.cursor()
Data_cur.execute('INSERT INTO furture values (?,?,?,?,?,?,?,?,?,?,?)',[SYMBOL, timestamp, ltp, ask, bid, ask_size, bid_size, ask_depth, bid_depth, volume_product, volume])
Data_Base.commit()

正しくデータベースにデータが格納したか確認するために、データを抽出して画面にprintしてみよう。

この記事では、Pythonのsqlite3を使ってテーブルのデータの抽出(SELECT)を行う処理について説明しています。
具体的には単純なSELECT文、条件を絞り込んだSELECT、テーブル同士をJOINした場合のSELECTについてのサンプルソースを使いながら解説していきたいと思います。

SELECT * FROM furtureの命令文で全てのデータを抽出する。そして、先ほど説明したfor文を使いデータを出力してみた。そして、close()でデータベースを閉じている。

"""
実行結果の表示
"""
      Data_cur.execute("SELECT * FROM furture")
      for Row in Data_cur:
         print(str(Row[0]) + "," + str(Row[1]) + "," + str(Row[2]))
      Data_Base.close()

試しに出力すると何故かデータが重複していた。色々なサイトを調べてもどうしてこうなったのかわからなかった。

試しにデータベースの中身を見るアプリで確認してみると、データは重複していなかった。print出力が間違っていたようだ。

今回は、csvファイルに11データ分を出力しているから、csvを作るコードも修正した。念のため、csvデータの重複も確認したけど、こちらも問題なかった。

今回出来上がったコードはこちら。
次回は、データベースから情報を取り出すことに挑戦しよう。

# -*- coding: utf-8 -*- #
"""
We crush capitalism.
"""

import pybitflyer
import csv
import time
import sqlite3
"""
初期設定
"""
Data_Base = sqlite3.connect("furture.db")
Data_cur = Data_Base.cursor()
Data_cur.execute('CREATE TABLE IF NOT EXISTS furture(symbol text, timestamp datatime, lpt real, ask real, bid real, ask_size real, bid_size real, ask_depth real, bid_depth real, volume_product real, volume real)')
Data_Base.commit()
Data_Base.close()

Start_time = time.perf_counter()
Ticker_symbol = ["BTC""ETH"]

while True:
   print(Start_time)
   print(time.perf_counter())
   """
   ティッカー操作処理
   """
   for SYMBOL in Ticker_symbol:
      """
      ティッカーからデータ取得
      """
      CODE = SYMBOL + "_JPY"
      tick = pybitflyer.API().ticker(product_code=CODE)
      timestamp = tick["timestamp"]
      ltp = tick["ltp"]
      ask = tick["best_ask"]
      bid = tick["best_bid"]
      ask_size = tick["best_ask_size"]
      bid_size = tick["best_bid_size"]
      ask_depth = tick["total_ask_depth"]
      bid_depth = tick["total_ask_depth"]
      volume_product = tick["volume_by_product"]
      volume = tick["volume"]
      """
      データベースへ格納
      """
      Data_Base = sqlite3.connect("furture.db")
      Data_cur = Data_Base.cursor()
      Data_cur.execute('INSERT INTO furture values (?,?,?,?,?,?,?,?,?,?,?)',[SYMBOL, timestamp, ltp, ask, bid, ask_size, bid_size, ask_depth, bid_depth, volume_product, volume])
      Data_Base.commit()
      """
      実行結果の表示
      """
      Data_cur.execute("SELECT * FROM furture")
      for Row in Data_cur:
         print(str(Row[0]) + "," + str(Row[1]) + "," + str(Row[2]))
      Data_Base.close()
      """
      CSVへの書き込む
      """
      with open('furture.csv','a',newline=''as files:
         writer = csv.writer(files)
         writer.writerow([SYMBOL,str(timestamp),str(ltp),str(ask),str(bid),str(ask_size),str(bid_size),str(ask_depth),str(bid_depth),str(volume_product),str(volume)])
   time.sleep((10 + Start_time ) - time.perf_counter())
   Start_time = Start_time + 10

目次

次の記事

前の記事

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