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
71 changes: 52 additions & 19 deletions jquantsapi/apis/v2/fins.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import Any
from typing import Any, Optional

import pandas as pd # type: ignore

Expand All @@ -22,24 +22,42 @@ def execute(
*,
code: str = "",
date_yyyymmdd: str = "",
cursor: str = "",
**kwargs: Any,
) -> pd.DataFrame:
) -> tuple[pd.DataFrame, Optional[str]]:
"""
`/fins/summary` を実行し、財務情報サマリを DataFrame で返す。
v2 `/fins/summary` を実行し、財務情報サマリと cursor を返す。

cursor は API 仕様上、最終ページのレスポンスにのみ含まれます。
"""
url = f"{client.JQUANTS_API_BASE}/fins/summary" # type: ignore[attr-defined]

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

all_data = client._get_paginated( # type: ignore[attr-defined]
"/fins/summary",
params=params,
)
all_data: list[dict[str, Any]] = []
returned_cursor: Optional[str] = None
query = dict(params)

while True:
resp = client._get(url, query) # type: ignore[attr-defined]
payload = resp.json()
all_data.extend(payload.get("data", []))
returned_cursor = payload.get("cursor")

pagination_key = payload.get("pagination_key")
if not pagination_key:
break
query["pagination_key"] = pagination_key

cols = constants.FIN_SUMMARY_COLUMNS_V2
if not all_data:
return pd.DataFrame()
return pd.DataFrame(columns=cols), returned_cursor

df = pd.DataFrame.from_records(all_data)
for col in (
Expand All @@ -57,9 +75,7 @@ def execute(
if sort_cols:
df.sort_values(sort_cols, inplace=True)

# v1 `/fins/statements` と同様に、定義済みカラムの順序で返す
cols = constants.FIN_SUMMARY_COLUMNS_V2
return df[cols].reset_index(drop=True)
return df[cols].reset_index(drop=True), returned_cursor


class FinDetailsApiV2(BaseApi):
Expand All @@ -76,32 +92,49 @@ def execute(
*,
code: str = "",
date_yyyymmdd: str = "",
cursor: str = "",
**kwargs: Any,
) -> pd.DataFrame:
) -> tuple[pd.DataFrame, Optional[str]]:
"""
`/fins/details` を実行し、財務諸表詳細を DataFrame で返す。
v2 `/fins/details` を実行し、財務諸表詳細と cursor を返す。

cursor は API 仕様上、最終ページのレスポンスにのみ含まれます。
"""
url = f"{client.JQUANTS_API_BASE}/fins/details" # type: ignore[attr-defined]

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

all_data = client._get_paginated( # type: ignore[attr-defined]
"/fins/details",
params=params,
)
all_data: list[dict[str, Any]] = []
returned_cursor: Optional[str] = None
query = dict(params)

while True:
resp = client._get(url, query) # type: ignore[attr-defined]
payload = resp.json()
all_data.extend(payload.get("data", []))
returned_cursor = payload.get("cursor")

pagination_key = payload.get("pagination_key")
if not pagination_key:
break
query["pagination_key"] = pagination_key

if not all_data:
return pd.DataFrame()
return pd.DataFrame(), returned_cursor

df = pd.DataFrame.from_records(all_data)
if "DiscDate" in df.columns:
df["DiscDate"] = pd.to_datetime(df["DiscDate"], errors="coerce")
sort_cols = [c for c in ["DiscDate", "DiscTime", "Code"] if c in df.columns]
if sort_cols:
df.sort_values(sort_cols, inplace=True)
return df.reset_index(drop=True)
return df.reset_index(drop=True), returned_cursor


class FinDividendApiV2(BaseApi):
Expand Down
73 changes: 67 additions & 6 deletions jquantsapi/client_v2.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@
else:
import tomli as tomllib

if sys.version_info >= (3, 13):
from warnings import deprecated # type: ignore[attr-defined]
else:
from typing_extensions import deprecated

from jquantsapi import __version__, constants
from jquantsapi.apis.v2.bulk import BulkGetApiV2, BulkListApiV2
from jquantsapi.apis.v2.derivatives import (
Expand Down Expand Up @@ -600,6 +605,9 @@ def get_eq_investor_types(
# ------------------------------------------------------------------
# /fins/summary (path_old: /fins/statements)
# ------------------------------------------------------------------
@deprecated(
"get_fin_summary_cursor() is now available for cursor-based incremental retrieval. Consider using it instead."
)
def get_fin_summary(
self,
code: str = "",
Expand All @@ -614,11 +622,12 @@ def get_fin_summary(
Returns:
pd.DataFrame: 財務情報 (v2のフィールド名で返却)
"""
return self._fin_summary_api.execute(
df, _ = self._fin_summary_api.execute(
self,
code=code,
date_yyyymmdd=date_yyyymmdd,
)
return df

def get_fin_summary_range(
self,
Expand Down Expand Up @@ -664,12 +673,12 @@ def get_fin_summary_range(
buff.append(df)
else:
future = executor.submit(
self.get_fin_summary, date_yyyymmdd=yyyymmdd
self.get_fin_summary_cursor, date_yyyymmdd=yyyymmdd
)
futures[future] = yyyymmdd

for future in as_completed(futures):
df = future.result()
df, _ = future.result()
if df.empty:
continue
buff.append(df)
Expand All @@ -689,9 +698,37 @@ def get_fin_summary_range(
.reset_index(drop=True)
)

def get_fin_summary_cursor(
self,
code: str = "",
date_yyyymmdd: str = "",
cursor: str = "",
) -> tuple[pd.DataFrame, Optional[str]]:
"""
財務情報サマリ cursor 差分取得対応版 (v2: /fins/summary)

cursor パラメータを使用した差分取得はプレミアムプラン限定の機能です。

Args:
code: 銘柄コード
date_yyyymmdd: 開示日 (YYYYMMDD or YYYY-MM-DD)
cursor: 前回レスポンスで返却された cursor。差分取得に使用します。
Returns:
tuple[pd.DataFrame, Optional[str]]: 財務情報サマリと cursor のタプル
"""
return self._fin_summary_api.execute(
self,
code=code,
date_yyyymmdd=date_yyyymmdd,
cursor=cursor,
)

# ------------------------------------------------------------------
# /fins/details (path_old: /fins/fs_details)
# ------------------------------------------------------------------
@deprecated(
"get_fin_details_cursor() is now available for cursor-based incremental retrieval. Consider using it instead."
)
def get_fin_details(
self,
code: str = "",
Expand All @@ -706,11 +743,12 @@ def get_fin_details(
Returns:
pd.DataFrame: 財務諸表詳細 (FS列に各項目が含まれる)
"""
return self._fin_details_api.execute(
df, _ = self._fin_details_api.execute(
self,
code=code,
date_yyyymmdd=date_yyyymmdd,
)
return df

def get_fin_details_range(
self,
Expand Down Expand Up @@ -745,12 +783,12 @@ def get_fin_details_range(
buff.append(df)
else:
future = executor.submit(
self.get_fin_details, date_yyyymmdd=yyyymmdd
self.get_fin_details_cursor, date_yyyymmdd=yyyymmdd
)
futures[future] = yyyymmdd

for future in as_completed(futures):
df = future.result()
df, _ = future.result()
if df.empty:
continue
buff.append(df)
Expand All @@ -770,6 +808,29 @@ def get_fin_details_range(
.reset_index(drop=True)
)

def get_fin_details_cursor(
self,
code: str = "",
date_yyyymmdd: str = "",
cursor: str = "",
) -> tuple[pd.DataFrame, Optional[str]]:
"""
財務諸表詳細 cursor 差分取得対応版 (v2: /fins/details)

Args:
code: 銘柄コード
date_yyyymmdd: 開示日 (YYYYMMDD or YYYY-MM-DD)
cursor: 前回レスポンスで返却された cursor。差分取得に使用します。
Returns:
tuple[pd.DataFrame, Optional[str]]: 財務諸表詳細と cursor のタプル
"""
return self._fin_details_api.execute(
self,
code=code,
date_yyyymmdd=date_yyyymmdd,
cursor=cursor,
)

# ------------------------------------------------------------------
# /fins/dividend (path_old: /fins/dividend)
# ------------------------------------------------------------------
Expand Down
Loading
Loading