K_DM Book
用語集
対象者 標準
対象者別の入口 →

対象者の設定はこのブラウザの中にだけ保存されます。

言語 JA

J-Quants API

05.4.4

J-Quants API

最終更新 2024-08-02 読了時間 9 分
まとめ
J-Quants API は日本取引所グループ(JPX)が提供する日本株のデータ API で、株価・上場銘柄一覧・決算短信の財務数値を 1 つの認証で取れます。このページでは公式クライアント jquantsapi.Client で 2022 年 7 月 25〜26 日の全銘柄株価を取ったあと、requests で直接 /listed/info を呼んで約 4,000 社の一覧を DataFrame にし、Sector17CodeName の value_counts() を円グラフ、ScaleCategory で絞った大型・中型株を plotly のツリーマップにします。後半では /fins/statements で社名に「塗料」「ペイント」を含む会社の決算短信を集め、DisclosedDate の年と TypeOfCurrentPeriod から「2023-2Q」のような決算期ラベルを作って、seaborn.barplot(hue="決算期") で EPS の推移を会社ごとに並べます。読み終えると、認証トークンの取り方と 3 つのエンドポイントの返り値の形が分かり、業種やキーワードを替えて同じ比較ができるようになります。

直感 #

日本株の分析で最初に困るのは「全銘柄の一覧と財務数値をどこから取るか」です。J-Quants は JPX 公式のため、銘柄コード・業種コード・規模区分が取引所の定義どおりに揃っており、決算短信の数値も NetSales や EarningsPerShare のような固定の列名で返ります。使い方は 3 段階で、まずリフレッシュトークンから有効期限 24 時間の idToken を取り、次に Authorization: Bearer <idToken> ヘッダーを付けて /listed/info などのエンドポイントを呼び、返ってきた JSON を pd.DataFrame にして集計します。株価は公式クライアントが日付の範囲指定を肩代わりしてくれるので、認証情報を渡すだけで全銘柄分が DataFrame で届きます。

J-Quants API を使ってみる #

利用には J-Quants のアカウントが必要で、Python からは公式の jquants-api-client か、API仕様書 に沿った requests の直接呼び出しで使います。まず公式クライアントで株価を 2 日分取り、返り値の形を確認します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
import os
import time
from datetime import datetime

import jquantsapi
import pandas as pd
import requests
from dateutil import tz

REFRESH_TOKEN: str = os.environ.get("JQ_REFRESH_TOKEN")
my_mail_address: str = os.environ.get("JQ_MAIL_ADDRESS")
my_password: str = os.environ.get("JQ_PASSWORD")
cli = jquantsapi.Client(mail_address=my_mail_address, password=my_password)
df = cli.get_price_range(
    start_dt=datetime(2022, 7, 25, tzinfo=tz.gettz("Asia/Tokyo")),
    end_dt=datetime(2022, 7, 26, tzinfo=tz.gettz("Asia/Tokyo")),
)
print(df)
           Date   Code    Open    High     Low   Close UpperLimit LowerLimit  \
0    2022-07-25  13010  3615.0  3660.0  3615.0  3630.0          0          0   
0    2022-07-26  13010  3615.0  3640.0  3610.0  3635.0          0          0   
1    2022-07-25  13050  2026.5  2037.0  2022.0  2023.0          0          0   
1    2022-07-26  13050  2026.0  2029.5  2022.0  2023.5          0          0   
2    2022-07-25  13060  2002.5  2015.0  2000.0  2001.0          0          0   
...         ...    ...     ...     ...     ...     ...        ...        ...   
4191 2022-07-26  99950   403.0   404.0   402.0   404.0          0          0   
4192 2022-07-25  99960  1274.0  1274.0  1263.0  1267.0          0          0   
4192 2022-07-26  99960  1254.0  1266.0  1254.0  1255.0          0          0   
4193 2022-07-25  99970   829.0   831.0   816.0   826.0          0          0   
4193 2022-07-26  99970   826.0   827.0   816.0   825.0          0          0   

        Volume  TurnoverValue  AdjustmentFactor  AdjustmentOpen  \
0       8100.0   2.942050e+07               1.0          3615.0   
0       8500.0   3.083550e+07               1.0          3615.0   
1      54410.0   1.103787e+08               1.0          2026.5   
1      22950.0   4.646586e+07               1.0          2026.0   
2     943830.0   1.891360e+09               1.0          2002.5   
...        ...            ...               ...             ...   
4191   13000.0   5.240900e+06               1.0           403.0   
4192    1500.0   1.902700e+06               1.0          1274.0   
4192    4000.0   5.021300e+06               1.0          1254.0   
4193  151200.0   1.245601e+08               1.0           829.0   
4193  133600.0   1.099946e+08               1.0           826.0   

      AdjustmentHigh  AdjustmentLow  AdjustmentClose  AdjustmentVolume  
0             3660.0         3615.0           3630.0            8100.0  
0             3640.0         3610.0           3635.0            8500.0  
1             2037.0         2022.0           2023.0           54410.0  
1             2029.5         2022.0           2023.5           22950.0  
2             2015.0         2000.0           2001.0          943830.0  
...              ...            ...              ...               ...  
4191           404.0          402.0            404.0           13000.0  
4192          1274.0         1263.0           1267.0            1500.0  
4192          1266.0         1254.0           1255.0            4000.0  
4193           831.0          816.0            826.0          151200.0  
4193           827.0          816.0            825.0          133600.0  

[8388 rows x 16 columns]

上場銘柄一覧(/listed/info) #

銘柄コード・会社名・17 業種・33 業種・規模区分が入った一覧を返すエンドポイントです(J-Quants API - listed info)。requests で直接呼ぶ関数を用意します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
def get_listed_companies(idToken: str):
    """上場銘柄一覧を習得する

    Args:
        idToken (str): idToken

    Returns:
        listed_companies (pd.DataFrame): 上場銘柄が記録されたデータフレーム
    """
    r = requests.get(
        "https://api.jquants.com/v1/listed/info",
        headers={"Authorization": "Bearer {}".format(idToken)},
    )
    if r.status_code == requests.codes.ok:
        listed_companies = pd.DataFrame(r.json()["info"]).set_index("Code")
        return listed_companies
    else:
        return None
1
2
3
4
5
6
7
r_post = requests.post(
    f"https://api.jquants.com/v1/token/auth_refresh?refreshtoken={REFRESH_TOKEN}"
)
idToken = r_post.json()["idToken"]

listed_companies = get_listed_companies(idToken)
listed_companies.head()

DateCompanyNameCompanyNameEnglishSector17CodeSector17CodeNameSector33CodeSector33CodeNameScaleCategoryMarketCodeMarketCodeName
Code
130102023-12-06極洋KYOKUYO CO.,LTD.1食品0050水産・農林業TOPIX Small 20111プライム
130502023-12-06大和アセットマネジメント株式会社 iFreeETF TOPIX(年1回決算型)iFreeETF TOPIX (Yearly Dividend Type)99その他9999その他-0109その他
130602023-12-06野村アセットマネジメント株式会社 NEXT FUNDS TOPIX連動型上場投信NEXT FUNDS TOPIX Exchange Traded Fund99その他9999その他-0109その他
130802023-12-06日興アセットマネジメント株式会社  上場インデックスファンドTOPIXNikko Exchange Traded Index Fund TOPIX99その他9999その他-0109その他
130902023-12-06野村アセットマネジメント株式会社 NEXT FUNDS ChinaAMC・中国株式・上証50...NEXT FUNDS ChinaAMC SSE50 Index Exchange Trade...99その他9999その他-0109その他
1
2
3
4
paint_companies = listed_companies[
    listed_companies["CompanyName"].str.contains("塗料|ペイント")
]
paint_companies

DateCompanyNameCompanyNameEnglishSector17CodeSector17CodeNameSector33CodeSector33CodeNameScaleCategoryMarketCodeMarketCodeName
Code
461102023-12-06大日本塗料Dai Nippon Toryo Company,Limited4素材・化学3200化学TOPIX Small 20111プライム
461202023-12-06日本ペイントホールディングスNIPPON PAINT HOLDINGS CO.,LTD.4素材・化学3200化学TOPIX Mid4000111プライム
461302023-12-06関西ペイントKANSAI PAINT CO.,LTD.4素材・化学3200化学TOPIX Mid4000111プライム
461502023-12-06神東塗料SHINTO PAINT COMPANY,LIMITED4素材・化学3200化学TOPIX Small 20112スタンダード
461602023-12-06川上塗料KAWAKAMI PAINT MANUFACTURING CO.,LTD.4素材・化学3200化学-0112スタンダード
461702023-12-06中国塗料Chugoku Marine Paints,Ltd.4素材・化学3200化学TOPIX Small 10111プライム
461902023-12-06日本特殊塗料Nihon Tokushu Toryo Co.,Ltd.4素材・化学3200化学TOPIX Small 20112スタンダード
462102023-12-06ロックペイントROCK PAINT CO.,LTD.4素材・化学3200化学-0112スタンダード
462402023-12-06イサム塗料Isamu Paint Co.,Ltd.4素材・化学3200化学-0112スタンダード

セクターの分布 #

一覧の Sector17CodeName 列は東証の 17 業種区分(TOPIX-17 シリーズ)です。業種ごとの銘柄数を数えて matplotlib.pyplot.pie の円グラフにし、上場企業の構成を俯瞰します。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
import matplotlib.pyplot as plt
import seaborn as sns

sector17_distribution = listed_companies["Sector17CodeName"].value_counts()
colors = sns.color_palette("Set2")

plt.figure(figsize=(10, 10))
plt.pie(
    sector17_distribution,
    labels=sector17_distribution.index,
    colors=colors,
    autopct="%.0f%%",
)
plt.show()

matplotlib.pyplot.pie — Matplotlib 3.8.3 documentationの図

規模コード #

ScaleCategory 列は時価総額と流動性による規模区分(東証規模別株価指数)で、TOPIX Core30・Large70・Mid400・Small の値を取ります(列の定義は 上場銘柄一覧(/listed/info) を参照)。大型・中型の 500 社に絞り、17 業種 → 33 業種の階層をツリーマップで面積として見ます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
import plotly.express as px

midcap_categories = ["TOPIX Mid400", "TOPIX Large70", "TOPIX Core30"]

df = px.data.tips()
fig = px.treemap(
    listed_companies[listed_companies["ScaleCategory"].isin(midcap_categories)],
    path=["Sector17CodeName", "Sector33CodeName"],
)
fig.show()

df = px.data.tips()
fig = px.treemap(
    listed_companies[listed_companies["ScaleCategory"].isin(midcap_categories)],
    path=["Sector17CodeName", "Sector33CodeName", "ScaleCategory"],
)
fig.show()

財務情報の取得 #

/fins/statements は決算短信の数値を銘柄コードごとに返すエンドポイントです(財務情報(/fins/statements))。列名は TDnet の インターフェイス仕様 に対応しています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
def get_statements(idToken, code):
    time.sleep(0.5)
    r = requests.get(
        f"https://api.jquants.com/v1/fins/statements?code={code}",
        headers={"Authorization": "Bearer {}".format(idToken)},
    )
    if r.status_code == requests.codes.ok:
        return r.json()["statements"]
    else:
        return None
1
2
res = get_statements(idToken, 86970)
res
[{'DisclosedDate': '2022-01-27',
  'DisclosedTime': '12:00:00',
  'LocalCode': '86970',
  'DisclosureNumber': '20220126573026',
  'TypeOfDocument': '3QFinancialStatements_Consolidated_IFRS',
  'TypeOfCurrentPeriod': '3Q',
  'CurrentPeriodStartDate': '2021-04-01',
  'CurrentPeriodEndDate': '2021-12-31',
  'CurrentFiscalYearStartDate': '2021-04-01',
  'CurrentFiscalYearEndDate': '2022-03-31',
  'NextFiscalYearStartDate': '',
  'NextFiscalYearEndDate': '',
  'NetSales': '100586000000',
  'OperatingProfit': '55967000000',
  'OrdinaryProfit': '',
  'Profit': '38013000000',
  'EarningsPerShare': '71.71',
  'DilutedEarningsPerShare': '',
  'TotalAssets': '62076519000000',
  'Equity': '311381000000',
  ...
  'NonConsolidatedProfit': '',
  'NonConsolidatedEarningsPerShare': '',
  'NonConsolidatedTotalAssets': '',
  'NonConsolidatedEquity': '',
  'NonConsolidatedEquityToAssetRatio': '',
  'NonConsolidatedBookValuePerShare': '',
  'ForecastNonConsolidatedNetSales2ndQuarter': '',
  'ForecastNonConsolidatedOperatingProfit2ndQuarter': '',
  'ForecastNonConsolidatedOrdinaryProfit2ndQuarter': '',
  'ForecastNonConsolidatedProfit2ndQuarter': '',
  'ForecastNonConsolidatedEarningsPerShare2ndQuarter': '',
  'NextYearForecastNonConsolidatedNetSales2ndQuarter': '',
  'NextYearForecastNonConsolidatedOperatingProfit2ndQuarter': '',
  'NextYearForecastNonConsolidatedOrdinaryProfit2ndQuarter': '',
  'NextYearForecastNonConsolidatedProfit2ndQuarter': '',
  'NextYearForecastNonConsolidatedEarningsPerShare2ndQuarter': '',
  'ForecastNonConsolidatedNetSales': '',
  'ForecastNonConsolidatedOperatingProfit': '',
  'ForecastNonConsolidatedOrdinaryProfit': '',
  'ForecastNonConsolidatedProfit': '',
  'ForecastNonConsolidatedEarningsPerShare': '',
  'NextYearForecastNonConsolidatedNetSales': '',
  'NextYearForecastNonConsolidatedOperatingProfit': '',
  'NextYearForecastNonConsolidatedOrdinaryProfit': '',
  'NextYearForecastNonConsolidatedProfit': '',
  'NextYearForecastNonConsolidatedEarningsPerShare': ''}]
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
paint_companies_statements = pd.concat(
    [pd.DataFrame(get_statements(idToken, code)) for code in paint_companies.index]
)

for c in paint_companies_statements.filter(
    regex="Sales|Assets|CashFlows|Profit|Equity|EarningsPerShare"
).columns:
    paint_companies_statements[c] = pd.to_numeric(paint_companies_statements[c])

for c in paint_companies_statements.filter(regex="Date").columns:
    paint_companies_statements[c] = pd.to_datetime(paint_companies_statements[c])
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
sorted_data = paint_companies_statements.groupby(["LocalCode"]).apply(
    lambda x: x.sort_values(["DisclosureNumber"], ascending=False)
)
sorted_data["決算期"] = sorted_data.apply(
    lambda row: f"{row['DisclosedDate'].year}-{row['TypeOfCurrentPeriod']}", axis=1
)
sorted_data["会社名"] = [
    paint_companies.at[code, "CompanyName"] for code in sorted_data["LocalCode"]
]
sorted_data

DisclosedDateDisclosedTimeLocalCodeDisclosureNumberTypeOfDocumentTypeOfCurrentPeriod...決算期会社名
LocalCode
4611082023-11-0914:00:0046110202310205692482QFinancialStatements_Consolidated_JP2Q...2023-2Q大日本塗料
72023-08-0814:00:0046110202307215250341QFinancialStatements_Consolidated_JP1Q...2023-1Q大日本塗料
62023-05-1114:00:004611020230421551091FYFinancialStatements_Consolidated_JPFY...2023-FY大日本塗料
52023-02-0914:00:0046110202301235923253QFinancialStatements_Consolidated_JP3Q...2023-3Q大日本塗料
42022-10-2714:00:004611020221024548184EarnForecastRevision2Q...2022-2Q大日本塗料
4624042023-02-0913:00:0046240202301235925043QFinancialStatements_Consolidated_JP3Q...2023-3Qイサム塗料
32022-11-0713:00:0046240202210245479812QFinancialStatements_Consolidated_JP2Q...2022-2Qイサム塗料
22022-08-0513:00:0046240202207225034911QFinancialStatements_Consolidated_JP1Q...2022-1Qイサム塗料
12022-05-1013:00:004624020220426528461FYFinancialStatements_Consolidated_JPFY...2022-FYイサム塗料
02022-02-0913:00:0046240202201245712373QFinancialStatements_Consolidated_JP3Q...2022-3Qイサム塗料

91 rows × 108 columns

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
plt.figure(figsize=(20, 5))
hue_order = [
    "2021-FY",
    "2021-1Q",
    "2021-2Q",
    "2022-3Q",
    "2022-FY",
    "2022-1Q",
    "2022-2Q",
    "2023-3Q",
    "2023-FY",
    "2023-1Q",
    "2023-2Q",
]
ax = sns.barplot(
    data=sorted_data,
    x="会社名",
    y="EarningsPerShare",
    hue="決算期",
    hue_order=hue_order,
)
for c in ax.containers:
    ax.bar_label(c, rotation=90, fontsize=10)

plt.xticks(rotation=90)
plt.legend(loc="upper left", bbox_to_anchor=(1, 1))
plt.show()

財務情報の取得の図

実行結果の読み方 #

各社の棒が左から右へ 2021-FY から 2023-2Q の順に並び、同じ年度内で 1Q → 2Q → 3Q → FY と EPS が積み上がる階段状の形が基本です。日本ペイントホールディングスのように EPS の絶対値が小さい会社と、関西ペイントのように 100 円を超える会社が並ぶので、比べるのは会社間の高さではなく、各社の階段が年度ごとに高くなっているか(増益か)です。棒が欠けている決算期は、その期の開示が取得期間に含まれていないか、開示年のずれで別のラベルに入っていることを示します。

使いどころと落とし穴 #

idToken は 24 時間、リフレッシュトークンは 1 週間で切れるので、翌日に同じノートブックを動かすと 401 になり、auth_refresh からやり直す必要があります。/fins/statements の数値はすべて文字列で届くため、pd.to_numeric を忘れると barplot が文字列を並べて意味のない図になります。決算期 ラベルは開示年ベースなので、3 月決算の会社の 3Q(12 月締め)は翌年 2 月開示で「翌年-3Q」になり、12 月決算の会社とは 1 年ずれて見えることがあります。正確に揃えるなら CurrentPeriodEndDate の年度を使ってラベルを作り直してください。無料プランは取得できる期間が直近 2 年程度に限られるので、長期の EPS 推移には有料プランか EDINET の XBRL を使います。

まとめ #

J-Quants API は、リフレッシュトークンから idToken を取り、Authorization: Bearer ヘッダーで /listed/info と /fins/statements を呼ぶだけで、日本株の銘柄一覧と決算短信の数値が DataFrame になります。一覧の Sector17CodeName を value_counts() すれば業種構成の円グラフ、ScaleCategory で絞って px.treemap に渡せば規模別のツリーマップ、社名で絞った会社の EarningsPerShare を 決算期 ごとに barplot すれば EPS の推移比較になります。文字列で届く数値の変換と、開示年ベースの決算期ラベルのずれに気をつければ、キーワードを替えるだけで別の業界に同じ分析を回せます。