見出し画像

出来高分析の初手としてのデータ取得


はじめに

この記事はデータ活用の初手としてTrading Viewとyfinance、Google Colabを活用して必要な情報を取得するまでを書いた備忘録です。
この状態のスクリプトが横展開効きやすそうだと考え、メモに残します。
最終アウトプットはGoogle Colab上で動作するPythonスクリプトです。Pythonスクリプトだけ欲しい人は目次から飛んでください。

Trading Viewでスクリーニング

fetch_tradingview_tickers関数でデータ取得対象を決めるためにTrading Viewのスクリーナーを用いて条件に一致する銘柄のティッカーコードを取得します。

yfinanceに渡すティッカコードリストを作成するのにTrading Viewを使うことにしたのはフィルター条件の柔軟さと、必要に応じてティッカーコード以外のデータも取得し、掛け合わせることができるためです。
また、スクリーナーの利用にあたって有料プランの契約は必要ありません。

payload内、filterの部分でスクリーニング条件を指定します。
下の例では出来高50万以上、相対ボリューム1.0以上、普通株、東証などを指定しています。

"filter": [
     {"left": "type", "operation": "equal", "right": "stock"},
     {"left": "subtype", "operation": "in_range", "right": ["common", "foreign-issuer"]},
     {"left": "volume","operation": "egreater","right": 500000},
     {"left": "relative_volume_10d_calc","operation": "egreater","right": 1},
     {"left": "exchange", "operation": "equal", "right": "TSE"}
],

自分が指定したい検索条件が分からないときはGUIで条件指定後、F12でデベロッパーツールを開き、Network>Fetch/XHR>scan>PayloadをコピペすればOKです。

yfinanceからデータを取得

取得したティッカーコードに対してdownload_data関数でyfinanceからデータを取得します。

下記の例では5分足のデータを11日分取得し、初日のデータを切り捨てて10日分のデータをcsv出力しています。
なぜか指定期間初日の9:00の出来高が0になってしまう仕様になっているため、+1日して初日のデータを捨てています。

Python スクリプト

import requests
import json
import pandas as pd
import yfinance as yf

def fetch_tradingview_tickers():
    url = 'https://scanner.tradingview.com/japan/scan'
    headers = {
        "Accept-Language": "ja,en-US;q=0.9,en;q=0.8",
        "Origin": "https://jp.tradingview.com/",
        "Referer": "https://jp.tradingview.com/"
    }
    payload = {
        "filter": [
            {"left": "type", "operation": "equal", "right": "stock"},
            {"left": "subtype", "operation": "in_range", "right": ["common", "foreign-issuer"]},
            {"left": "volume","operation": "egreater","right": 500000},
            {"left": "relative_volume_10d_calc","operation": "egreater","right": 1},
            {"left": "exchange", "operation": "equal", "right": "TSE"}
        ],
        "options": {"lang": "ja"},
        "markets": ["japan"],
        "symbols": {"query": {"types": []}, "tickers": [], "groups": [{"type": "index", "values": ["TVC:NI225"]}]},
        "columns": ["name"],
        "sort": {"sortBy": "name", "sortOrder": "asc"},
        "price_conversion": {"to_symbol": False}
    }
    response = requests.post(url, headers=headers, json=payload)
    response.raise_for_status()
    return pd.DataFrame([stock['d'] for stock in response.json()["data"]], columns=payload["columns"])

def download_data(ticker_names):
    ticker_symbols = [name + ".T" for name in ticker_names]
    data = yf.download(ticker_symbols, period="11d", interval="5m", group_by='ticker')
    all_data = pd.DataFrame()

    if isinstance(data.columns, pd.MultiIndex):
        for ticker in ticker_symbols:
            if ticker in data.columns.levels[0]:  # ティッカーシンボルが存在するかチェック
                df = data[ticker].dropna().copy()
                df = df[df.index.date > df.index[0].date()]
                df['Ticker'] = ticker
                # 数値データの列のみを整数に変換
                numeric_cols = df.select_dtypes(include=['number']).columns
                df[numeric_cols] = df[numeric_cols].round(0).astype(int)
                all_data = pd.concat([all_data, df])
    else:  # 単一ティッカーの場合
        data = data.dropna().copy()
        data = data[data.index.date > data.index[0].date()]
        data['Ticker'] = ticker_symbols[0]
        # 数値データの列のみを整数に変換
        numeric_cols = data.select_dtypes(include=['number']).columns
        data[numeric_cols] = data[numeric_cols].round(0).astype(int)
        all_data = data

    return all_data

def main():
    try:
        tickers = fetch_tradingview_tickers()
        all_data = download_data(tickers['name'].tolist())
        all_data.to_csv('all_tickers_data.csv')
        print("All tickers have been processed and their data saved in a single CSV file.")
    except requests.HTTPError as e:
        print(f"HTTP error occurred: {e}")
    except json.JSONDecodeError as e:
        print(f"JSON decode error: {e}")
    except Exception as e:
        print(f"An error occurred: {e}")

if __name__ == '__main__':
    main()

活用

スクリーニング条件を変えたい場合はfilterを変更
Trading Viewから取得するデータを増やしたい場合はcolumnsを変更
yfinanceから取得するデータを変更したいときはyf.downloadのパラメータを変更してください

いいなと思ったら応援しよう!