from datetime import date from typing import Optional # 品种主力合约轮换规则。 # 每个品种维护: # exchange: tushare 合约后缀(交易所) # active: 当月 -> (主力合约月, 年份偏移) # 例 FG 12 月用次年 5 月,故 12 -> (5, 1) ROLLOVER_RULES: dict[str, dict] = { "FG": { "exchange": "ZCE", "active": { 1: (5, 0), 2: (5, 0), 3: (5, 0), 4: (9, 0), 5: (9, 0), 6: (9, 0), 7: (9, 0), 8: (1, 1), 9: (1, 1), 10: (1, 1), 11: (1, 1), 12: (5, 1), }, }, } def active_contract(symbol: str, today: Optional[date] = None) -> str: """按主力轮换规则,返回当日 ts_code(含交易所后缀)。""" if symbol not in ROLLOVER_RULES: raise ValueError(f"未配置 {symbol} 的主力轮换规则,可在 contracts.ROLLOVER_RULES 中追加") today = today or date.today() rule = ROLLOVER_RULES[symbol] contract_month, year_offset = rule["active"][today.month] year = today.year + year_offset return f"{symbol}{year % 100:02d}{contract_month:02d}.{rule['exchange']}"