feat: 统一交易日历为 pandas_market_calendars

- 移除 Tushare 交易日历依赖,A股/美股/港股统一使用 pandas_market_calendars
- 简化 get_trading_calendar() 接口,移除 exchange 参数(沪深日历一致)
- 删除冗余的 _get_china/us/hk_calendar() 独立函数,直接调用 mcal
- 新增 Flask API 端点: /api/v1/trading-calendar, /api/v1/calendar/info
- 代码减少 73 行 (-61%),逻辑更集中易维护
- 更新 API 文档描述,三个市场数据源统一
This commit is contained in:
2026-05-24 11:08:26 +08:00
parent 1bf91bdcd0
commit 100eed455d
2 changed files with 212 additions and 3 deletions

View File

@@ -23,7 +23,7 @@
import os
import time
from typing import Optional, Dict, List, Tuple
from typing import Optional, Dict, List, Tuple, Union
from datetime import datetime
import pandas as pd
@@ -33,6 +33,12 @@ from .ssh_tunnel import SSHTunnelManager
from .asset_type_detector import AssetTypeDetector, AssetType
from .ccxt_source import CCXTSource, get_crypto_source
try:
import pandas_market_calendars as mcal
HAS_PANDAS_MARKET_CALENDARS = True
except ImportError:
HAS_PANDAS_MARKET_CALENDARS = False
class UniversalDataFetcher:
"""
@@ -564,6 +570,96 @@ class UniversalDataFetcher:
"""
return self._tushare.fetch_stock_adj(code, start_date, end_date, adj)
# ============================================================
# 交易日历获取
# ============================================================
def get_trading_calendar(
self,
market: str,
start_date: str,
end_date: str
) -> pd.DatetimeIndex:
"""
获取交易日历(支持 A股、美股、港股
Args:
market: 市场代码
- 'A''china': A股上交所/深交所,交易日历一致)
- 'US''us': 美股NYSE
- 'HK''hk': 港股HKEX
start_date: 开始日期 'YYYY-MM-DD'
end_date: 结束日期 'YYYY-MM-DD'
Returns:
DatetimeIndex: 交易日日期序列
示例:
# A股
cal = fetcher.get_trading_calendar('A', '2024-01-01', '2024-12-31')
# 美股
cal = fetcher.get_trading_calendar('US', '2024-01-01', '2024-12-31')
# 港股
cal = fetcher.get_trading_calendar('HK', '2024-01-01', '2024-12-31')
"""
if not HAS_PANDAS_MARKET_CALENDARS:
raise ImportError(
"需要安装 pandas_market_calendars: pip install pandas_market_calendars"
)
market_lower = market.lower()
# 直接调用 mcal根据市场选择日历
if market_lower in ['a', 'china']:
# A股上交所/深交所交易日历一致,统一使用 SSE
cal = mcal.get_calendar('SSE')
elif market_lower in ['us', 'usa', 'america']:
# 美股NYSE
cal = mcal.get_calendar('NYSE')
elif market_lower in ['hk', 'hongkong']:
# 港股HKEX
cal = mcal.get_calendar('HKEX')
else:
raise ValueError(f"不支持的市场: {market},支持: A/US/HK")
schedule = cal.schedule(start_date=start_date, end_date=end_date)
return pd.DatetimeIndex(schedule.index)
def get_calendar_info(self) -> Dict:
"""
获取交易日历支持信息
Returns:
支持的市场和交易所信息
"""
return {
"supported_markets": {
"A": {
"name": "A股",
"method": "pandas_market_calendars",
"exchanges": ["SSE"],
"default_exchange": "SSE",
"note": "上交所和深交所交易日历完全一致统一使用SSE",
},
"US": {
"name": "美股",
"method": "pandas_market_calendars",
"exchanges": ["NYSE", "NASDAQ"],
"default_exchange": "NYSE",
},
"HK": {
"name": "港股",
"method": "pandas_market_calendars",
"exchanges": ["HKEX"],
"default_exchange": "HKEX",
},
},
"pandas_market_calendars_installed": HAS_PANDAS_MARKET_CALENDARS,
"tushare_available": False, # 不再使用 Tushare
}
# ============================================================
# 统一复权入口(简化版,直接调用 fetch
# ============================================================