Files
daily_stock_analysis/tests/test_yfinance_jp_kr_indices.py
zhulinsen ade3b4cb6e feat: add JP KR market review support (#1822)
* feat: add JP KR market review support

* fix(review-feedback-1822): update the Market Light schema/service support before accepting these

* fix(review-feedback-1822): add JP/KR to daily market context before accepting them and update

* fix(review-feedback-1822): add English JP/KR strategy text or make the renderer language-aware

* fix(review-feedback-1822): update the prompt role/shell alongside the new accepted regions

* fix(review-feedback-1822): 修正 PR 描述中的过期验证结论,并补充/澄清 JP/KR Yahoo Finance 指数兼容性证据或在线验证边界

* fix(review-feedback-1822): 收敛 Market Light 告警契约与用户文档同步问题

* fix(review-feedback-1822): 修正后再合入

* fix(review-feedback-1822): 补齐外部 Yahoo Finance 指数接入与运行时配置变更的兼容性/迁移证据,并修正 PR 描述中与当前 CI 状态不一致的内容

* fix(review-feedback-1822): 当前 CI 状态为 failure,且阻断型 backend-gate 失败

* fix(review-feedback-1822): 修复 MARKET REVIEW REGION 逗号值在交易日过滤与配置 schema 中的契约漂移,并补充对应回归测试

* fix(review-feedback-1822): 收敛 PR 描述中的验证状态与用户可见 Web 改动证据

* fix(review-feedback-1822): 修正 PR 描述中的过期验证结论,并补充 Web 设置变更的截图或无法截图时的替代可视证据说明

* fix(review-feedback-1822): 收敛 PR 描述中的验证状态,并补齐 Web 设置变更的截图或替代可视证据

* fix(review-feedback-1822): 收敛 PR 描述后再合入

* fix(review-feedback-1822): 收敛 PR 描述中的验证状态,并补充 Web 设置变更截图或无法截图时的替代可视证据说明

* fix(review-feedback-1822): 收敛验证状态和 Web UI 可视证据,避免合入记录与实际 head 不一致

* fix(review-feedback-1822): 收敛 PR 描述中的验证状态与 Web 可视证据

* fix(review-feedback-1822): 收敛 PR 描述中的验证状态,并补齐 Web 设置变更的截图或替代可视证据说明

* fix(review-feedback-1822): 修正 PR 描述与当前 CI 事实不一致的问题,补充 Web 设置可视证据,并收敛或拆出 PR 模板改动

* fix(review-feedback-1822): 收敛 PR 描述与证据

* fix(review-feedback-1822): 修正 PR 描述与证据,使验证状态、用户可见变更证据、模板改动范围和当前 head 保持一致

* fix(review-feedback-1822): 收敛 PR 描述、补齐可视证据,并澄清/补充外部模型/API 与运行时配置迁移相关兼容性证据

* fix(review-feedback-1822): 收敛 Web/文档契约不一致、同步残留测试,并更新 PR 描述与可视证据
2026-06-28 17:03:15 +08:00

84 lines
2.8 KiB
Python

# -*- coding: utf-8 -*-
"""Unit tests for JP/KR Yahoo Finance market-review index mappings."""
import os
import sys
import unittest
from unittest.mock import MagicMock
import pandas as pd
if 'fake_useragent' not in sys.modules:
sys.modules['fake_useragent'] = MagicMock()
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
def _make_mock_hist(close: float = 100.0, prev_close: float = 98.0) -> pd.DataFrame:
return pd.DataFrame(
{
'Close': [prev_close, close],
'Open': [prev_close - 1, close - 1],
'High': [prev_close + 2, close + 2],
'Low': [prev_close - 2, close - 2],
'Volume': [1000.0, 1200.0],
},
index=pd.DatetimeIndex(['2026-03-26', '2026-03-27']),
)
def _make_mock_yf(hist_df: pd.DataFrame):
mock_ticker = MagicMock()
mock_ticker.history.return_value = hist_df
mock_yf = MagicMock()
mock_yf.Ticker.return_value = mock_ticker
return mock_yf
class TestJpKrIndexMappings(unittest.TestCase):
def setUp(self):
from data_provider.yfinance_fetcher import YfinanceFetcher
self.fetcher = YfinanceFetcher()
def test_jp_indices_use_expected_yahoo_symbols(self):
mock_yf = _make_mock_yf(pd.DataFrame())
self.fetcher._get_jp_main_indices(mock_yf)
ticker_calls = [call.args[0] for call in mock_yf.Ticker.call_args_list]
self.assertEqual(ticker_calls, ['^N225', '^TOPX'])
def test_kr_indices_use_expected_yahoo_symbols(self):
mock_yf = _make_mock_yf(pd.DataFrame())
self.fetcher._get_kr_main_indices(mock_yf)
ticker_calls = [call.args[0] for call in mock_yf.Ticker.call_args_list]
self.assertEqual(ticker_calls, ['^KS11', '^KQ11'])
def test_jp_indices_return_expected_codes_when_data_available(self):
result = self.fetcher._get_jp_main_indices(_make_mock_yf(_make_mock_hist()))
self.assertIsNotNone(result)
assert result is not None
self.assertEqual([item['code'] for item in result], ['N225', 'TOPX'])
self.assertEqual([item['name'] for item in result], ['日经225', '东证指数'])
def test_kr_indices_return_expected_codes_when_data_available(self):
result = self.fetcher._get_kr_main_indices(_make_mock_yf(_make_mock_hist()))
self.assertIsNotNone(result)
assert result is not None
self.assertEqual([item['code'] for item in result], ['KS11', 'KQ11'])
self.assertEqual([item['name'] for item in result], ['KOSPI', 'KOSDAQ'])
def test_jp_kr_indices_return_none_when_all_empty(self):
mock_yf = _make_mock_yf(pd.DataFrame())
self.assertIsNone(self.fetcher._get_jp_main_indices(mock_yf))
self.assertIsNone(self.fetcher._get_kr_main_indices(mock_yf))
if __name__ == '__main__':
unittest.main()