mirror of
https://github.com/ZhuLinsen/daily_stock_analysis
synced 2026-09-20 10:53:33 +08:00
fix: stabilize yfinance dividend TTM fixtures (#2214)
This commit is contained in:
@@ -8,13 +8,11 @@ graceful degradation when yfinance is unavailable.
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from datetime import datetime, timezone
|
||||
import unittest
|
||||
from datetime import datetime, timedelta
|
||||
from datetime import datetime, timezone
|
||||
from unittest.mock import patch, MagicMock
|
||||
|
||||
import pandas as pd
|
||||
import pytz
|
||||
|
||||
from data_provider.yfinance_fundamental_adapter import (
|
||||
YfinanceFundamentalAdapter,
|
||||
@@ -22,6 +20,14 @@ from data_provider.yfinance_fundamental_adapter import (
|
||||
)
|
||||
|
||||
|
||||
_DIVIDEND_EVENT_DATES = (
|
||||
"2025-08-11",
|
||||
"2025-11-10",
|
||||
"2026-02-09",
|
||||
"2026-05-11",
|
||||
)
|
||||
|
||||
|
||||
def _build_mock_ticker(
|
||||
info: dict,
|
||||
income_stmt: pd.DataFrame | None = None,
|
||||
@@ -82,14 +88,6 @@ class TestYfinanceFundamentalAdapter(unittest.TestCase):
|
||||
"trailingAnnualDividendRate": 1.04,
|
||||
"dividendYield": 0.36,
|
||||
}
|
||||
income_df = pd.DataFrame(
|
||||
{
|
||||
pd.Timestamp("2026-03-31"): {"Total Revenue": 1.11e11, "Net Income": 2.95e10},
|
||||
pd.Timestamp("2025-12-31"): {"Total Revenue": 1.24e11, "Net Income": 3.62e10},
|
||||
pd.Timestamp("2025-09-30"): {"Total Revenue": 9.49e10, "Net Income": 2.49e10},
|
||||
pd.Timestamp("2025-06-30"): {"Total Revenue": 9.40e10, "Net Income": 2.34e10},
|
||||
}
|
||||
)
|
||||
# Need at least 5 columns to trigger statement-derived YoY.
|
||||
income_df_with_yoy = pd.DataFrame(
|
||||
{
|
||||
@@ -106,18 +104,10 @@ class TestYfinanceFundamentalAdapter(unittest.TestCase):
|
||||
pd.Timestamp("2025-12-31"): {"Operating Cash Flow": 3.5e10},
|
||||
}
|
||||
)
|
||||
# Use dates relative to now so the 365-day TTM window always
|
||||
# contains all 4 events regardless of when the test runs (#2204).
|
||||
now_ny = datetime.now(pytz.timezone("America/New_York"))
|
||||
dividends = pd.Series(
|
||||
[0.26, 0.26, 0.26, 0.27],
|
||||
index=pd.DatetimeIndex(
|
||||
[
|
||||
(now_ny - timedelta(days=330)).strftime("%Y-%m-%d"),
|
||||
(now_ny - timedelta(days=240)).strftime("%Y-%m-%d"),
|
||||
(now_ny - timedelta(days=150)).strftime("%Y-%m-%d"),
|
||||
(now_ny - timedelta(days=60)).strftime("%Y-%m-%d"),
|
||||
],
|
||||
_DIVIDEND_EVENT_DATES,
|
||||
tz="America/New_York",
|
||||
),
|
||||
name="Dividends",
|
||||
@@ -147,6 +137,7 @@ class TestYfinanceFundamentalAdapter(unittest.TestCase):
|
||||
# info.dividendYield (0.36) is intentionally ignored when TTM cash exists.
|
||||
self.assertAlmostEqual(div["ttm_dividend_yield_pct"], 0.3762, places=4)
|
||||
self.assertEqual(div["currency"], "USD")
|
||||
self.assertEqual(div["events"][0]["ex_dividend_date"], "2026-05-11")
|
||||
self.assertEqual(
|
||||
bundle["belong_boards"],
|
||||
[
|
||||
@@ -160,15 +151,8 @@ class TestYfinanceFundamentalAdapter(unittest.TestCase):
|
||||
# Series. Without coercion, `.items()` yields (column_name, Series), every event
|
||||
# is dropped, and TTM silently falls back to the annual-rate estimate — the real
|
||||
# bug seen on live US/HK/JP/KR/TW reports (24.0 / "0 次" instead of the true sum).
|
||||
# Use dates relative to now so the 365-day TTM window is always satisfied (#2204).
|
||||
now_ny = datetime.now(pytz.timezone("America/New_York"))
|
||||
idx = pd.DatetimeIndex(
|
||||
[
|
||||
(now_ny - timedelta(days=330)).strftime("%Y-%m-%d"),
|
||||
(now_ny - timedelta(days=240)).strftime("%Y-%m-%d"),
|
||||
(now_ny - timedelta(days=150)).strftime("%Y-%m-%d"),
|
||||
(now_ny - timedelta(days=60)).strftime("%Y-%m-%d"),
|
||||
],
|
||||
_DIVIDEND_EVENT_DATES,
|
||||
tz="America/New_York",
|
||||
)
|
||||
dividends_df = pd.DataFrame({"Dividends": [0.26, 0.26, 0.26, 0.27]}, index=idx)
|
||||
@@ -191,7 +175,7 @@ class TestYfinanceFundamentalAdapter(unittest.TestCase):
|
||||
|
||||
def test_ttm_dividend_window_uses_as_of_date_cutoff(self) -> None:
|
||||
idx = pd.DatetimeIndex(
|
||||
["2025-08-11", "2025-11-10", "2026-02-09", "2026-05-11"],
|
||||
_DIVIDEND_EVENT_DATES,
|
||||
tz="America/New_York",
|
||||
)
|
||||
dividends = pd.Series([0.26, 0.26, 0.26, 0.27], index=idx, name="Dividends")
|
||||
|
||||
Reference in New Issue
Block a user