東証が公開している東証上場銘柄一覧を元に板情報を取得する
東証が公開している東証上場銘柄一覧
こちらから東証上場銘柄一覧(Excel)をダウンロードすることができます。
このデータがあればau株コム証券のkabuステーション®APIを利用して東証の全銘柄のその日の板情報が取得できると思って試してみました。
kabuステーション®APIを利用する時の注意点
情報系のリクエストは秒間10件ていどの流量制限が設けられている。
リクエストされた銘柄は自動でAPI登録銘柄リストに登録され、
50銘柄を超えると以降のリクエストが400 BadRequestになる。
使用するライブラリ
Excelを操作するためopenpyxlをインストールする。
Excelにヘッダ項目を追加
板情報取得に必要なのはB列のコード。
K列に安値、L列に高値、M列に始値、N列に終値、O列に出来高を追加してxlsxで保存する。
xlsだとopenpyxlで操作することができません。
サンプルプログラム1
B列のコードを取得していた情報を取得しK列~O列に設定。
B列がブランクになるまで処理してExcelを保存するサンプルです。
1件処理した後に0.2秒待機させてます。
import urllib.request import json import time import openpyxl from openpyxl.workbook import Workbook # エクセルファイルのパス EXCEL_PATH = "c:\\data\\東証上場銘柄一覧.xlsx" class KabuStationApi(): def __init__(self): """コンストラクタ """ # APIトークン取得 obj = { "APIPassword": "password"} url = "http://localhost:18080/kabusapi/token" res = self.__get_content(url, obj, {}, 'POST') self.token = res["Token"] def add_board_info(self): # 処理開始時刻 start_time = time.time() # Excelファイルを読み込む wb = openpyxl.load_workbook(filename=EXCEL_PATH, data_only=True) # シート ws = wb.worksheets[0] # 開始行番号 rowNo = 2 cd = ws.cell(row=rowNo, column=2).value # 銘柄コードがブランクになるまでループ while cd is not None: # 銘柄コード cd = str(ws.cell(row=rowNo, column=2).value) print(f"銘柄コード:{cd} Start") # 板情報取得用のURL 全て東証の銘柄なので市場コードは1固定 url = "http://localhost:18080/kabusapi/board/" + str(cd) +"@1" param = {"X-API-KEY":self.token} res = self.__get_content(url, {}, param) if len(res) > 0: print(res["SymbolName"]) # 安値 ws.cell(row=rowNo, column=11, value=res["LowPrice"]) # 高値 ws.cell(row=rowNo, column=12, value=res["HighPrice"]) # 始値 ws.cell(row=rowNo, column=13, value=res["OpeningPrice"]) # 終値 ws.cell(row=rowNo, column=14, value=res["CurrentPrice"]) # 出来高 ws.cell(row=rowNo, column=15, value=res["TradingVolume"]) print(f"銘柄コード:{cd} End") # 0.2秒待機 time.sleep(0.2) # 次の行へ rowNo += 1 cd = ws.cell(row=rowNo, column=2).value # 処理終了時刻 end_time = time.time() elapsed_time = end_time - start_time elapsed_hour = str(int(elapsed_time // 3600)).zfill(2) elapsed_minute = str(int((elapsed_time % 3600) // 60)).zfill(2) elapsed_second = str(int((elapsed_time % 3600 % 60))).zfill(2) wb.save(EXCEL_PATH) print(f"経過時間:{elapsed_hour}:{elapsed_minute}:{elapsed_second}:") def __get_content(self, url, body_param, header_param, method="GET"): """指定したURLにリクエストを送信しレスポンスを返す Parameters ---------- url : string url body_param : dict, optional Httpリクエストボディに設定するパラメーター, by default None header_param : dict, optional Httpヘッダに設定するパラメーター, by default {} method : str, optional HTTPメソッド, by default 'GET' Returns ------- dict 取得したデータ """ req = None if body_param is not None: req = urllib.request.Request(url, json.dumps(body_param).encode('utf8'), method=method) else: req = urllib.request.Request(url, method=method) req.add_header('Content-Type', 'application/json') for key, param in header_param.items(): req.add_header(key, param) try: with urllib.request.urlopen(req) as res: return json.loads(res.read()) except urllib.error.HTTPError as e: print(e) return {} except Exception as e: print(e) return {} # インスタンス生成 api = KabuStationApi() # データを取得しExcelの板情報を更新 api.add_board_info()
実行結果
・ ・ ・ ・ 銘柄コード:1390 Start UBS ETF MSCIアジア太平洋株(除く日本) 銘柄コード:1390 End 銘柄コード:1391 Start HTTP Error 400: Bad Request 銘柄コード:1391 End 銘柄コード:1392 Start HTTP Error 400: Bad Request 銘柄コード:1392 End 銘柄コード:1393 Start HTTP Error 400: Bad Request 銘柄コード:1393 End 銘柄コード:1394 Start HTTP Error 400: Bad Request 銘柄コード:1394 End
リファレンスに記載された通りAPI登録銘柄リストに登録された銘柄が50銘柄を超えると以降のリクエストが400 BadRequestになります。
こちらのリファレンスを参考に50件登録したらAPI登録銘柄リストをクリアするようにすればBad Requestは解消されました。
サンプルプログラム2
サンプルプログラム1にAPI登録銘柄リストクリア処理を追加したサンプルです。
import urllib.request import json import time import openpyxl from openpyxl.workbook import Workbook # エクセルファイルのパス EXCEL_PATH = "c:\\data\\東証上場銘柄一覧.xlsx" class KabuStationApi(): def __init__(self): """コンストラクタ """ # APIトークン取得 obj = { "APIPassword": "password"} url = "http://localhost:18080/kabusapi/token" res = self.__get_content(url, obj, {}, 'POST') self.token = res["Token"] print("APIトークン:" + self.token) def add_board_info(self): # 処理開始時刻 start_time = time.time() # Excelファイルを読み込む wb = openpyxl.load_workbook(filename=EXCEL_PATH, data_only=True) # シート ws = wb.worksheets[0] # 開始行番号 rowNo = 2 cd = ws.cell(row=rowNo, column=2).value # 処理前にAPI登録銘柄リストをクリア cnt = 0 self.__clear_register() # 銘柄コードがブランクになるまでループ while cd is not None: # 銘柄コード cd = str(ws.cell(row=rowNo, column=2).value) print(f"銘柄コード:{cd} Start") # 板情報取得用のURL 全て東証の銘柄なので市場コードは1固定 url = "http://localhost:18080/kabusapi/board/" + str(cd) +"@1" param = {"X-API-KEY":self.token} res = self.__get_content(url, {}, param) if len(res) > 0: print(res["SymbolName"]) # 安値 ws.cell(row=rowNo, column=11, value=res["LowPrice"]) # 高値 ws.cell(row=rowNo, column=12, value=res["HighPrice"]) # 始値 ws.cell(row=rowNo, column=13, value=res["OpeningPrice"]) # 終値 ws.cell(row=rowNo, column=14, value=res["CurrentPrice"]) # 出来高 ws.cell(row=rowNo, column=15, value=res["TradingVolume"]) print(f"銘柄コード:{cd} End") # 0.2秒待機 time.sleep(0.2) # 次の行へ rowNo += 1 cd = ws.cell(row=rowNo, column=2).value cnt += 1 # API登録銘柄が50になった場合登録状態をクリアする if cnt == 50: cnt = 0 self.__clear_register() # 処理終了時刻 end_time = time.time() elapsed_time = end_time - start_time elapsed_hour = str(int(elapsed_time // 3600)).zfill(2) elapsed_minute = str(int((elapsed_time % 3600) // 60)).zfill(2) elapsed_second = str(int((elapsed_time % 3600 % 60))).zfill(2) wb.save(EXCEL_PATH) print(f"経過時間:{elapsed_hour}:{elapsed_minute}:{elapsed_second}:") def __get_content(self, url, body_param, header_param, method="GET"): """指定したURLにリクエストを送信しレスポンスを返す Parameters ---------- url : string url body_param : dict, optional Httpリクエストボディに設定するパラメーター, by default None header_param : dict, optional Httpヘッダに設定するパラメーター, by default {} method : str, optional HTTPメソッド, by default 'GET' Returns ------- dict 取得したデータ """ req = None if body_param is not None: req = urllib.request.Request(url, json.dumps(body_param).encode('utf8'), method=method) else: req = urllib.request.Request(url, method=method) req.add_header('Content-Type', 'application/json') for key, param in header_param.items(): req.add_header(key, param) try: with urllib.request.urlopen(req) as res: return json.loads(res.read()) except urllib.error.HTTPError as e: print(e) return {} except Exception as e: print(e) return {} def __clear_register(self): """API登録銘柄リストをクリアする """ url = "http://localhost:18080/kabusapi/unregister/all" param = {"X-API-KEY":self.token} print("登録銘柄クリア Start") res = self.__put_content(url, {}, param) print("登録銘柄クリア End") return res def __put_content(self, url, body_param, header_param): """指定したURLにリクエストを送信しレスポンスを返す Parameters ---------- url : string url body_param : dict, optional Httpリクエストボディに設定するパラメーター, by default None header_param : dict, optional Httpヘッダに設定するパラメーター, by default {} method : str, optional HTTPメソッド, by default 'GET' Returns ------- dict 取得したデータ """ if body_param is not None: req = urllib.request.Request(url, json.dumps(body_param).encode('utf8'), method="PUT") else: req = urllib.request.Request(url, method="PUT") req.add_header('Content-Type', 'application/json') for key, param in header_param.items(): req.add_header(key, param) try: with urllib.request.urlopen(req) as res: return json.loads(res.read()) except urllib.error.HTTPError as e: print(e) return {} except Exception as e: print(e) return {} # インスタンス生成 api = KabuStationApi() # データを取得しExcelの板情報を更新 api.add_board_info()
実行結果
・ ・ ・ ・ 銘柄コード:9993 Start ヤマザワ 銘柄コード:9993 End 銘柄コード:9994 Start やまや 銘柄コード:9994 End 銘柄コード:9995 Start グローセル 銘柄コード:9995 End 銘柄コード:9996 Start サトー商会 銘柄コード:9996 End 銘柄コード:9997 Start ベルーナ 銘柄コード:9997 End 経過時間:05:57:15:
一部ブランクの銘柄がありまが、おそらく出来高0の銘柄。
0.2秒待機しましたが、レスポンスが返ってくるまで数秒かかったので全銘柄取得するのに約6時間かかりました・・・
試す場合は待機時間等に気を付けて自己責任でお願いします。