Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ API レスポンスが Dataframe の形式で取得できます。
- get_eq_master - 上場銘柄一覧
- get_eq_bars_daily - 株価日足
- get_fin_summary - 決算サマリー
- get_eq_earnings_cal - 決算発表日
- get_fin_earnings_date - 決算発表予定日
- get_eq_earnings_cal - 決算発表予定日(3・9月期決算会社のみ・翌営業日分)

------------------ Light plan or higher is required ------------------

Expand All @@ -101,6 +102,9 @@ API レスポンスが Dataframe の形式で取得できます。
- get_drv_bars_daily_fut - 先物日足
- get_drv_bars_daily_opt - オプション日足
- get_drv_bars_daily_opt_225 - 日経225オプション日足
- get_edinet_major_shareholders - 大株主状況(EDINET)
- get_edinet_cross_shareholdings - 政策保有株式(EDINET)
- get_edinet_large_volume_shareholders - 大量保有報告書(EDINET)

------------------ Premium plan or higher is required ------------------

Expand Down Expand Up @@ -131,6 +135,7 @@ API レスポンスが Dataframe の形式で取得できます。
- get_list - 銘柄一覧(セクター情報付き)
- get_eq_bars_daily_range - 株価日足(範囲指定)
- get_fin_summary_range - 決算サマリー(範囲指定)
- get_fin_earnings_date_range - 決算発表予定日(公表日の範囲指定)

------------------ Standard plan or higher is required ------------------

Expand Down
147 changes: 147 additions & 0 deletions jquantsapi/apis/v2/edinet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,147 @@
from __future__ import annotations

from typing import Any

import pandas as pd # type: ignore

from jquantsapi.apis.base import BaseApi, SupportsRequest


def _fetch_edinet(
client: SupportsRequest,
path: str,
*,
edinet_code: str = "",
code: str = "",
date_yyyymmdd: str = "",
) -> pd.DataFrame:
"""
EDINET 系 3 エンドポイント共通の取得処理。

クエリ仕様は 3 エンドポイントで共通:
- edinet_code / code / date は任意指定(すべて省略時は API 実行日提出分)
- edinet_code と code の同時指定は不可(API 仕様では 400 エラー)
- ネスト項目(Hldrs / Report 等)は dict / list のまま object 列として保持する
"""
if edinet_code and code:
raise ValueError("edinet_code と code は同時に指定できません。")

params: dict[str, Any] = {}
if edinet_code:
params["edinet_code"] = edinet_code
if code:
params["code"] = code
if date_yyyymmdd:
params["date"] = date_yyyymmdd

all_data = client._get_paginated( # type: ignore[attr-defined]
path,
params=params,
)

if not all_data:
return pd.DataFrame()

df = pd.DataFrame.from_records(all_data)
for col in ("SubDate", "PerSt", "PerEn"):
if col in df.columns:
df[col] = pd.to_datetime(df[col], errors="coerce")
sort_cols = [c for c in ["SubDate", "SubTime", "Code"] if c in df.columns]
if sort_cols:
df.sort_values(sort_cols, inplace=True)
return df.reset_index(drop=True)


class EdinetMajorShareholdersApiV2(BaseApi):
"""
v2 の大株主状況 API (`/edinet/major-shareholders`) のラッパークラス。
"""

name = "edinet_major_shareholders"
version = "v2"

def execute(
self,
client: SupportsRequest,
*,
edinet_code: str = "",
code: str = "",
date_yyyymmdd: str = "",
**kwargs: Any,
) -> pd.DataFrame:
"""
`/edinet/major-shareholders` を実行し、大株主状況を DataFrame で返す。

大株主レコードは `Hldrs` 列に list のまま保持されます。
"""
return _fetch_edinet(
client,
"/edinet/major-shareholders",
edinet_code=edinet_code,
code=code,
date_yyyymmdd=date_yyyymmdd,
)


class EdinetCrossShareholdingsApiV2(BaseApi):
"""
v2 の政策保有株式 API (`/edinet/cross-shareholdings`) のラッパークラス。
"""

name = "edinet_cross_shareholdings"
version = "v2"

def execute(
self,
client: SupportsRequest,
*,
edinet_code: str = "",
code: str = "",
date_yyyymmdd: str = "",
**kwargs: Any,
) -> pd.DataFrame:
"""
`/edinet/cross-shareholdings` を実行し、政策保有株式を DataFrame で返す。

保有主体ブロックは `Report` / `Largest` / `SecondLargest` 列に
dict のまま保持されます(内部に Spec[] / Deem[] の銘柄明細を含む)。
"""
return _fetch_edinet(
client,
"/edinet/cross-shareholdings",
edinet_code=edinet_code,
code=code,
date_yyyymmdd=date_yyyymmdd,
)


class EdinetLargeVolumeShareholdersApiV2(BaseApi):
"""
v2 の大量保有報告書 API (`/edinet/large-volume-shareholders`) のラッパークラス。
"""

name = "edinet_large_volume_shareholders"
version = "v2"

def execute(
self,
client: SupportsRequest,
*,
edinet_code: str = "",
code: str = "",
date_yyyymmdd: str = "",
**kwargs: Any,
) -> pd.DataFrame:
"""
`/edinet/large-volume-shareholders` を実行し、大量保有報告書データを
DataFrame で返す。

提出者及び共同保有者のレコードは `Hldrs` 列に list のまま保持されます。
"""
return _fetch_edinet(
client,
"/edinet/large-volume-shareholders",
edinet_code=edinet_code,
code=code,
date_yyyymmdd=date_yyyymmdd,
)
19 changes: 13 additions & 6 deletions jquantsapi/apis/v2/fins.py
Original file line number Diff line number Diff line change
Expand Up @@ -200,23 +200,30 @@ def execute(
*,
code: str = "",
date_yyyymmdd: str = "",
scheduled_date: str = "",
scheduled_date_yyyymmdd: str = "",
**kwargs: Any,
) -> pd.DataFrame:
"""
`/fins/earnings-date` を実行し、決算発表予定日データを DataFrame で返す。

code・date_yyyymmdd・scheduled_date のいずれか1つの指定が必須です
(2つ以上指定するとAPI側で400エラーになります)。SchDate が未定の
場合は空文字列のままです(pd.to_datetime は空文字を NaT に変換)。
code・date_yyyymmdd・scheduled_date_yyyymmdd のいずれか1つの指定が
必須です(API 仕様。未指定・2つ以上の指定は ValueError)。SchDate
未定の場合は空文字列のままです(pd.to_datetime は空文字を NaT に変換)。
"""
specified = [v for v in (code, date_yyyymmdd, scheduled_date_yyyymmdd) if v]
if len(specified) != 1:
raise ValueError(
"code / date_yyyymmdd / scheduled_date_yyyymmdd の"
"いずれか1つを指定してください。"
)

params: dict[str, Any] = {}
if code:
params["code"] = code
if date_yyyymmdd:
params["date"] = date_yyyymmdd
if scheduled_date:
params["scheduled_date"] = scheduled_date
if scheduled_date_yyyymmdd:
params["scheduled_date"] = scheduled_date_yyyymmdd

all_data = client._get_paginated( # type: ignore[attr-defined]
"/fins/earnings-date",
Expand Down
133 changes: 128 additions & 5 deletions jquantsapi/client_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@
DrvBarsDailyOpt225ApiV2,
DrvBarsDailyOptApiV2,
)
from jquantsapi.apis.v2.edinet import (
EdinetCrossShareholdingsApiV2,
EdinetLargeVolumeShareholdersApiV2,
EdinetMajorShareholdersApiV2,
)
from jquantsapi.apis.v2.equities import (
EqBarsDailyAmApiV2,
EqBarsDailyApiV2,
Expand Down Expand Up @@ -129,6 +134,11 @@ def __init__(self, api_key: Optional[str] = None) -> None:
self._td_list_api = TdListApiV2()
self._td_files_api = TdFilesApiV2()
self._td_bulk_api = TdBulkApiV2()
self._edinet_major_shareholders_api = EdinetMajorShareholdersApiV2()
self._edinet_cross_shareholdings_api = EdinetCrossShareholdingsApiV2()
self._edinet_large_volume_shareholders_api = (
EdinetLargeVolumeShareholdersApiV2()
)

# ------------------------------------------------------------------
# 内部ユーティリティ
Expand Down Expand Up @@ -873,7 +883,7 @@ def get_fin_earnings_date(
self,
code: str = "",
date_yyyymmdd: str = "",
scheduled_date: str = "",
scheduled_date_yyyymmdd: str = "",
) -> pd.DataFrame:
"""
決算発表予定日 (v2: /fins/earnings-date)
Expand All @@ -882,13 +892,13 @@ def get_fin_earnings_date(
(旧 /equities/earnings-calendar)と異なり、決算期によらず全上場銘柄
(REIT等含む)が対象で、予定日の変更・未定の履歴も公表日単位で追跡できます。

code・date_yyyymmdd・scheduled_date のいずれか1つの指定が必須です
(2つ以上指定するとAPI側で400エラーになります)。
code・date_yyyymmdd・scheduled_date_yyyymmdd のいずれか1つの指定が
必須です(未指定・2つ以上の指定は ValueError)。

Args:
code: 銘柄コード。指定時は変更履歴を含む全レコードを返却
date_yyyymmdd: 公表日 (YYYYMMDD or YYYY-MM-DD)。指定日に公表・変更された全銘柄
scheduled_date: 発表予定日 (YYYYMMDD or YYYY-MM-DD)。指定日を現在有効な予定日とする全銘柄
scheduled_date_yyyymmdd: 発表予定日 (YYYYMMDD or YYYY-MM-DD)。指定日を現在有効な予定日とする全銘柄
(その後予定日が変更されたレコードはヒットしない点に注意)
Returns:
pd.DataFrame: 決算発表予定日データ(PubDate/SchDate/FQName/FYE/Code/CoName/CoNameEn)
Expand All @@ -897,9 +907,34 @@ def get_fin_earnings_date(
self,
code=code,
date_yyyymmdd=date_yyyymmdd,
scheduled_date=scheduled_date,
scheduled_date_yyyymmdd=scheduled_date_yyyymmdd,
)

def get_fin_earnings_date_range(
self,
start_dt: DatetimeLike = "20140901",
end_dt: DatetimeLike = datetime.now(),
) -> pd.DataFrame:
"""
決算発表予定日データを公表日の範囲指定で取得 (v2: /fins/earnings-date)
"""
buff: list[pd.DataFrame] = []
dates = pd.date_range(start_dt, end_dt, freq="D")
with ThreadPoolExecutor(max_workers=self.MAX_WORKERS) as executor:
futures = [
executor.submit(
self.get_fin_earnings_date, date_yyyymmdd=s.strftime("%Y-%m-%d")
)
for s in dates
]
for future in as_completed(futures):
df = future.result()
if not df.empty:
buff.append(df)
if not buff:
return pd.DataFrame()
return pd.concat(buff).sort_values(["PubDate", "Code"]).reset_index(drop=True)

# ------------------------------------------------------------------
# /equities/earnings-calendar (path_old: /fins/announcement)
# ------------------------------------------------------------------
Expand Down Expand Up @@ -1517,6 +1552,94 @@ def download_bulk_by_endpoint(
for chunk in response.iter_content(chunk_size=8192):
f.write(chunk)

# ------------------------------------------------------------------
# EDINET API (v2: /edinet/*)
# ------------------------------------------------------------------
def get_edinet_major_shareholders(
self,
edinet_code: str = "",
code: str = "",
date_yyyymmdd: str = "",
) -> pd.DataFrame:
"""
大株主状況 (v2: /edinet/major-shareholders)

有価証券報告書に記載されている大株主の状況を取得できます。
edinet_code と code の同時指定はできません。すべて省略した場合は
API 実行日に提出された全有報のデータを返します。
大株主レコードは Hldrs 列に list のまま保持されます。

Args:
edinet_code: EDINETコード (例: E03814)
code: 銘柄コード
date_yyyymmdd: 提出日
Returns:
pd.DataFrame: 大株主状況データ
"""
return self._edinet_major_shareholders_api.execute(
self,
edinet_code=edinet_code,
code=code,
date_yyyymmdd=date_yyyymmdd,
)

def get_edinet_cross_shareholdings(
self,
edinet_code: str = "",
code: str = "",
date_yyyymmdd: str = "",
) -> pd.DataFrame:
"""
政策保有株式 (v2: /edinet/cross-shareholdings)

有価証券報告書「株式の保有状況」に記載されている政策保有株式を取得できます。
edinet_code と code の同時指定はできません。すべて省略した場合は
API 実行日に提出された全有報のデータを返します。
保有主体ブロックは Report / Largest / SecondLargest 列に dict のまま
保持されます(内部に Spec[] / Deem[] の銘柄明細を含む)。

Args:
edinet_code: EDINETコード (例: E02367)
code: 銘柄コード
date_yyyymmdd: 提出日
Returns:
pd.DataFrame: 政策保有株式データ
"""
return self._edinet_cross_shareholdings_api.execute(
self,
edinet_code=edinet_code,
code=code,
date_yyyymmdd=date_yyyymmdd,
)

def get_edinet_large_volume_shareholders(
self,
edinet_code: str = "",
code: str = "",
date_yyyymmdd: str = "",
) -> pd.DataFrame:
"""
大量保有報告書 (v2: /edinet/large-volume-shareholders)

大量保有報告書・変更報告書に記載されている発行者、提出者情報を取得できます。
edinet_code と code の同時指定はできません。すべて省略した場合は
API 実行日に提出された全書類のデータを返します。
提出者及び共同保有者のレコードは Hldrs 列に list のまま保持されます。

Args:
edinet_code: 発行者の EDINETコード (例: E03814)
code: 発行者の銘柄コード
date_yyyymmdd: 提出日
Returns:
pd.DataFrame: 大量保有報告書データ
"""
return self._edinet_large_volume_shareholders_api.execute(
self,
edinet_code=edinet_code,
code=code,
date_yyyymmdd=date_yyyymmdd,
)

# ------------------------------------------------------------------
# TDnet/適時開示 API (v2: /td/*)
# ------------------------------------------------------------------
Expand Down
Loading
Loading