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:
@@ -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)
|
||||
# ============================================================
|
||||
|
||||
Reference in New Issue
Block a user