From 50a62736b4755d7538c1603afbe6e98a7656babb Mon Sep 17 00:00:00 2001 From: jevwithwind Date: Sat, 4 Jul 2026 11:40:49 +0900 Subject: [PATCH] =?UTF-8?q?fins/summary=20=E3=81=AE=20Code=20=E5=88=97?= =?UTF-8?q?=E3=82=92=E6=96=87=E5=AD=97=E5=88=97=E3=81=AB=E5=9B=BA=E5=AE=9A?= =?UTF-8?q?=E3=81=97=20float=20=E5=8C=96=20(7203.0)=20=E3=82=92=E9=98=B2?= =?UTF-8?q?=E6=AD=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit issue #108 で報告された事象への対応。Code が数値で返却され欠損値と 混在すると float 化して "7203.0" となるため、DataFrame 化の前に レコード単位で文字列へ変換する。数値コード・英数字コードのテストを追加。 Co-Authored-By: Claude Fable 5 --- jquantsapi/apis/v2/fins.py | 7 +++++++ tests/test_client_v2.py | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/jquantsapi/apis/v2/fins.py b/jquantsapi/apis/v2/fins.py index 989286c..ec586aa 100644 --- a/jquantsapi/apis/v2/fins.py +++ b/jquantsapi/apis/v2/fins.py @@ -59,6 +59,13 @@ def execute( if not all_data: return pd.DataFrame(columns=cols), returned_cursor + # Code が数値で返却されると、欠損値との混在時に float 化して + # "7203.0" のようになるため、DataFrame 化の前に文字列へ固定する + for record in all_data: + record_code = record.get("Code") + if record_code is not None: + record["Code"] = str(record_code) + df = pd.DataFrame.from_records(all_data) for col in ( "DiscDate", diff --git a/tests/test_client_v2.py b/tests/test_client_v2.py index 8efeaa7..577e9e4 100644 --- a/tests/test_client_v2.py +++ b/tests/test_client_v2.py @@ -700,6 +700,42 @@ def test_get_fin_summary_cursor_with_pagination(): assert mock_get.call_count == 2 +def test_get_fin_summary_cursor_numeric_code_stays_string(): + """Codeが数値で返却され欠損値と混在してもfloat化せず文字列のまま保持されることを確認 (#108)""" + record_numeric = dict(FIN_SUMMARY_RECORD) + record_numeric["Code"] = 7203 + record_missing = dict(FIN_SUMMARY_RECORD) + record_missing["Code"] = None + ret_value = {"data": [record_numeric, record_missing]} + + with patch.object( + jquantsapi.ClientV2, "_load_config", return_value={"api_key": "dummy_key"} + ), patch.object(jquantsapi.ClientV2, "_get") as mock_get: + mock_get.return_value.json.return_value = ret_value + + cli = jquantsapi.ClientV2() + df, _ = cli.get_fin_summary_cursor() + assert len(df) == 2 + assert df["Code"].isna().sum() == 1 + assert df["Code"].dropna().tolist() == ["7203"] + + +def test_get_fin_summary_cursor_alphanumeric_code_preserved(): + """2024年以降の英数字銘柄コード(例: 186A)が文字列のまま保持されることを確認 (#108)""" + record_alnum = dict(FIN_SUMMARY_RECORD) + record_alnum["Code"] = "186A" + ret_value = {"data": [record_alnum]} + + with patch.object( + jquantsapi.ClientV2, "_load_config", return_value={"api_key": "dummy_key"} + ), patch.object(jquantsapi.ClientV2, "_get") as mock_get: + mock_get.return_value.json.return_value = ret_value + + cli = jquantsapi.ClientV2() + df, _ = cli.get_fin_summary_cursor() + assert df["Code"].tolist() == ["186A"] + + def test_get_fin_details_cursor(): """get_fin_details_cursorがtuple(DataFrame, cursor)を返すことを確認""" ret_value = {"data": [FIN_DETAILS_RECORD]}