""" Wind 数据获取模块 提供统一的接口获取股票历史数据、财务数据和技术指标 """ from WindPy import w import pandas as pd from datetime import datetime, timedelta from typing import List, Dict, Optional, Tuple class WindDataFetcher: """Wind数据获取器""" def __init__(self): """初始化Wind连接""" self._start() def _start(self): """启动Wind连接""" result = w.start() if result.ErrorCode != 0: raise ConnectionError(f"Wind连接失败: {result.Data}") print("Wind连接成功") def _stop(self): """关闭Wind连接""" w.stop() def __enter__(self): return self def __exit__(self, exc_type, exc_val, exc_tb): self._stop() @staticmethod def _handle_wsd_result(result, field_names): """处理wsd返回结果""" if result.ErrorCode != 0: raise ValueError(f"数据获取失败: {result.Data}") # 转换为DataFrame data_dict = dict(zip(field_names, result.Data)) df = pd.DataFrame(data_dict, columns=field_names) df['date'] = result.Times return df def get_daily_data(self, stock_code: str, start_date: str, end_date: str, fields: List[str]) -> pd.DataFrame: """ 获取日线数据 Args: stock_code: 股票代码,如 '300866.SZ' start_date: 开始日期,格式 'YYYY-MM-DD' end_date: 结束日期,格式 'YYYY-MM-DD' fields: 数据字段列表 Returns: DataFrame包含日期和指定字段的数据 """ result = w.wsd(stock_code, fields, start_date, end_date) return self._handle_wsd_result(result, fields) def get_stock_basic(self, stock_code: str) -> Dict: """ 获取股票基本信息 Args: stock_code: 股票代码 Returns: 包含股票名称、行业、上市日期等信息的字典 """ fields = ['sec_name', 'industry', 'ipo_date', 'list_date', 'trade_status'] result = w.wss(stock_code, fields) if result.ErrorCode != 0: raise ValueError(f"基本信息获取失败: {result.Data}") return dict(zip(fields, result.Data[0])) def get_technical_indicators(self, stock_code: str, start_date: str, end_date: str) -> pd.DataFrame: """ 获取技术指标数据 Args: stock_code: 股票代码 start_date: 开始日期 end_date: 结束日期 Returns: DataFrame包含MA、成交量等技术指标 """ fields = [ 'close', 'open', 'high', 'low', 'volume', 'amt', 'pct_chg', 'ma5', 'ma10', 'ma20', 'ma60', 'pe_ttm', 'pb_lf', 'ps_ttm', 'pcf_ncf_ttm' ] return self.get_daily_data(stock_code, start_date, end_date, fields) def get_financial_data(self, stock_code: str, report_date: str = '') -> Dict: """ 获取财务数据 Args: stock_code: 股票代码 report_date: 报告期,格式 'YYYYMMDD',默认最新 Returns: 包含ROE、营收、净利润等财务指标的字典 """ fields = [ 'roe_wgt', 'roa2', 'net_profit_to_profit', 'total_revenue_ps', 'profit_to_gr', 'ebit_ps', 'assets_to_eqt', 'debt_to_assets', 'current_ratio', 'quick_ratio', 'op_income_to_revenue' ] result = w.wss(stock_code, fields, 'rptDate={}'.format(report_date)) if result.ErrorCode != 0: raise ValueError(f"财务数据获取失败: {result.Data}") return dict(zip(fields, result.Data[0])) def get_weekly_data(self, stock_code: str, start_date: str, end_date: str, fields: List[str] = None) -> pd.DataFrame: """ 获取并汇总周线数据 Args: stock_code: 股票代码 start_date: 开始日期 end_date: 结束日期 fields: 数据字段,默认为基本OHLCV Returns: DataFrame包含周线数据 """ if fields is None: fields = ['close', 'open', 'high', 'low', 'volume', 'amt', 'pct_chg'] # 获取日线数据 df_daily = self.get_daily_data(stock_code, start_date, end_date, fields) # 转换为周线数据 df_daily.set_index('date', inplace=True) df_weekly = df_daily.resample('W').agg({ 'open': 'first', 'high': 'max', 'low': 'min', 'close': 'last', 'volume': 'sum', 'amt': 'sum', 'pct_chg': 'sum' # 周涨跌幅近似为日涨跌幅之和 }).dropna() df_weekly.reset_index(inplace=True) return df_weekly def get_stock_list_by_sector(self, sector_name: str, limit: int = 10) -> List[str]: """ 获取某行业的龙头股票列表 Args: sector_name: 行业名称 limit: 返回数量 Returns: 股票代码列表 """ # 使用Wind的行业板块数据 fields = ['sec_name', 'ipo_date'] # 这里简化处理,实际需要根据Wind板块接口调整 print(f"注意: 行业股票列表获取需要根据实际Wind板块接口实现") return [] def calculate_volatility(self, df: pd.DataFrame, annualized: bool = True) -> float: """ 计算波动率 Args: df: 包含收盘价的DataFrame annualized: 是否年化 Returns: 波动率(百分比) """ returns = df['close'].pct_change().dropna() volatility = returns.std() if annualized: # 日数据年化系数:sqrt(252),周数据年化系数:sqrt(52) n = len(df) if n > 250: # 日线数据 volatility *= 252 ** 0.5 else: # 周线数据 volatility *= 52 ** 0.5 return volatility * 100 # 转换为百分比 # 便捷函数 def fetch_stock_report_data(stock_code: str, days_back: int = 90, weekly: bool = True) -> Tuple[pd.DataFrame, Dict]: """ 获取股票报告所需的数据 Args: stock_code: 股票代码 days_back: 获取多少天的数据 weekly: 是否为周线数据 Returns: (price_df, financial_dict) 价格数据和财务数据 """ end_date = datetime.now().strftime('%Y-%m-%d') start_date = (datetime.now() - timedelta(days=days_back)).strftime('%Y-%m-%d') with WindDataFetcher() as fetcher: # 获取价格数据 if weekly: price_df = fetcher.get_weekly_data(stock_code, start_date, end_date) else: price_df = fetcher.get_technical_indicators(stock_code, start_date, end_date) # 获取财务数据 financial_data = fetcher.get_financial_data(stock_code) # 获取基本信息 basic_info = fetcher.get_stock_basic(stock_code) # 合并财务信息 financial_data.update(basic_info) return price_df, financial_data if __name__ == '__main__': # 测试代码 with WindDataFetcher() as fetcher: # 示例:获取某股票的数据 code = '300866.SZ' start = '2025-01-01' end = '2026-02-06' print(f"获取 {code} 的日线数据...") df = fetcher.get_technical_indicators(code, start, end) print(df.tail()) print(f"\n获取 {code} 的基本信息...") info = fetcher.get_stock_basic(code) print(info)