diff --git a/framework_v2/strategies/rotation/rotation.py b/framework_v2/strategies/rotation/rotation.py index 77ebfdc..56ba20c 100644 --- a/framework_v2/strategies/rotation/rotation.py +++ b/framework_v2/strategies/rotation/rotation.py @@ -115,6 +115,68 @@ class GlobalRotationStrategy(StrategyBase): return list(codes) + def get_data(self) -> Dict[str, pd.DataFrame]: + """ + 获取数据(分别获取指数和 ETF,使用不同的复权方式) + + 指数数据:使用 raw(原始价格)用于信号计算 + ETF 数据:使用 hfq(后复权价格)用于收益计算 + + Returns: + 数据字典 {code: DataFrame} + """ + if self._data_fetcher is None: + self._data_fetcher = self._create_data_fetcher() + + # 获取信号→交易映射 + signal_to_trade = self.config.asset_pools.get_signal_to_trade_mapping() + + # 处理 end_date 为 None 的情况(使用今天) + from datetime import date + start = self.config.backtest.start_date + end = self.config.backtest.end_date + if end is None: + end = date.today().strftime('%Y-%m-%d') + + data = {} + + # 1. 获取指数数据(信号标的,使用 raw) + signal_codes = set(self.config.asset_pools.get_signal_codes()) + if self.use_dynamic_threshold and self.bond_code: + signal_codes.add(self.bond_code) + + if signal_codes: + print(f"\n[数据] 获取 {len(signal_codes)} 只指数数据(adj='raw')...") + try: + index_data = self._data_fetcher.fetch_indices( + codes=list(signal_codes), + start=start, + end=end, + adj='raw' # 指数使用原始价格 + ) + data.update(index_data) + print(f" ✓ 指数数据: {len(index_data)} 只") + except Exception as e: + print(f" ✗ 指数数据获取失败: {e}") + + # 2. 获取 ETF 数据(交易标的,使用 hfq) + trade_codes = list(set(signal_to_trade.values())) + if trade_codes: + print(f"\n[数据] 获取 {len(trade_codes)} 只 ETF 数据(adj='hfq')...") + try: + etf_data = self._data_fetcher.fetch_etf( + codes=trade_codes, + start=start, + end=end, + adj='hfq' # ETF 使用后复权价格 + ) + data.update(etf_data) + print(f" ✓ ETF 数据: {len(etf_data)} 只") + except Exception as e: + print(f" ✗ ETF 数据获取失败: {e}") + + return data + def compute_factors(self, data: Dict[str, pd.DataFrame]) -> Dict[str, pd.Series]: """ 计算动量因子(只使用信号标的的数据)