diff --git a/src/data/api_wrappers/__init__.py b/src/data/api_wrappers/__init__.py index d5dbb2f..5d75731 100644 --- a/src/data/api_wrappers/__init__.py +++ b/src/data/api_wrappers/__init__.py @@ -47,7 +47,8 @@ from src.data.api_wrappers.api_pro_bar import ( from src.data.api_wrappers.financial_data.api_income import ( get_income, sync_income, - IncomeSync, + preview_income_sync, + IncomeQuarterSync, ) from src.data.api_wrappers.api_bak_basic import get_bak_basic, sync_bak_basic from src.data.api_wrappers.api_namechange import get_namechange, sync_namechange @@ -84,7 +85,8 @@ __all__ = [ # Income statement "get_income", "sync_income", - "IncomeSync", + "preview_income_sync", + "IncomeQuarterSync", # Historical stock list "get_bak_basic", "sync_bak_basic", diff --git a/src/data/api_wrappers/base_financial_sync.py b/src/data/api_wrappers/base_financial_sync.py new file mode 100644 index 0000000..adcba1a --- /dev/null +++ b/src/data/api_wrappers/base_financial_sync.py @@ -0,0 +1,756 @@ +"""财务数据同步基础抽象模块。 + +提供专门用于按季度同步财务数据的基类 QuarterBasedSync。 +财务数据特点: +- 按季度发布(period: 20231231, 20230930, 20230630, 20230331) +- 使用 VIP 接口一次性获取某季度的全部上市公司数据 +- 数据可能会修正,增量同步需获取当前季度+前一季度 +- 主键为 (ts_code, end_date) + +使用方式: + class IncomeQuarterSync(QuarterBasedSync): + table_name = "financial_income" + api_name = "income_vip" + + def fetch_single_quarter(self, period: str) -> pd.DataFrame: + # 实现单季度数据获取 + ... +""" + +from abc import ABC, abstractmethod +from typing import Optional, Dict, List, Tuple, Set +from datetime import datetime +import pandas as pd +from tqdm import tqdm + +from src.data.client import TushareClient +from src.data.storage import ThreadSafeStorage, Storage +from src.data.utils import get_today_date, get_quarters_in_range, DEFAULT_START_DATE + + +class QuarterBasedSync(ABC): + """财务数据季度同步抽象基类。 + + 专门处理按季度同步的财务数据(利润表、资产负债表、现金流量表)。 + 财务数据同步特点: + 1. 按季度获取:使用 VIP 接口一次性获取某季度全部上市公司数据 + 2. 数据可修正:同一季度数据可能被更新,增量同步需获取当前季度+前一季度 + 3. 差异检测:需对比本地与远程数据量,识别缺失或变更的记录 + 4. 主键:(ts_code, end_date) + + 子类必须实现: + - table_name: 类属性,目标表名 + - api_name: 类属性,Tushare API 接口名 + - fetch_single_quarter(period) -> pd.DataFrame: 获取单季度数据 + - TABLE_SCHEMA: 类属性,表结构定义 + + Attributes: + table_name: 目标表名(子类必须覆盖) + api_name: Tushare API 接口名(子类必须覆盖) + DEFAULT_START_DATE: 默认起始日期(2018Q1) + TABLE_SCHEMA: 表结构定义 {列名: SQL类型} + TABLE_INDEXES: 索引定义 [(索引名, [列名列表]), ...] + 注意:不要创建唯一索引,因为财务数据可能发生多次修正 + """ + + table_name: str = "" # 子类必须覆盖 + api_name: str = "" # 子类必须覆盖 + DEFAULT_START_DATE = "20180331" # 2018年Q1 + + # 目标报表类型(子类可覆盖) + # 默认只同步合并报表(report_type='1') + # 设为 None 则同步所有报表类型 + TARGET_REPORT_TYPE: Optional[str] = "1" + + # 表结构定义(子类必须覆盖) + TABLE_SCHEMA: Dict[str, str] = {} + + # 索引定义(子类可覆盖) + # 格式: [("index_name", ["col1", "col2"]), ...] + # 注意:不要创建唯一索引,因为财务数据可能发生多次修正 + TABLE_INDEXES: List[Tuple[str, List[str]]] = [] + + def __init__(self): + """初始化季度同步管理器。""" + self.storage = ThreadSafeStorage() + self.client = TushareClient() + self._cached_data: Optional[pd.DataFrame] = None + + # ====================================================================== + # 抽象方法 - 子类必须实现 + # ====================================================================== + + @abstractmethod + def fetch_single_quarter(self, period: str) -> pd.DataFrame: + """获取单季度的全部上市公司数据。 + + Args: + period: 报告期,季度最后一天日期(如 '20231231') + + Returns: + 包含该季度全部上市公司财务数据的 DataFrame + """ + pass + + # ====================================================================== + # 季度计算工具方法 + # ====================================================================== + + def get_current_quarter(self) -> str: + """获取当前季度(考虑是否到季末)。 + + 如果当前日期未到季度最后一天,则返回前一季度。 + 这样可以避免获取尚无数据的未来季度。 + + Returns: + 当前季度字符串 (YYYYMMDD),如 '20231231' + """ + today = get_today_date() + year = int(today[:4]) + month = int(today[4:6]) + + # 确定当前季度 + if month <= 3: + current_q = f"{year}0331" + elif month <= 6: + current_q = f"{year}0630" + elif month <= 9: + current_q = f"{year}0930" + else: + current_q = f"{year}1231" + + # 如果今天还没到季末,返回前一季度 + if today < current_q: + return self.get_prev_quarter(current_q) + + return current_q + + def get_prev_quarter(self, quarter: str) -> str: + """获取前一季度。 + + Args: + quarter: 季度字符串 (YYYYMMDD),如 '20231231' + + Returns: + 前一季度字符串 (YYYYMMDD) + """ + year = int(quarter[:4]) + month_day = quarter[4:] + + if month_day == "0331": + return f"{year - 1}1231" + elif month_day == "0630": + return f"{year}0331" + elif month_day == "0930": + return f"{year}0630" + else: # "1231" + return f"{year}0930" + + def get_next_quarter(self, quarter: str) -> str: + """获取下一季度。 + + Args: + quarter: 季度字符串 (YYYYMMDD) + + Returns: + 下一季度字符串 (YYYYMMDD) + """ + year = int(quarter[:4]) + month_day = quarter[4:] + + if month_day == "0331": + return f"{year}0630" + elif month_day == "0630": + return f"{year}0930" + elif month_day == "0930": + return f"{year}1231" + else: # "1231" + return f"{year + 1}0331" + + # ====================================================================== + # 表结构管理 + # ====================================================================== + + def ensure_table_exists(self) -> None: + """确保表结构存在,如不存在则创建表和索引。 + + 注意:不设置主键和唯一索引,因为财务数据可能发生多次修正, + 同一支股票在同一季度可能有多个版本(不同的ann_date)。 + DuckDB 会自动创建 rowid 作为主键。 + """ + storage = Storage() + + if storage.exists(self.table_name): + return + + if not self.TABLE_SCHEMA: + print( + f"[{self.__class__.__name__}] TABLE_SCHEMA not defined, skipping table creation" + ) + return + + # 构建列定义(不设置主键) + columns_def = [] + for col_name, col_type in self.TABLE_SCHEMA.items(): + columns_def.append(f'"{col_name}" {col_type}') + + columns_sql = ", ".join(columns_def) + create_sql = f'CREATE TABLE IF NOT EXISTS "{self.table_name}" ({columns_sql})' + + try: + storage._connection.execute(create_sql) + print(f"[{self.__class__.__name__}] Created table '{self.table_name}'") + except Exception as e: + print(f"[{self.__class__.__name__}] Error creating table: {e}") + raise + + # 创建普通索引(不要创建唯一索引) + for idx_name, idx_cols in self.TABLE_INDEXES: + try: + idx_cols_sql = ", ".join(f'"{col}"' for col in idx_cols) + storage._connection.execute( + f'CREATE INDEX IF NOT EXISTS "{idx_name}" ON "{self.table_name}"({idx_cols_sql})' + ) + print( + f"[{self.__class__.__name__}] Created index '{idx_name}' on {idx_cols}" + ) + except Exception as e: + print( + f"[{self.__class__.__name__}] Error creating index {idx_name}: {e}" + ) + + # ====================================================================== + # 数据差异检测(核心逻辑) + # ====================================================================== + + def get_local_data_count_by_stock(self, period: str) -> Dict[str, int]: + """获取本地数据库中某季度的各股票数据量。 + + Args: + period: 季度字符串 (YYYYMMDD) + + Returns: + 字典 {ts_code: 记录数} + """ + storage = Storage() + + try: + # 将 YYYYMMDD 转换为 YYYY-MM-DD 格式 + period_formatted = f"{period[:4]}-{period[4:6]}-{period[6:]}" + query = f''' + SELECT ts_code, COUNT(*) as cnt + FROM "{self.table_name}" + WHERE end_date = ? + GROUP BY ts_code + ''' + result = storage._connection.execute(query, [period_formatted]).fetchdf() + + if result.empty: + return {} + + return dict(zip(result["ts_code"], result["cnt"])) + except Exception as e: + print(f"[{self.__class__.__name__}] Error querying local data count: {e}") + return {} + + def get_local_records_by_key(self, period: str) -> Dict[tuple, int]: + """获取本地数据库中某季度的记录(按主键分组计数)。 + + 用于更精确的差异检测,按 (ts_code, end_date, report_type) 分组。 + + Args: + period: 季度字符串 (YYYYMMDD) + + Returns: + 字典 {(ts_code, end_date, report_type): 记录数} + """ + storage = Storage() + + try: + # 将 YYYYMMDD 转换为 YYYY-MM-DD 格式 + period_formatted = f"{period[:4]}-{period[4:6]}-{period[6:]}" + query = f''' + SELECT ts_code, end_date, report_type, COUNT(*) as cnt + FROM "{self.table_name}" + WHERE end_date = ? + GROUP BY ts_code, end_date, report_type + ''' + result = storage._connection.execute(query, [period_formatted]).fetchdf() + + if result.empty: + return {} + + return { + (row["ts_code"], row["end_date"], row["report_type"]): row["cnt"] + for _, row in result.iterrows() + } + except Exception as e: + print(f"[{self.__class__.__name__}] Error querying local records: {e}") + return {} + + def compare_and_find_differences( + self, remote_df: pd.DataFrame, period: str + ) -> Tuple[pd.DataFrame, pd.DataFrame]: + """对比远程数据与本地数据,找出差异。 + + 逻辑: + 1. 统计远程数据中每只股票的数据量 + 2. 查询本地数据库中该季度每只股票的数据量 + 3. 对比找出: + - 本地缺失的股票(新增) + - 数据量不一致的股票(有更新,可能包含财务修正) + 4. 返回需要插入的差异数据 + + 注意:主键为 (ts_code, end_date, report_type),因此同一支股票在同一季度 + 可能有多个 report_type 的记录。差异检测按股票级别进行,如果该股票的 + 记录总数不一致,则更新该股票的所有记录。 + + Args: + remote_df: 从 API 获取的远程数据 + period: 季度字符串 + + Returns: + (差异数据DataFrame, 统计信息DataFrame) + 统计信息包含:ts_code, remote_count, local_count, status + """ + if remote_df.empty: + return pd.DataFrame(), pd.DataFrame() + + # 1. 统计远程数据中每只股票的数据量 + remote_counts = remote_df.groupby("ts_code").size().to_dict() + + # 2. 获取本地数据量(按股票汇总) + local_counts = self.get_local_data_count_by_stock(period) + + # 3. 对比找出差异 + diff_stocks = [] # 需要更新的股票列表 + stats = [] + + for ts_code, remote_count in remote_counts.items(): + local_count = local_counts.get(ts_code, 0) + + if local_count == 0: + status = "new" # 本地不存在,全部插入 + diff_stocks.append(ts_code) + elif local_count != remote_count: + status = "modified" # 数据量不一致,可能包含财务修正 + diff_stocks.append(ts_code) + else: + status = "same" # 数据量一致,跳过 + + stats.append( + { + "ts_code": ts_code, + "remote_count": remote_count, + "local_count": local_count, + "status": status, + } + ) + + # 4. 提取差异数据 + if diff_stocks: + diff_df = remote_df[remote_df["ts_code"].isin(diff_stocks)].copy() + else: + diff_df = pd.DataFrame() + + stats_df = pd.DataFrame(stats) + + return diff_df, stats_df + + # ====================================================================== + # 同步核心逻辑 + # ====================================================================== + + def delete_stock_quarter_data( + self, period: str, ts_codes: Optional[List[str]] = None + ) -> int: + """删除指定季度和股票的数据。 + + 在同步前删除旧数据,然后插入新数据(先删除后插入策略)。 + + Args: + period: 季度字符串 (YYYYMMDD) + ts_codes: 股票代码列表,None 表示删除该季度所有数据 + + Returns: + 删除的记录数 + """ + storage = Storage() + + try: + # 将 YYYYMMDD 转换为 YYYY-MM-DD 格式 + period_formatted = f"{period[:4]}-{period[4:6]}-{period[6:]}" + if ts_codes: + # 删除指定股票的数据 + placeholders = ", ".join(["?" for _ in ts_codes]) + query = f''' + DELETE FROM "{self.table_name}" + WHERE end_date = ? AND ts_code IN ({placeholders}) + ''' + result = storage._connection.execute( + query, [period_formatted] + ts_codes + ) + else: + # 删除整个季度的数据 + query = f'DELETE FROM "{self.table_name}" WHERE end_date = ?' + result = storage._connection.execute(query, [period_formatted]) + + # DuckDB 的 rowcount 可能返回 -1,我们手动查询删除后的数量变化 + # 由于我们已经删除了特定条件的数据,直接返回传入的股票数量作为估算 + if ts_codes: + deleted_count = len(ts_codes) + else: + # 删除整个季度,查询删除前的数量 + deleted_count = -1 # 标记为未知,稍后处理 + return deleted_count + except Exception as e: + print(f"[{self.__class__.__name__}] Error deleting data: {e}") + return 0 + + def sync_quarter(self, period: str, dry_run: bool = False) -> Dict: + """同步单个季度的数据。 + + 流程: + 1. 获取远程数据 + 2. 根据 TARGET_REPORT_TYPE 过滤报表类型 + 3. 对比本地数据,找出差异股票 + 4. 删除差异股票的旧数据 + 5. 插入新数据(先删除后插入) + + 注意:财务数据同步必须取当前季度和前一季度进行对比更新, + 不存在"不需要同步"的情况。 + + Args: + period: 季度字符串 (YYYYMMDD) + dry_run: 是否为预览模式 + + Returns: + 同步结果字典 { + 'period': 季度, + 'remote_total': 远程总记录数, + 'diff_count': 差异记录数, + 'deleted_count': 删除的记录数, + 'inserted_count': 插入的记录数, + 'dry_run': 是否预览模式 + } + """ + print(f"[{self.__class__.__name__}] Syncing quarter {period}...") + + # 1. 获取远程数据 + remote_df = self.fetch_single_quarter(period) + + if remote_df.empty: + print(f"[{self.__class__.__name__}] No data for quarter {period}") + return { + "period": period, + "remote_total": 0, + "diff_count": 0, + "deleted_count": 0, + "inserted_count": 0, + "dry_run": dry_run, + } + + # 2. 根据 TARGET_REPORT_TYPE 过滤报表类型 + if self.TARGET_REPORT_TYPE and "report_type" in remote_df.columns: + remote_df = remote_df[remote_df["report_type"] == self.TARGET_REPORT_TYPE] + + remote_total = len(remote_df) + print(f"[{self.__class__.__name__}] Fetched {remote_total} records from API") + + # 3. 检查本地是否有该季度数据 + local_counts = self.get_local_data_count_by_stock(period) + is_first_sync_for_period = len(local_counts) == 0 + + # 4. 执行同步 + deleted_count = 0 + inserted_count = 0 + + if is_first_sync_for_period: + # 首次同步该季度:直接插入所有数据 + print( + f"[{self.__class__.__name__}] First sync for quarter {period}, inserting all data directly" + ) + + if not dry_run: + self.storage.queue_save(self.table_name, remote_df, use_upsert=False) + self.storage.flush() + inserted_count = len(remote_df) + print( + f"[{self.__class__.__name__}] Inserted {inserted_count} new records" + ) + + return { + "period": period, + "remote_total": remote_total, + "diff_count": len(remote_df), + "deleted_count": 0, + "inserted_count": inserted_count, + "dry_run": dry_run, + } + + # 5. 非首次同步:对比找出差异股票 + diff_df, stats_df = self.compare_and_find_differences(remote_df, period) + + diff_stocks = list(diff_df["ts_code"].unique()) if not diff_df.empty else [] + unchanged_count = ( + len(stats_df[stats_df["status"] == "same"]) if not stats_df.empty else 0 + ) + + print(f"[{self.__class__.__name__}] Comparison result:") + print(f" - Stocks with differences: {len(diff_stocks)}") + print(f" - Unchanged stocks: {unchanged_count}") + + if not dry_run and not diff_df.empty: + # 5.1 删除差异股票的旧数据 + deleted_stocks_count = len(diff_stocks) + self.delete_stock_quarter_data(period, diff_stocks) + deleted_count = len(diff_df) + print( + f"[{self.__class__.__name__}] Deleted {deleted_stocks_count} stocks' old records (approx {deleted_count} rows)" + ) + + # 5.2 插入新数据(使用普通 INSERT,因为已删除旧数据) + self.storage.queue_save(self.table_name, diff_df, use_upsert=False) + self.storage.flush() + inserted_count = len(diff_df) + print(f"[{self.__class__.__name__}] Inserted {inserted_count} new records") + + return { + "period": period, + "remote_total": remote_total, + "diff_count": len(diff_df), + "deleted_count": deleted_count, + "inserted_count": inserted_count, + "dry_run": dry_run, + } + + def sync_range( + self, start_quarter: str, end_quarter: str, dry_run: bool = False + ) -> List[Dict]: + """同步指定季度范围的数据。 + + 注意:增量同步会自动包含前一季度以确保数据完整性。 + + Args: + start_quarter: 起始季度 (YYYYMMDD) + end_quarter: 结束季度 (YYYYMMDD) + dry_run: 是否为预览模式 + + Returns: + 各季度同步结果列表 + """ + quarters = get_quarters_in_range(start_quarter, end_quarter) + + if not quarters: + print(f"[{self.__class__.__name__}] No quarters to sync") + return [] + + print( + f"[{self.__class__.__name__}] Syncing {len(quarters)} quarters: {quarters}" + ) + + results = [] + for period in tqdm(quarters, desc=f"Syncing {self.table_name}"): + try: + result = self.sync_quarter(period, dry_run=dry_run) + results.append(result) + except Exception as e: + print(f"[{self.__class__.__name__}] Error syncing {period}: {e}") + results.append({"period": period, "error": str(e)}) + + return results + + def sync_incremental(self, dry_run: bool = False) -> List[Dict]: + """执行增量同步。 + + 策略: + 1. 确保表存在(首次同步时自动建表) + 2. 获取表中最新季度 + 3. 计算当前季度(考虑是否到季末) + 4. 确定同步范围:从最新季度到当前季度 + 5. **重要**:额外包含前一季度以确保数据完整性 + + 注意:财务数据同步与日线数据不同,必须每次都获取数据进行对比 + 更新,不存在"不需要同步"的情况。因为财务数据可能会被修正。 + + Args: + dry_run: 是否为预览模式 + + Returns: + 各季度同步结果列表 + """ + print(f"\n{'=' * 60}") + print(f"[{self.__class__.__name__}] Incremental Sync") + print(f"{'=' * 60}") + + # 0. 确保表存在(首次同步时自动建表) + self.ensure_table_exists() + + # 1. 获取最新季度 + storage = Storage() + try: + result = storage._connection.execute( + f'SELECT MAX(end_date) FROM "{self.table_name}"' + ).fetchone() + latest_quarter = result[0] if result and result[0] else None + if hasattr(latest_quarter, "strftime"): + latest_quarter = latest_quarter.strftime("%Y%m%d") + except Exception as e: + print(f"[{self.__class__.__name__}] Error getting latest quarter: {e}") + latest_quarter = None + + # 2. 获取当前季度 + current_quarter = self.get_current_quarter() + + if latest_quarter is None: + # 无本地数据,执行全量同步 + print(f"[{self.__class__.__name__}] No local data, performing full sync") + return self.sync_range(self.DEFAULT_START_DATE, current_quarter, dry_run) + + print(f"[{self.__class__.__name__}] Latest local quarter: {latest_quarter}") + print(f"[{self.__class__.__name__}] Current quarter: {current_quarter}") + + # 3. 确定同步范围 + # 财务数据必须每次都进行对比更新,不存在"跳过"的情况 + # 同步范围:从最新季度到当前季度(包含前一季度以确保数据完整性) + start_quarter = latest_quarter + if start_quarter > current_quarter: + # 如果本地数据比当前季度还新,仍然需要同步(可能包含修正数据) + start_quarter = current_quarter + else: + # 正常情况:包含前一季度 + start_quarter = self.get_prev_quarter(latest_quarter) + + if start_quarter < self.DEFAULT_START_DATE: + start_quarter = self.DEFAULT_START_DATE + + # 打印同步的两个季度信息 + print(f"\n[{self.__class__.__name__}] 将同步以下两个季度的财报:") + print(f" - 前一季度: {start_quarter}") + print(f" - 当前季度: {current_quarter}") + print(f" (包含前一季度以确保数据完整性)") + print() + + return self.sync_range(start_quarter, current_quarter, dry_run) + + def sync_full(self, dry_run: bool = False) -> List[Dict]: + """执行全量同步。 + + Args: + dry_run: 是否为预览模式 + + Returns: + 各季度同步结果列表 + """ + print(f"\n{'=' * 60}") + print(f"[{self.__class__.__name__}] Full Sync") + print(f"{'=' * 60}") + + # 确保表存在 + self.ensure_table_exists() + + current_quarter = self.get_current_quarter() + + return self.sync_range(self.DEFAULT_START_DATE, current_quarter, dry_run) + + # ====================================================================== + # 预览模式 + # ====================================================================== + + def preview_sync(self) -> Dict: + """预览同步信息(不实际同步)。 + + 注意:财务数据同步必须每次都进行,因为数据可能会被修正。 + 预览显示将要同步的季度范围。 + + Returns: + 预览信息字典 + """ + print(f"\n{'=' * 60}") + print(f"[{self.__class__.__name__}] Preview Mode") + print(f"{'=' * 60}") + + # 获取最新季度 + storage = Storage() + try: + result = storage._connection.execute( + f'SELECT MAX(end_date) FROM "{self.table_name}"' + ).fetchone() + latest_quarter = result[0] if result and result[0] else None + if hasattr(latest_quarter, "strftime"): + latest_quarter = latest_quarter.strftime("%Y%m%d") + except Exception: + latest_quarter = None + + current_quarter = self.get_current_quarter() + + if latest_quarter is None: + # 无本地数据,需要全量同步 + start_quarter = self.DEFAULT_START_DATE + message = "No local data, full sync required" + else: + # 财务数据必须每次都进行对比更新 + # 同步范围:从最新季度到当前季度(包含前一季度) + start_quarter = self.get_prev_quarter(latest_quarter) + if start_quarter < self.DEFAULT_START_DATE: + start_quarter = self.DEFAULT_START_DATE + message = f"Incremental sync from {start_quarter} to {current_quarter}" + + preview = { + "table_name": self.table_name, + "api_name": self.api_name, + "latest_quarter": latest_quarter, + "current_quarter": current_quarter, + "start_quarter": start_quarter, + "end_quarter": current_quarter, + "message": message, + } + + print(f"Table: {self.table_name}") + print(f"API: {self.api_name}") + print(f"Latest local: {latest_quarter}") + print(f"Current quarter: {current_quarter}") + print(f"Sync range: {start_quarter} -> {current_quarter}") + print(f"Message: {message}") + print(f"{'=' * 60}") + + return preview + + +# ====================================================================== +# 便捷函数 +# ====================================================================== + + +def sync_financial_data( + syncer_class: type, force_full: bool = False, dry_run: bool = False +) -> List[Dict]: + """通用的财务数据同步便捷函数。 + + Args: + syncer_class: QuarterBasedSync 的子类 + force_full: 是否强制全量同步 + dry_run: 是否为预览模式 + + Returns: + 同步结果列表 + """ + syncer = syncer_class() + + if force_full: + return syncer.sync_full(dry_run) + else: + return syncer.sync_incremental(dry_run) + + +def preview_financial_sync(syncer_class: type) -> Dict: + """预览财务数据同步信息。 + + Args: + syncer_class: QuarterBasedSync 的子类 + + Returns: + 预览信息字典 + """ + syncer = syncer_class() + return syncer.preview_sync() diff --git a/src/data/api_wrappers/financial_data/api_financial_sync.py b/src/data/api_wrappers/financial_data/api_financial_sync.py index a67305e..c6cf4e1 100644 --- a/src/data/api_wrappers/financial_data/api_financial_sync.py +++ b/src/data/api_wrappers/financial_data/api_financial_sync.py @@ -1,696 +1,234 @@ """财务数据统一同步调度中心。 -该模块作为财务数据同步的调度中心,统一管理各类型财务数据的同步流程。 -支持全量同步和增量同步两种模式。 +该模块作为财务数据同步的调度中心,只负责任务协调和调度。 +具体的同步逻辑已下沉到各 API 文件中。 -财务数据类型: +支持的财务数据类型: - income: 利润表 (已实现) - balance: 资产负债表 (预留) - cashflow: 现金流量表 (预留) -同步模式: -1. 全量同步 (force_full=True): - - 检查表是否存在,如不存在则建表+建索引 - - 从默认开始日期 (20180101) 同步到当前季度 - -2. 增量同步 (force_full=False): - - 获取表中最新季度 (MAX(end_date)) - - 计算当前季度(如果当前日期未到季末,则用前一季度) - - 如果最新季度 == 当前季度,不同步(避免消耗流量) - - 否则从最新季度+1 同步到当前季度 - -使用方式: - # 增量同步利润表数据(推荐) +使用方式: + # 同步所有财务数据(增量) from src.data.api_wrappers.financial_data.api_financial_sync import sync_financial sync_financial() - # 全量同步利润表数据 - from src.data.api_wrappers.financial_data.api_financial_sync import sync_financial + # 全量同步 sync_financial(force_full=True) + # 只同步利润表 + sync_financial(data_types=["income"]) + # 预览同步 from src.data.api_wrappers.financial_data.api_financial_sync import preview_sync preview = preview_sync() """ -from typing import Optional, Dict, List -from datetime import datetime +from typing import List, Dict, Optional -import pandas as pd - -from src.data.storage import Storage, ThreadSafeStorage -from src.data.utils import ( - get_today_date, - get_quarters_in_range, - date_to_quarter, - DEFAULT_START_DATE, +from src.data.api_wrappers.financial_data.api_income import ( + IncomeQuarterSync, + sync_income, + preview_income_sync, ) -from src.data.api_wrappers.financial_data.api_income import get_income -# ============================================================================= -# 财务数据表结构定义 -# ============================================================================= - -# 各财务数据表的表名和字段定义 -FINANCIAL_TABLES = { +# 支持的财务数据类型映射 +FINANCIAL_SYNCERS = { "income": { - "table_name": "financial_income", - "api_name": "income_vip", - "period_field": "end_date", # 用于存储最新季度的字段 - "get_data_func": get_income, + "syncer_class": IncomeQuarterSync, + "sync_func": sync_income, + "preview_func": preview_income_sync, + "display_name": "利润表", }, # 预留:资产负债表 # "balance": { - # "table_name": "financial_balance", - # "api_name": "balance Sheet_vip", - # "period_field": "end_date", - # "get_data_func": get_balance, + # "syncer_class": BalanceQuarterSync, + # "sync_func": sync_balance, + # "preview_func": preview_balance_sync, + # "display_name": "资产负债表", # }, # 预留:现金流量表 # "cashflow": { - # "table_name": "financial_cashflow", - # "api_name": "cashflow_vip", - # "period_field": "end_date", - # "get_data_func": get_cashflow, + # "syncer_class": CashflowQuarterSync, + # "sync_func": sync_cashflow, + # "preview_func": preview_cashflow_sync, + # "display_name": "现金流量表", # }, } -# ============================================================================= -# 财务数据同步核心类 -# ============================================================================= - - -class FinancialSync: - """财务数据统一同步管理器。 - - 支持全量同步和增量同步,自动检测数据状态并选择最优同步策略。 - - 功能特性: - - 全量/增量同步自动切换 - - 自动建表和索引(如不存在) - - 智能季度计算(当前季度未到季末时使用前一季度) - - 流量保护(最新季度==当前季度时不请求API) - - Example: - >>> sync = FinancialSync() - >>> sync.sync_all() # 增量同步所有财务数据 - >>> sync.sync_all(force_full=True) # 全量同步 - >>> sync.sync_income() # 只同步利润表 - """ - - # 表结构定义(按表名) - TABLE_SCHEMAS = { - "financial_income": { - "columns": { - "ts_code": "VARCHAR(16) NOT NULL", - "ann_date": "DATE", - "f_ann_date": "DATE", - "end_date": "DATE NOT NULL", - "report_type": "INTEGER", - "comp_type": "INTEGER", - "end_type": "VARCHAR(10)", - "basic_eps": "DOUBLE", - "diluted_eps": "DOUBLE", - "total_revenue": "DOUBLE", - "revenue": "DOUBLE", - "int_income": "DOUBLE", - "prem_earned": "DOUBLE", - "comm_income": "DOUBLE", - "n_commis_income": "DOUBLE", - "n_oth_income": "DOUBLE", - "n_oth_b_income": "DOUBLE", - "prem_income": "DOUBLE", - "out_prem": "DOUBLE", - "une_prem_reser": "DOUBLE", - "reins_income": "DOUBLE", - "n_sec_tb_income": "DOUBLE", - "n_sec_uw_income": "DOUBLE", - "n_asset_mg_income": "DOUBLE", - "oth_b_income": "DOUBLE", - "fv_value_chg_gain": "DOUBLE", - "invest_income": "DOUBLE", - "ass_invest_income": "DOUBLE", - "forex_gain": "DOUBLE", - "total_cogs": "DOUBLE", - "oper_cost": "DOUBLE", - "int_exp": "DOUBLE", - "comm_exp": "DOUBLE", - "biz_tax_surchg": "DOUBLE", - "sell_exp": "DOUBLE", - "admin_exp": "DOUBLE", - "fin_exp": "DOUBLE", - "assets_impair_loss": "DOUBLE", - "prem_refund": "DOUBLE", - "compens_payout": "DOUBLE", - "reser_insur_liab": "DOUBLE", - "div_payt": "DOUBLE", - "reins_exp": "DOUBLE", - "oper_exp": "DOUBLE", - "compens_payout_refu": "DOUBLE", - "insur_reser_refu": "DOUBLE", - "reins_cost_refund": "DOUBLE", - "other_bus_cost": "DOUBLE", - "operate_profit": "DOUBLE", - "non_oper_income": "DOUBLE", - "non_oper_exp": "DOUBLE", - "nca_disploss": "DOUBLE", - "total_profit": "DOUBLE", - "income_tax": "DOUBLE", - "n_income": "DOUBLE", - "n_income_attr_p": "DOUBLE", - "minority_gain": "DOUBLE", - "oth_compr_income": "DOUBLE", - "t_compr_income": "DOUBLE", - "compr_inc_attr_p": "DOUBLE", - "compr_inc_attr_m_s": "DOUBLE", - "ebit": "DOUBLE", - "ebitda": "DOUBLE", - "insurance_exp": "DOUBLE", - "undist_profit": "DOUBLE", - "distable_profit": "DOUBLE", - "rd_exp": "DOUBLE", - "fin_exp_int_exp": "DOUBLE", - "fin_exp_int_inc": "DOUBLE", - "transfer_surplus_rese": "DOUBLE", - "transfer_housing_imprest": "DOUBLE", - "transfer_oth": "DOUBLE", - "adj_lossgain": "DOUBLE", - "withdra_legal_surplus": "DOUBLE", - "withdra_legal_pubfund": "DOUBLE", - "withdra_biz_devfund": "DOUBLE", - "withdra_rese_fund": "DOUBLE", - "withdra_oth_ersu": "DOUBLE", - "workers_welfare": "DOUBLE", - "distr_profit_shrhder": "DOUBLE", - "prfshare_payable_dvd": "DOUBLE", - "comshare_payable_dvd": "DOUBLE", - "capit_comstock_div": "DOUBLE", - "net_after_nr_lp_correct": "DOUBLE", - "credit_impa_loss": "DOUBLE", - "net_expo_hedging_benefits": "DOUBLE", - "oth_impair_loss_assets": "DOUBLE", - "total_opcost": "DOUBLE", - "amodcost_fin_assets": "DOUBLE", - "oth_income": "DOUBLE", - "asset_disp_income": "DOUBLE", - "continued_net_profit": "DOUBLE", - "end_net_profit": "DOUBLE", - "update_flag": "VARCHAR(1)", - }, - "primary_key": ("ts_code", "end_date"), - "indexes": [ - ("idx_financial_ann", ["ts_code", "ann_date"]), - ], - }, - } - - def __init__(self): - """初始化同步管理器""" - self.storage = Storage() - self.thread_storage = ThreadSafeStorage() - - def _create_table_if_not_exists(self, table_name: str) -> None: - """如果表不存在则创建表和索引。 - - Args: - table_name: 表名 - """ - if self.storage.exists(table_name): - print(f"[FinancialSync] 表 {table_name} 已存在,跳过建表") - return - - if table_name not in self.TABLE_SCHEMAS: - print(f"[FinancialSync] 表 {table_name} 没有定义表结构,跳过建表") - return - - schema = self.TABLE_SCHEMAS[table_name] - print(f"[FinancialSync] 表 {table_name} 不存在,创建表和索引...") - - # 构建列定义 - columns_def = [] - for col_name, col_type in schema["columns"].items(): - columns_def.append(f'"{col_name}" {col_type}') - - # 添加主键约束 - if schema.get("primary_key"): - pk_cols = ', '.join(f'"{col}"' for col in schema["primary_key"]) - columns_def.append(f"PRIMARY KEY ({pk_cols})") - - columns_sql = ", ".join(columns_def) - create_sql = f'CREATE TABLE IF NOT EXISTS "{table_name}" ({columns_sql})' - - try: - self.storage._connection.execute(create_sql) - print(f"[FinancialSync] 表 {table_name} 创建完成") - except Exception as e: - print(f"[FinancialSync] 创建表 {table_name} 失败: {e}") - raise - - # 创建索引 - for idx_name, idx_cols in schema.get("indexes", []): - try: - idx_cols_sql = ', '.join(f'"{col}"' for col in idx_cols) - self.storage._connection.execute( - f'CREATE INDEX IF NOT EXISTS "{idx_name}" ON "{table_name}"({idx_cols_sql})' - ) - print(f"[FinancialSync] 索引 {idx_name} 创建完成") - except Exception as e: - print(f"[FinancialSync] 创建索引 {idx_name} 失败: {e}") - def _get_latest_quarter( - self, table_name: str, period_field: str = "end_date" - ) -> Optional[str]: - """获取表中最新季度。 - - Args: - table_name: 表名 - period_field: 季度字段名 - - Returns: - 最新季度字符串 (YYYYMMDD),如无数据返回 None - """ - try: - result = self.storage._connection.execute(f""" - SELECT MAX({period_field}) FROM {table_name} - """).fetchone() - - if result and result[0]: - # 转换为字符串格式 - latest = result[0] - if hasattr(latest, "strftime"): - return latest.strftime("%Y%m%d") - return str(latest) - return None - except Exception as e: - print(f"[FinancialSync] 获取最新季度失败: {e}") - return None - - def _get_current_quarter(self) -> str: - """获取当前季度(考虑是否到季末)。 - - 如果当前日期未到季度最后一天,则返回前一季度。 - 这样可以避免获取尚无数据的未来季度。 - - Returns: - 当前季度字符串 (YYYYMMDD) - """ - today = get_today_date() - current_quarter = date_to_quarter(today) - - # 检查今天是否到了当前季度的最后一天 - if today < current_quarter: - # 未到季末,返回前一季度 - return self._get_prev_quarter(current_quarter) - - return current_quarter - - def _get_prev_quarter(self, quarter: str) -> str: - """获取前一季度。 - - Args: - quarter: 季度字符串 (YYYYMMDD) - - Returns: - 前一季度字符串 (YYYYMMDD) - """ - year = int(quarter[:4]) - month_day = quarter[4:] - - if month_day == "0331": - # Q1 -> 去年 Q4 - return f"{year - 1}1231" - elif month_day == "0630": - # Q2 -> Q1 - return f"{year}0331" - elif month_day == "0930": - # Q3 -> Q2 - return f"{year}0630" - else: # "1231" - # Q4 -> Q3 - return f"{year}0930" - - def _get_next_quarter(self, quarter: str) -> str: - """获取下一季度。 - - Args: - quarter: 季度字符串 (YYYYMMDD) - - Returns: - 下一季度字符串 (YYYYMMDD) - """ - year = int(quarter[:4]) - month_day = quarter[4:] - - if month_day == "0331": - # Q1 -> Q2 - return f"{year}0630" - elif month_day == "0630": - # Q2 -> Q3 - return f"{year}0930" - elif month_day == "0930": - # Q3 -> Q4 - return f"{year}1231" - else: # "1231" - # Q4 -> 明年 Q1 - return f"{year + 1}0331" - - def _check_incremental_needed( - self, - table_name: str, - period_field: str = "end_date", - ) -> tuple[bool, Optional[str], Optional[str]]: - """检查增量同步是否需要。 - - Args: - table_name: 表名 - period_field: 季度字段名 - - Returns: - (是否需要同步, 起始季度, 目标季度) - - 如果不需要同步,返回 (False, None, None) - """ - # 获取表中最新季度 - latest_quarter = self._get_latest_quarter(table_name, period_field) - - if latest_quarter is None: - # 无本地数据,需要全量同步 - print(f"[FinancialSync] 表 {table_name} 无数据,需要全量同步") - return (True, DEFAULT_START_DATE, self._get_current_quarter()) - - print(f"[FinancialSync] 表 {table_name} 最新季度: {latest_quarter}") - - # 获取当前季度(考虑是否到季末) - current_quarter = self._get_current_quarter() - print(f"[FinancialSync] 当前季度: {current_quarter}") - - # 比较:如果最新季度 >= 当前季度,不需要同步 - if latest_quarter >= current_quarter: - print( - f"[FinancialSync] 最新季度 {latest_quarter} >= 当前季度 {current_quarter},跳过增量同步" - ) - return (False, None, None) - - # 需要增量同步:从最新季度+1 到 当前季度 - start_quarter = self._get_next_quarter(latest_quarter) - print(f"[FinancialSync] 增量同步: {start_quarter} -> {current_quarter}") - - return (True, start_quarter, current_quarter) - - def _sync_single_table( - self, - table_config: Dict, - start_quarter: str, - end_quarter: str, - ) -> int: - """同步单个财务数据表。 - - Args: - table_config: 表配置字典 - start_quarter: 起始季度 - end_quarter: 目标季度 - - Returns: - 同步的记录数 - """ - table_name = table_config["table_name"] - get_data_func = table_config["get_data_func"] - - # 获取需要同步的季度列表 - quarters = get_quarters_in_range(start_quarter, end_quarter) - print(f"[FinancialSync] 计划同步 {len(quarters)} 个季度: {quarters}") - - total_records = 0 - - # 对每个季度调用 API 获取数据 - for period in quarters: - try: - df = get_data_func(period) - if df.empty: - print(f"[WARN] 季度 {period} 无数据") - continue - - # 只保留合并报表 (report_type='1',注意是字符串) - if "report_type" in df.columns: - df = df[df["report_type"] == "1"] - - if not df.empty: - self.thread_storage.queue_save(table_name, df) - print(f"[FinancialSync] 季度 {period} -> {len(df)} 条记录") - total_records += len(df) - - except Exception as e: - print(f"[ERROR] 获取季度 {period} 数据失败: {e}") - - # 刷新缓存到数据库 - self.thread_storage.flush() - - return total_records - - def sync_income( - self, - force_full: bool = False, - ) -> Dict: - """同步利润表数据。 - - Args: - force_full: 若为 True,强制全量同步 - - Returns: - 同步结果字典 - """ - table_config = FINANCIAL_TABLES["income"] - table_name = table_config["table_name"] - period_field = table_config["period_field"] - - print("\n" + "=" * 60) - print(f"[FinancialSync] 开始同步利润表 (force_full={force_full})") - print("=" * 60) - - # 1. 全量同步:建表 - if force_full: - self._create_table_if_not_exists(table_name) - start_quarter = DEFAULT_START_DATE - end_quarter = self._get_current_quarter() - else: - # 2. 增量同步:检查是否需要 - needed, start_quarter, end_quarter = self._check_incremental_needed( - table_name, period_field - ) - - if not needed: - return { - "status": "skipped", - "message": "数据已是最新", - "table": table_name, - } - - # 检查表是否存在,不存在则创建 - if not self.storage.exists(table_name): - self._create_table_if_not_exists(table_name) - - # 3. 执行同步 - print(f"[FinancialSync] 同步范围: {start_quarter} -> {end_quarter}") - total_records = self._sync_single_table( - table_config, start_quarter, end_quarter - ) - - result = { - "status": "success", - "table": table_name, - "start_quarter": start_quarter, - "end_quarter": end_quarter, - "records": total_records, - } - - print(f"[FinancialSync] 利润表同步完成: {total_records} 条记录") - return result - - def sync_all( - self, - force_full: bool = False, - ) -> Dict[str, Dict]: - """同步所有财务数据表。 - - Args: - force_full: 若为 True,强制全量同步 - - Returns: - 各表同步结果字典 - """ - results = {} - - print("\n" + "=" * 60) - print(f"[FinancialSync] 开始同步所有财务数据 (force_full={force_full})") - print("=" * 60) - - # 同步各财务数据表 - for data_type, table_config in FINANCIAL_TABLES.items(): - try: - if data_type == "income": - result = self.sync_income(force_full=force_full) - else: - # 预留其他表的同步逻辑 - print(f"[FinancialSync] {data_type} 暂未实现,跳过") - result = {"status": "not_implemented"} - - results[data_type] = result - - except Exception as e: - print(f"[ERROR] 同步 {data_type} 失败: {e}") - results[data_type] = {"status": "error", "error": str(e)} - - # 打印汇总 - print("\n" + "=" * 60) - print("[FinancialSync] 同步汇总") - print("=" * 60) - for data_type, result in results.items(): - status = result.get("status", "unknown") - records = result.get("records", 0) - print(f" {data_type}: {status} ({records} records)") - print("=" * 60) - - return results - - -# ============================================================================= -# 便捷函数 -# ============================================================================= - - def sync_financial( - data_type: str = "income", + data_types: Optional[List[str]] = None, force_full: bool = False, -) -> Dict: - """同步财务数据(便捷函数)。 + dry_run: bool = False, +) -> Dict[str, List]: + """同步财务数据(调度函数)。 + + 根据指定的数据类型,调度对应的同步器执行同步。 Args: - data_type: 财务数据类型 ('income', 'balance', 'cashflow') + data_types: 数据类型列表,如 ["income", "balance"] + None 表示同步所有类型 force_full: 若为 True,强制全量同步 + dry_run: 若为 True,仅预览不写入 Returns: - 同步结果字典 + 各类型同步结果字典 {数据类型: 同步结果列表} Example: - >>> # 增量同步利润表 + >>> # 同步所有财务数据 >>> sync_financial() + >>> + >>> # 只同步利润表 + >>> sync_financial(data_types=["income"]) + >>> >>> # 全量同步 >>> sync_financial(force_full=True) """ - syncer = FinancialSync() + if data_types is None: + data_types = list(FINANCIAL_SYNCERS.keys()) - if data_type == "income": - return syncer.sync_income(force_full=force_full) - else: - raise ValueError(f"不支持的财务数据类型: {data_type}") + results = {} + print("\n" + "=" * 60) + print("[Financial Sync] 财务数据同步调度中心") + print("=" * 60) + print(f"数据类型: {', '.join(data_types)}") + print(f"同步模式: {'全量' if force_full else '增量'}") + print(f"写入模式: {'预览' if dry_run else '实际写入'}") + print("=" * 60) -def sync_all_financial(force_full: bool = False) -> Dict[str, Dict]: - """同步所有财务数据(便捷函数)。 - - Args: - force_full: 若为 True,强制全量同步 - - Returns: - 各表同步结果字典 - - Example: - >>> # 增量同步所有财务数据 - >>> sync_all_financial() - >>> # 全量同步 - >>> sync_all_financial(force_full=True) - """ - syncer = FinancialSync() - return syncer.sync_all(force_full=force_full) - - -def preview_sync() -> Dict: - """预览同步信息(不实际同步)。 - - Returns: - 预览信息字典: - { - 'income': { - 'sync_needed': bool, - 'latest_quarter': str, - 'current_quarter': str, - 'start_quarter': str, - 'end_quarter': str, - }, - ... - } - """ - syncer = FinancialSync() - preview = {} - - for data_type, table_config in FINANCIAL_TABLES.items(): - if data_type != "income": + for data_type in data_types: + if data_type not in FINANCIAL_SYNCERS: + print(f"[WARN] 未知的数据类型: {data_type}") + results[data_type] = {"error": f"Unknown data type: {data_type}"} continue - table_name = table_config["table_name"] - period_field = table_config["period_field"] + config = FINANCIAL_SYNCERS[data_type] + sync_func = config["sync_func"] + display_name = config["display_name"] - # 获取最新季度 - latest_quarter = syncer._get_latest_quarter(table_name, period_field) - current_quarter = syncer._get_current_quarter() + print(f"\n[{display_name}] 开始同步...") - # 检查是否需要同步 - needed, start_quarter, end_quarter = syncer._check_incremental_needed( - table_name, period_field + try: + result = sync_func(force_full=force_full, dry_run=dry_run) + results[data_type] = result + print(f"[{display_name}] 同步完成") + except Exception as e: + print(f"[ERROR] [{display_name}] 同步失败: {e}") + results[data_type] = {"error": str(e)} + + # 打印汇总 + print("\n" + "=" * 60) + print("[Financial Sync] 同步汇总") + print("=" * 60) + for data_type, result in results.items(): + if "error" in result: + status = f"失败: {result['error']}" + elif isinstance(result, list): + total_records = sum( + r.get("diff_count", 0) for r in result if isinstance(r, dict) + ) + status = f"成功 ({len(result)} 个季度, {total_records} 条差异)" + else: + status = "完成" + + display_name = FINANCIAL_SYNCERS.get(data_type, {}).get( + "display_name", data_type ) + print(f" {display_name}: {status}") + print("=" * 60) - preview[data_type] = { - "sync_needed": needed, - "latest_quarter": latest_quarter, - "current_quarter": current_quarter, - "start_quarter": start_quarter, - "end_quarter": end_quarter, + return results + + +def preview_sync(data_types: Optional[List[str]] = None) -> Dict[str, Dict]: + """预览财务数据同步信息。 + + Args: + data_types: 数据类型列表,None 表示所有类型 + + Returns: + 各类型预览信息字典 + + Example: + >>> preview = preview_sync() + >>> print(preview) + """ + if data_types is None: + data_types = list(FINANCIAL_SYNCERS.keys()) + + previews = {} + + print("\n" + "=" * 60) + print("[Financial Sync] 同步预览") + print("=" * 60) + + for data_type in data_types: + if data_type not in FINANCIAL_SYNCERS: + continue + + preview_func = FINANCIAL_SYNCERS[data_type]["preview_func"] + previews[data_type] = preview_func() + + return previews + + +def list_financial_types() -> List[Dict]: + """列出所有支持的财务数据类型。 + + Returns: + 数据类型信息列表 + """ + return [ + { + "name": name, + "display_name": config["display_name"], } - - return preview + for name, config in FINANCIAL_SYNCERS.items() + ] -# ============================================================================= -# 主程序入口 -# ============================================================================= +# 保持向后兼容的别名 +sync_all_financial = sync_financial if __name__ == "__main__": import sys print("=" * 60) - print("财务数据同步模块") + print("财务数据同步调度中心") print("=" * 60) + print("\n支持的财务数据类型:") + print("-" * 60) + + for info in list_financial_types(): + print(f" - {info['name']}: {info['display_name']}") + + print("-" * 60) print("\n使用方式:") - print(" # 预览同步信息") - print( - " from src.data.api_wrappers.financial_data.api_financial_sync import preview_sync" - ) - print(" preview = preview_sync()") + print(" # 同步所有财务数据(默认)") + print(" python api_financial_sync.py") print("") - print(" # 增量同步(推荐)") + print(" # 全量同步") + print(" python api_financial_sync.py --full") + print("") + print(" # 预览模式") + print(" python api_financial_sync.py --preview") + print("") + print(" # Python 代码调用") print( " from src.data.api_wrappers.financial_data.api_financial_sync import sync_financial" ) print(" sync_financial()") - print("") - print(" # 全量同步") - print(" sync_financial(force_full=True)") - print("") - print(" # 同步所有财务数据") - print( - " from src.data.api_wrappers.financial_data.api_financial_sync import sync_all_financial" - ) - print(" sync_all_financial()") print("=" * 60) - # 默认执行增量同步 - if len(sys.argv) > 1 and sys.argv[1] == "--full": - print("\n[Main] 执行全量同步...") - result = sync_all_financial(force_full=True) + # 默认执行同步 + if len(sys.argv) > 1 and sys.argv[1] == "--preview": + print("\n执行预览...") + preview_sync() else: - print("\n[Main] 执行增量同步...") - result = sync_financial() - - print("\n[Main] 执行完成!") - print(f"结果: {result}") + print("\n执行同步...") + force_full = "--full" in sys.argv + sync_financial(force_full=force_full) diff --git a/src/data/api_wrappers/financial_data/api_income.py b/src/data/api_wrappers/financial_data/api_income.py index fd66ca2..8b7f838 100644 --- a/src/data/api_wrappers/financial_data/api_income.py +++ b/src/data/api_wrappers/financial_data/api_income.py @@ -7,133 +7,252 @@ - income_vip: 获取某一季度全部上市公司利润表数据 - 需要 5000 积分才能调用 - period 参数为报告期(季度最后一天,如 20231231) + +使用方式: + # 同步利润表数据 + from src.data.api_wrappers.financial_data.api_income import IncomeQuarterSync, sync_income + + # 方式1: 使用类 + syncer = IncomeQuarterSync() + syncer.sync_incremental() # 增量同步 + syncer.sync_full() # 全量同步 + + # 方式2: 使用便捷函数 + sync_income() # 增量同步 + sync_income(force_full=True) # 全量同步 """ +from typing import Optional import pandas as pd -from typing import Optional, List -from tqdm import tqdm from src.data.client import TushareClient -from src.data.storage import ThreadSafeStorage -from src.data.utils import get_today_date, get_quarters_in_range +from src.data.api_wrappers.base_financial_sync import ( + QuarterBasedSync, + sync_financial_data, + preview_financial_sync, +) -def get_income( - period: str, - fields: Optional[str] = None, -) -> pd.DataFrame: - """获取利润表数据 (VIP 接口) +class IncomeQuarterSync(QuarterBasedSync): + """利润表季度同步实现。 - 从 Tushare 获取指定季度的全部上市公司利润表数据。 + 使用 income_vip 接口按季度获取全部上市公司利润表数据。 - Args: - period: 报告期,季度最后一天日期 (如 '20231231', '20230930') - - 0331: 一季报 - - 0630: 半年报 - - 0930: 三季报 - - 1231: 年报 - fields: 指定返回字段,默认返回全部字段 - - Returns: - pd.DataFrame 包含利润表数据: - - ts_code: 股票代码 - - ann_date: 公告日期 - - end_date: 报告期 - - basic_eps: 基本每股收益 - - report_type: 报告类型 (1=合并报表) - - Example: - >>> data = get_income('20231231') - >>> print(data[['ts_code', 'ann_date', 'basic_eps']].head()) + 表结构: financial_income + 主键: (ts_code, end_date) """ - client = TushareClient() - # 默认字段:返回全部字段(利润表有100+字段) - if fields is None: - fields = "ts_code,ann_date,f_ann_date,end_date,report_type,comp_type,end_type,basic_eps,diluted_eps,total_revenue,revenue,int_income,prem_earned,comm_income,n_commis_income,n_oth_income,n_oth_b_income,prem_income,out_prem,une_prem_reser,reins_income,n_sec_tb_income,n_sec_uw_income,n_asset_mg_income,oth_b_income,fv_value_chg_gain,invest_income,ass_invest_income,forex_gain,total_cogs,oper_cost,int_exp,comm_exp,biz_tax_surchg,sell_exp,admin_exp,fin_exp,assets_impair_loss,prem_refund,compens_payout,reser_insur_liab,div_payt,reins_exp,oper_exp,compens_payout_refu,insur_reser_refu,reins_cost_refund,other_bus_cost,operate_profit,non_oper_income,non_oper_exp,nca_disploss,total_profit,income_tax,n_income,n_income_attr_p,minority_gain,oth_compr_income,t_compr_income,compr_inc_attr_p,compr_inc_attr_m_s,ebit,ebitda,insurance_exp,undist_profit,distable_profit,rd_exp,fin_exp_int_exp,fin_exp_int_inc,transfer_surplus_rese,transfer_housing_imprest,transfer_oth,adj_lossgain,withdra_legal_surplus,withdra_legal_pubfund,withdra_biz_devfund,withdra_rese_fund,withdra_oth_ersu,workers_welfare,distr_profit_shrhder,prfshare_payable_dvd,comshare_payable_dvd,capit_comstock_div,net_after_nr_lp_correct,credit_impa_loss,net_expo_hedging_benefits,oth_impair_loss_assets,total_opcost,amodcost_fin_assets,oth_income,asset_disp_income,continued_net_profit,end_net_profit,update_flag" - params = {"fields": fields, "period": period} - return client.query("income_vip", **params) + table_name = "financial_income" + api_name = "income_vip" + # 目标报表类型:默认只同步合并报表 + TARGET_REPORT_TYPE = "1" -# ============================================================================= -# IncomeSync - 利润表数据批量同步类 -# ============================================================================= + # 表结构定义 + TABLE_SCHEMA = { + "ts_code": "VARCHAR(16) NOT NULL", + "ann_date": "DATE", + "f_ann_date": "DATE", + "end_date": "DATE NOT NULL", + "report_type": "INTEGER", + "comp_type": "INTEGER", + "end_type": "VARCHAR(10)", + "basic_eps": "DOUBLE", + "diluted_eps": "DOUBLE", + "total_revenue": "DOUBLE", + "revenue": "DOUBLE", + "int_income": "DOUBLE", + "prem_earned": "DOUBLE", + "comm_income": "DOUBLE", + "n_commis_income": "DOUBLE", + "n_oth_income": "DOUBLE", + "n_oth_b_income": "DOUBLE", + "prem_income": "DOUBLE", + "out_prem": "DOUBLE", + "une_prem_reser": "DOUBLE", + "reins_income": "DOUBLE", + "n_sec_tb_income": "DOUBLE", + "n_sec_uw_income": "DOUBLE", + "n_asset_mg_income": "DOUBLE", + "oth_b_income": "DOUBLE", + "fv_value_chg_gain": "DOUBLE", + "invest_income": "DOUBLE", + "ass_invest_income": "DOUBLE", + "forex_gain": "DOUBLE", + "total_cogs": "DOUBLE", + "oper_cost": "DOUBLE", + "int_exp": "DOUBLE", + "comm_exp": "DOUBLE", + "biz_tax_surchg": "DOUBLE", + "sell_exp": "DOUBLE", + "admin_exp": "DOUBLE", + "fin_exp": "DOUBLE", + "assets_impair_loss": "DOUBLE", + "prem_refund": "DOUBLE", + "compens_payout": "DOUBLE", + "reser_insur_liab": "DOUBLE", + "div_payt": "DOUBLE", + "reins_exp": "DOUBLE", + "oper_exp": "DOUBLE", + "compens_payout_refu": "DOUBLE", + "insur_reser_refu": "DOUBLE", + "reins_cost_refund": "DOUBLE", + "other_bus_cost": "DOUBLE", + "operate_profit": "DOUBLE", + "non_oper_income": "DOUBLE", + "non_oper_exp": "DOUBLE", + "nca_disploss": "DOUBLE", + "total_profit": "DOUBLE", + "income_tax": "DOUBLE", + "n_income": "DOUBLE", + "n_income_attr_p": "DOUBLE", + "minority_gain": "DOUBLE", + "oth_compr_income": "DOUBLE", + "t_compr_income": "DOUBLE", + "compr_inc_attr_p": "DOUBLE", + "compr_inc_attr_m_s": "DOUBLE", + "ebit": "DOUBLE", + "ebitda": "DOUBLE", + "insurance_exp": "DOUBLE", + "undist_profit": "DOUBLE", + "distable_profit": "DOUBLE", + "rd_exp": "DOUBLE", + "fin_exp_int_exp": "DOUBLE", + "fin_exp_int_inc": "DOUBLE", + "transfer_surplus_rese": "DOUBLE", + "transfer_housing_imprest": "DOUBLE", + "transfer_oth": "DOUBLE", + "adj_lossgain": "DOUBLE", + "withdra_legal_surplus": "DOUBLE", + "withdra_legal_pubfund": "DOUBLE", + "withdra_biz_devfund": "DOUBLE", + "withdra_rese_fund": "DOUBLE", + "withdra_oth_ersu": "DOUBLE", + "workers_welfare": "DOUBLE", + "distr_profit_shrhder": "DOUBLE", + "prfshare_payable_dvd": "DOUBLE", + "comshare_payable_dvd": "DOUBLE", + "capit_comstock_div": "DOUBLE", + "net_after_nr_lp_correct": "DOUBLE", + "credit_impa_loss": "DOUBLE", + "net_expo_hedging_benefits": "DOUBLE", + "oth_impair_loss_assets": "DOUBLE", + "total_opcost": "DOUBLE", + "amodcost_fin_assets": "DOUBLE", + "oth_income": "DOUBLE", + "asset_disp_income": "DOUBLE", + "continued_net_profit": "DOUBLE", + "end_net_profit": "DOUBLE", + "update_flag": "VARCHAR(1)", + } - -class IncomeSync: - """利润表数据批量同步管理器 (VIP 版本) - - 功能特性: - - 按季度同步,每次请求获取该季度全部上市公司数据 - - 使用 income_vip 接口 - - 只保留合并报表(report_type=1) - - 使用 ThreadSafeStorage 安全写入 - - Example: - >>> sync = IncomeSync() - >>> sync.sync(start_date='20200101', end_date='20231231') - """ + # 索引定义(不要创建唯一索引) + # 注意:财务数据可能发生多次修正,不设置主键和唯一索引 + TABLE_INDEXES = [ + ("idx_financial_income_ts_code", ["ts_code"]), + ("idx_financial_income_end_date", ["end_date"]), + ("idx_financial_income_ts_period", ["ts_code", "end_date", "report_type"]), + ] def __init__(self): - """初始化同步管理器""" - self.storage = ThreadSafeStorage() - self.client = TushareClient() + """初始化利润表同步器。""" + super().__init__() + self._fields = None # 默认返回全部字段 - def sync( - self, - start_date: str, - end_date: Optional[str] = None, - ) -> None: - """同步利润表数据 + def fetch_single_quarter(self, period: str) -> pd.DataFrame: + """获取单季度的全部上市公司利润表数据。 Args: - start_date: 开始日期 YYYYMMDD - end_date: 结束日期 YYYYMMDD(默认为今天) + period: 报告期,季度最后一天日期(如 '20231231') + + Returns: + 包含该季度全部上市公司利润表数据的 DataFrame """ - if end_date is None: - end_date = get_today_date() + params = {"period": period} - # 获取日期范围内的所有季度 - quarters = get_quarters_in_range(start_date, end_date) - print(f"[IncomeSync] 计划同步 {len(quarters)} 个季度: {quarters}") + if self._fields: + params["fields"] = self._fields - # 对每个季度调用 income_vip 获取全部股票数据 - for period in tqdm(quarters, desc="Syncing income by quarter"): - try: - df = get_income(period) - if df.empty: - print(f"[WARN] 季度 {period} 无数据") - continue + return self.client.query(self.api_name, **params) - # 只保留合并报表 (report_type='1',注意是字符串) - if "report_type" in df.columns: - df = df[df["report_type"] == "1"] - if not df.empty: - self.storage.queue_save("financial_income", df) - print(f"[IncomeSync] 季度 {period} -> {len(df)} 条记录") - - except Exception as e: - print(f"[ERROR] 获取季度 {period} 数据失败: {e}") - - # 刷新缓存到数据库 - self.storage.flush() - print(f"[IncomeSync] 同步完成,共处理 {len(quarters)} 个季度") +# ============================================================================= +# 便捷函数 +# ============================================================================= def sync_income( - start_date: str, - end_date: Optional[str] = None, -) -> None: - """同步利润表数据(便捷函数) + force_full: bool = False, + dry_run: bool = False, +) -> list: + """同步利润表数据(便捷函数)。 Args: - start_date: 开始日期 YYYYMMDD - end_date: 结束日期 YYYYMMDD(默认为今天) + force_full: 若为 True,强制全量同步 + dry_run: 若为 True,仅预览不写入 + + Returns: + 同步结果列表 Example: - >>> sync_income('20200101') - >>> sync_income('20200101', '20231231') + >>> # 增量同步 + >>> sync_income() + >>> + >>> # 全量同步 + >>> sync_income(force_full=True) + >>> + >>> # 预览 + >>> sync_income(dry_run=True) """ - syncer = IncomeSync() - syncer.sync(start_date, end_date) + return sync_financial_data(IncomeQuarterSync, force_full, dry_run) + + +def preview_income_sync() -> dict: + """预览利润表同步信息。 + + Returns: + 预览信息字典 + """ + return preview_financial_sync(IncomeQuarterSync) + + +def get_income(period: str, fields: Optional[str] = None) -> pd.DataFrame: + """获取利润表数据(原始接口,单季度)。 + + 用于直接获取某个季度的数据,不进行同步管理。 + + Args: + period: 报告期,季度最后一天日期(如 '20231231') + fields: 指定返回字段,默认返回全部字段 + + Returns: + 包含利润表数据的 DataFrame + """ + client = TushareClient() + + if fields is None: + fields = ( + "ts_code,ann_date,f_ann_date,end_date,report_type,comp_type,end_type," + "basic_eps,diluted_eps,total_revenue,revenue,int_income,prem_earned," + "comm_income,n_commis_income,n_oth_income,n_oth_b_income,prem_income," + "out_prem,une_prem_reser,reins_income,n_sec_tb_income,n_sec_uw_income," + "n_asset_mg_income,oth_b_income,fv_value_chg_gain,invest_income," + "ass_invest_income,forex_gain,total_cogs,oper_cost,int_exp,comm_exp," + "biz_tax_surchg,sell_exp,admin_exp,fin_exp,assets_impair_loss,prem_refund," + "compens_payout,reser_insur_liab,div_payt,reins_exp,oper_exp," + "compens_payout_refu,insur_reser_refu,reins_cost_refund,other_bus_cost," + "operate_profit,non_oper_income,non_oper_exp,nca_disploss,total_profit," + "income_tax,n_income,n_income_attr_p,minority_gain,oth_compr_income," + "t_compr_income,compr_inc_attr_p,compr_inc_attr_m_s,ebit,ebitda," + "insurance_exp,undist_profit,distable_profit,rd_exp,fin_exp_int_exp," + "fin_exp_int_inc,transfer_surplus_rese,transfer_housing_imprest," + "transfer_oth,adj_lossgain,withdra_legal_surplus,withdra_legal_pubfund," + "withdra_biz_devfund,withdra_rese_fund,withdra_oth_ersu,workers_welfare," + "distr_profit_shrhder,prfshare_payable_dvd,comshare_payable_dvd," + "capit_comstock_div,net_after_nr_lp_correct,credit_impa_loss," + "net_expo_hedging_benefits,oth_impair_loss_assets,total_opcost," + "amodcost_fin_assets,oth_income,asset_disp_income,continued_net_profit," + "end_net_profit,update_flag" + ) + + return client.query("income_vip", period=period, fields=fields) diff --git a/src/data/storage.py b/src/data/storage.py index 5a7b00c..0bdd6f3 100644 --- a/src/data/storage.py +++ b/src/data/storage.py @@ -1,4 +1,5 @@ """DuckDB storage for data persistence.""" + import pandas as pd import polars as pl import duckdb @@ -73,13 +74,22 @@ class Storage: - api_financial_sync.py: FinancialSync.TABLE_SCHEMAS """ self._connection = duckdb.connect(str(self.db_path)) - def save(self, name: str, data: pd.DataFrame, mode: str = "append") -> dict: + + def save( + self, + name: str, + data: pd.DataFrame, + mode: str = "append", + use_upsert: bool = True, + ) -> dict: """Save data to DuckDB. Args: name: Table name data: DataFrame to save - mode: 'append' (UPSERT) or 'replace' (DELETE + INSERT) + mode: 'append' or 'replace' (DELETE + INSERT) + use_upsert: 若为 True 使用 INSERT OR REPLACE (upsert), + 若为 False 使用普通 INSERT (依赖外部删除逻辑) Returns: Dict with save result @@ -123,17 +133,20 @@ class Storage: if mode == "replace": self._connection.execute(f"DELETE FROM {name}") - # UPSERT: INSERT OR REPLACE - columns = ', '.join(f'"{col}"' for col in data.columns) - self._connection.execute(f""" - INSERT OR REPLACE INTO {name} ({columns}) - SELECT {columns} FROM temp_data - """) - columns = ", ".join(data.columns) - self._connection.execute(f""" - INSERT OR REPLACE INTO {name} ({columns}) - SELECT {columns} FROM temp_data - """) + columns = ", ".join(f'"{col}"' for col in data.columns) + + if use_upsert: + # UPSERT: INSERT OR REPLACE (需要主键约束) + self._connection.execute(f""" + INSERT OR REPLACE INTO {name} ({columns}) + SELECT {columns} FROM temp_data + """) + else: + # 普通 INSERT (依赖外部删除逻辑确保无重复) + self._connection.execute(f""" + INSERT INTO {name} ({columns}) + SELECT {columns} FROM temp_data + """) row_count = len(data) print(f"[Storage] Saved {row_count} rows to DuckDB ({name})") @@ -220,8 +233,8 @@ class Storage: # Build query conditions = [] if start_date and end_date: - start = pd.to_datetime(start_date, format='%Y%m%d').date() - end = pd.to_datetime(end_date, format='%Y%m%d').date() + start = pd.to_datetime(start_date, format="%Y%m%d").date() + end = pd.to_datetime(end_date, format="%Y%m%d").date() conditions.append(f"trade_date BETWEEN '{start}' AND '{end}'") if ts_code: conditions.append(f"ts_code = '{ts_code}'") @@ -231,13 +244,13 @@ class Storage: # 使用 DuckDB 的 Polars 导出(需要 pyarrow) df = self._connection.sql(query).pl() - + # 将 trade_date 转换为字符串格式,保持兼容性 if "trade_date" in df.columns: df = df.with_columns( pl.col("trade_date").dt.strftime("%Y%m%d").alias("trade_date") ) - + return df def exists(self, name: str) -> bool: @@ -295,12 +308,18 @@ class ThreadSafeStorage: def __init__(self): self.storage = Storage() - self._pending_writes: List[tuple] = [] # [(name, data), ...] + self._pending_writes: List[tuple] = [] # [(name, data, use_upsert), ...] - def queue_save(self, name: str, data: pd.DataFrame): - """将数据放入写入队列(不立即写入)""" + def queue_save(self, name: str, data: pd.DataFrame, use_upsert: bool = True): + """将数据放入写入队列(不立即写入) + + Args: + name: 表名 + data: DataFrame 数据 + use_upsert: 若为 True 使用 INSERT OR REPLACE,若为 False 使用普通 INSERT + """ if not data.empty: - self._pending_writes.append((name, data)) + self._pending_writes.append((name, data, use_upsert)) def flush(self): """批量写入所有队列数据。 @@ -310,21 +329,22 @@ class ThreadSafeStorage: if not self._pending_writes: return - # 合并相同表的数据 + # 按表名和 use_upsert 分组 table_data = defaultdict(list) - for name, data in self._pending_writes: - table_data[name].append(data) + for name, data, use_upsert in self._pending_writes: + key = (name, use_upsert) + table_data[key].append(data) # 批量写入每个表 - for name, data_list in table_data.items(): + for (name, use_upsert), data_list in table_data.items(): combined = pd.concat(data_list, ignore_index=True) # 在批量数据中先去重 if "ts_code" in combined.columns and "trade_date" in combined.columns: combined = combined.drop_duplicates( subset=["ts_code", "trade_date"], keep="last" ) - self.storage.save(name, combined, mode="append") + self.storage.save(name, combined, mode="append", use_upsert=use_upsert) self._pending_writes.clear() diff --git a/src/experiment/regression.ipynb b/src/experiment/regression.ipynb index 0942c43..b0680a3 100644 --- a/src/experiment/regression.ipynb +++ b/src/experiment/regression.ipynb @@ -22,8 +22,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:54:34.025295Z", - "start_time": "2026-03-05T15:54:33.223817Z" + "end_time": "2026-03-07T16:27:36.008131Z", + "start_time": "2026-03-07T16:27:36.005668Z" } }, "source": [ @@ -48,7 +48,7 @@ "from src.training.config import TrainingConfig" ], "outputs": [], - "execution_count": 1 + "execution_count": 6 }, { "cell_type": "markdown", @@ -60,8 +60,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:54:34.040804Z", - "start_time": "2026-03-05T15:54:34.036138Z" + "end_time": "2026-03-07T16:27:36.020762Z", + "start_time": "2026-03-07T16:27:36.011650Z" } }, "cell_type": "code", @@ -121,7 +121,7 @@ " return data" ], "outputs": [], - "execution_count": 2 + "execution_count": 7 }, { "cell_type": "markdown", @@ -135,8 +135,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:54:34.050475Z", - "start_time": "2026-03-05T15:54:34.045956Z" + "end_time": "2026-03-07T16:27:36.027366Z", + "start_time": "2026-03-07T16:27:36.024465Z" } }, "cell_type": "code", @@ -174,7 +174,7 @@ "}" ], "outputs": [], - "execution_count": 3 + "execution_count": 8 }, { "cell_type": "markdown", @@ -187,8 +187,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:54:34.069686Z", - "start_time": "2026-03-05T15:54:34.065755Z" + "end_time": "2026-03-07T16:27:36.035196Z", + "start_time": "2026-03-07T16:27:36.031430Z" } }, "source": [ @@ -242,7 +242,7 @@ "PERSIST_MODEL = False" ], "outputs": [], - "execution_count": 4 + "execution_count": 9 }, { "cell_type": "markdown", @@ -257,8 +257,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:54:39.199834Z", - "start_time": "2026-03-05T15:54:34.082579Z" + "end_time": "2026-03-07T16:27:41.855565Z", + "start_time": "2026-03-07T16:27:36.040416Z" } }, "source": [ @@ -396,22 +396,22 @@ "output_type": "stream", "text": [ "数据形状: (7044952, 24)\n", - "数据列: ['ts_code', 'trade_date', 'high', 'vol', 'close', 'low', 'total_mv', 'f_ann_date', 'n_income', 'ma5', 'ma10', 'ma20', 'ma_ratio', 'volatility_5', 'volatility_20', 'vol_ratio', 'return_10', 'return_20', 'return_diff', 'vol_ma5', 'vol_ma20', 'market_cap_rank', 'high_low_ratio', 'return_5']\n", + "数据列: ['ts_code', 'trade_date', 'low', 'close', 'vol', 'high', 'total_mv', 'f_ann_date', 'n_income', 'ma5', 'ma10', 'ma20', 'ma_ratio', 'volatility_5', 'volatility_20', 'vol_ratio', 'return_10', 'return_20', 'return_diff', 'vol_ma5', 'vol_ma20', 'market_cap_rank', 'high_low_ratio', 'return_5']\n", "\n", "前5行预览:\n", "shape: (5, 24)\n", - "┌───────────┬────────────┬─────────┬───────────┬───┬──────────┬────────────┬───────────┬───────────┐\n", - "│ ts_code ┆ trade_date ┆ high ┆ vol ┆ … ┆ vol_ma20 ┆ market_cap ┆ high_low_ ┆ return_5 │\n", - "│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ _rank ┆ ratio ┆ --- │\n", - "│ str ┆ str ┆ f64 ┆ f64 ┆ ┆ f64 ┆ --- ┆ --- ┆ f64 │\n", - "│ ┆ ┆ ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ │\n", - "╞═══════════╪════════════╪═════════╪═══════════╪═══╪══════════╪════════════╪═══════════╪═══════════╡\n", - "│ 000001.SZ ┆ 20200102 ┆ 1850.42 ┆ 1.5302e6 ┆ … ┆ null ┆ 0.993583 ┆ null ┆ -0.004746 │\n", - "│ 000001.SZ ┆ 20200103 ┆ 1889.72 ┆ 1.1162e6 ┆ … ┆ null ┆ 0.993585 ┆ null ┆ -0.02852 │\n", - "│ 000001.SZ ┆ 20200106 ┆ 1893.0 ┆ 862083.5 ┆ … ┆ null ┆ 0.993588 ┆ null ┆ -0.004685 │\n", - "│ 000001.SZ ┆ 20200107 ┆ 1886.45 ┆ 728607.56 ┆ … ┆ null ┆ 0.993588 ┆ null ┆ -0.022743 │\n", - "│ 000001.SZ ┆ 20200108 ┆ 1861.34 ┆ 847824.12 ┆ … ┆ null ┆ 0.993586 ┆ null ┆ -0.008401 │\n", - "└───────────┴────────────┴─────────┴───────────┴───┴──────────┴────────────┴───────────┴───────────┘\n", + "┌───────────┬────────────┬─────────┬─────────┬───┬──────────┬─────────────┬────────────┬───────────┐\n", + "│ ts_code ┆ trade_date ┆ low ┆ close ┆ … ┆ vol_ma20 ┆ market_cap_ ┆ high_low_r ┆ return_5 │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ rank ┆ atio ┆ --- │\n", + "│ str ┆ str ┆ f64 ┆ f64 ┆ ┆ f64 ┆ --- ┆ --- ┆ f64 │\n", + "│ ┆ ┆ ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ │\n", + "╞═══════════╪════════════╪═════════╪═════════╪═══╪══════════╪═════════════╪════════════╪═══════════╡\n", + "│ 000001.SZ ┆ 20200102 ┆ 1806.75 ┆ 1841.69 ┆ … ┆ null ┆ 0.993583 ┆ null ┆ -0.004746 │\n", + "│ 000001.SZ ┆ 20200103 ┆ 1847.15 ┆ 1875.53 ┆ … ┆ null ┆ 0.993585 ┆ null ┆ -0.02852 │\n", + "│ 000001.SZ ┆ 20200106 ┆ 1846.05 ┆ 1863.52 ┆ … ┆ null ┆ 0.993588 ┆ null ┆ -0.004685 │\n", + "│ 000001.SZ ┆ 20200107 ┆ 1850.42 ┆ 1872.26 ┆ … ┆ null ┆ 0.993588 ┆ null ┆ -0.022743 │\n", + "│ 000001.SZ ┆ 20200108 ┆ 1815.49 ┆ 1818.76 ┆ … ┆ null ┆ 0.993586 ┆ null ┆ -0.008401 │\n", + "└───────────┴────────────┴─────────┴─────────┴───┴──────────┴─────────────┴────────────┴───────────┘\n", "\n", "[配置] 训练期: 20200101 - 20241231\n", "[配置] 测试期: 20250101 - 20251231\n", @@ -420,7 +420,7 @@ ] } ], - "execution_count": 5 + "execution_count": 10 }, { "cell_type": "markdown", @@ -433,8 +433,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:54:45.542301Z", - "start_time": "2026-03-05T15:54:39.210579Z" + "end_time": "2026-03-07T16:27:48.155192Z", + "start_time": "2026-03-07T16:27:41.865012Z" } }, "source": [ @@ -478,14 +478,14 @@ ] } ], - "execution_count": 6 + "execution_count": 11 }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:54:46.133946Z", - "start_time": "2026-03-05T15:54:45.552454Z" + "end_time": "2026-03-07T16:27:48.744530Z", + "start_time": "2026-03-07T16:27:48.163043Z" } }, "source": [ @@ -531,47 +531,44 @@ "\n", " 训练集前5行预览:\n", "shape: (5, 24)\n", - "┌───────────┬────────────┬─────────┬───────────┬───┬──────────┬────────────┬───────────┬───────────┐\n", - "│ ts_code ┆ trade_date ┆ high ┆ vol ┆ … ┆ vol_ma20 ┆ market_cap ┆ high_low_ ┆ return_5 │\n", - "│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ _rank ┆ ratio ┆ --- │\n", - "│ str ┆ str ┆ f64 ┆ f64 ┆ ┆ f64 ┆ --- ┆ --- ┆ f64 │\n", - "│ ┆ ┆ ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ │\n", - "╞═══════════╪════════════╪═════════╪═══════════╪═══╪══════════╪════════════╪═══════════╪═══════════╡\n", - "│ 000001.SZ ┆ 20200102 ┆ 1850.42 ┆ 1.5302e6 ┆ … ┆ null ┆ 0.993583 ┆ null ┆ -0.004746 │\n", - "│ 000002.SZ ┆ 20200102 ┆ 4986.64 ┆ 1012130.4 ┆ … ┆ null ┆ 0.99492 ┆ null ┆ -0.011057 │\n", - "│ 000004.SZ ┆ 20200102 ┆ 93.06 ┆ 17853.2 ┆ … ┆ null ┆ 0.057219 ┆ null ┆ -0.000441 │\n", - "│ 000005.SZ ┆ 20200102 ┆ 29.19 ┆ 104134.12 ┆ … ┆ null ┆ 0.28984 ┆ null ┆ 0.022337 │\n", - "│ 000006.SZ ┆ 20200102 ┆ 193.07 ┆ 124751.76 ┆ … ┆ null ┆ 0.631551 ┆ null ┆ 0.012964 │\n", - "└───────────┴────────────┴─────────┴───────────┴───┴──────────┴────────────┴───────────┴───────────┘\n", + "┌───────────┬────────────┬─────────┬─────────┬───┬──────────┬─────────────┬────────────┬───────────┐\n", + "│ ts_code ┆ trade_date ┆ low ┆ close ┆ … ┆ vol_ma20 ┆ market_cap_ ┆ high_low_r ┆ return_5 │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ rank ┆ atio ┆ --- │\n", + "│ str ┆ str ┆ f64 ┆ f64 ┆ ┆ f64 ┆ --- ┆ --- ┆ f64 │\n", + "│ ┆ ┆ ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ │\n", + "╞═══════════╪════════════╪═════════╪═════════╪═══╪══════════╪═════════════╪════════════╪═══════════╡\n", + "│ 000001.SZ ┆ 20200102 ┆ 1806.75 ┆ 1841.69 ┆ … ┆ null ┆ 0.993583 ┆ null ┆ -0.004746 │\n", + "│ 000002.SZ ┆ 20200102 ┆ 4824.87 ┆ 4832.29 ┆ … ┆ null ┆ 0.99492 ┆ null ┆ -0.011057 │\n", + "│ 000004.SZ ┆ 20200102 ┆ 90.1 ┆ 90.75 ┆ … ┆ null ┆ 0.057219 ┆ null ┆ -0.000441 │\n", + "│ 000005.SZ ┆ 20200102 ┆ 28.82 ┆ 29.1 ┆ … ┆ null ┆ 0.28984 ┆ null ┆ 0.022337 │\n", + "│ 000006.SZ ┆ 20200102 ┆ 190.24 ┆ 191.3 ┆ … ┆ null ┆ 0.631551 ┆ null ┆ 0.012964 │\n", + "└───────────┴────────────┴─────────┴─────────┴───┴──────────┴─────────────┴────────────┴───────────┘\n", "\n", " 测试集前5行预览:\n", "shape: (5, 24)\n", - "┌───────────┬────────────┬─────────┬───────────┬───┬───────────┬───────────┬───────────┬───────────┐\n", - "│ ts_code ┆ trade_date ┆ high ┆ vol ┆ … ┆ vol_ma20 ┆ market_ca ┆ high_low_ ┆ return_5 │\n", - "│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ p_rank ┆ ratio ┆ --- │\n", - "│ str ┆ str ┆ f64 ┆ f64 ┆ ┆ f64 ┆ --- ┆ --- ┆ f64 │\n", - "│ ┆ ┆ ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ │\n", - "╞═══════════╪════════════╪═════════╪═══════════╪═══╪═══════════╪═══════════╪═══════════╪═══════════╡\n", - "│ 000001.SZ ┆ 20250102 ┆ 1504.02 ┆ 1.8196e6 ┆ … ┆ 1.2151e6 ┆ 0.991617 ┆ 0.063478 ┆ -0.002622 │\n", - "│ 000002.SZ ┆ 20250102 ┆ 1337.34 ┆ 1.1827e6 ┆ … ┆ 1.2839e6 ┆ 0.970007 ┆ 0.020839 ┆ -0.022509 │\n", - "│ 000004.SZ ┆ 20250102 ┆ 58.48 ┆ 119760.37 ┆ … ┆ 159807.91 ┆ 0.099106 ┆ 0.131858 ┆ -0.064897 │\n", - "│ ┆ ┆ ┆ ┆ ┆ 8 ┆ ┆ ┆ │\n", - "│ 000006.SZ ┆ 20250102 ┆ 298.84 ┆ 307195.1 ┆ … ┆ 404264.21 ┆ 0.72392 ┆ 0.028423 ┆ -0.048278 │\n", - "│ ┆ ┆ ┆ ┆ ┆ 1 ┆ ┆ ┆ │\n", - "│ 000007.SZ ┆ 20250102 ┆ 60.22 ┆ 68219.01 ┆ … ┆ 88380.284 ┆ 0.183495 ┆ 0.391829 ┆ 0.015649 │\n", - "│ ┆ ┆ ┆ ┆ ┆ 5 ┆ ┆ ┆ │\n", - "└───────────┴────────────┴─────────┴───────────┴───┴───────────┴───────────┴───────────┴───────────┘\n" + "┌───────────┬────────────┬─────────┬─────────┬───┬────────────┬────────────┬───────────┬───────────┐\n", + "│ ts_code ┆ trade_date ┆ low ┆ close ┆ … ┆ vol_ma20 ┆ market_cap ┆ high_low_ ┆ return_5 │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ _rank ┆ ratio ┆ --- │\n", + "│ str ┆ str ┆ f64 ┆ f64 ┆ ┆ f64 ┆ --- ┆ --- ┆ f64 │\n", + "│ ┆ ┆ ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ │\n", + "╞═══════════╪════════════╪═════════╪═════════╪═══╪════════════╪════════════╪═══════════╪═══════════╡\n", + "│ 000001.SZ ┆ 20250102 ┆ 1455.46 ┆ 1460.57 ┆ … ┆ 1.2151e6 ┆ 0.991617 ┆ 0.063478 ┆ -0.002622 │\n", + "│ 000002.SZ ┆ 20250102 ┆ 1284.65 ┆ 1291.92 ┆ … ┆ 1.2839e6 ┆ 0.970007 ┆ 0.020839 ┆ -0.022509 │\n", + "│ 000004.SZ ┆ 20250102 ┆ 54.17 ┆ 57.63 ┆ … ┆ 159807.918 ┆ 0.099106 ┆ 0.131858 ┆ -0.064897 │\n", + "│ 000006.SZ ┆ 20250102 ┆ 285.33 ┆ 288.12 ┆ … ┆ 404264.211 ┆ 0.72392 ┆ 0.028423 ┆ -0.048278 │\n", + "│ 000007.SZ ┆ 20250102 ┆ 57.49 ┆ 58.15 ┆ … ┆ 88380.2845 ┆ 0.183495 ┆ 0.391829 ┆ 0.015649 │\n", + "└───────────┴────────────┴─────────┴─────────┴───┴────────────┴────────────┴───────────┴───────────┘\n" ] } ], - "execution_count": 7 + "execution_count": 12 }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:54:46.983171Z", - "start_time": "2026-03-05T15:54:46.145439Z" + "end_time": "2026-03-07T16:27:49.562499Z", + "start_time": "2026-03-07T16:27:48.753734Z" } }, "source": [ @@ -626,18 +623,18 @@ "\n", " 训练集处理后前5行预览:\n", "shape: (5, 24)\n", - "┌───────────┬────────────┬──────────┬───────────┬───┬──────────┬───────────┬───────────┬───────────┐\n", - "│ ts_code ┆ trade_date ┆ high ┆ vol ┆ … ┆ vol_ma20 ┆ market_ca ┆ high_low_ ┆ return_5 │\n", - "│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ p_rank ┆ ratio ┆ --- │\n", - "│ str ┆ str ┆ f64 ┆ f64 ┆ ┆ f64 ┆ --- ┆ --- ┆ f64 │\n", - "│ ┆ ┆ ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ │\n", - "╞═══════════╪════════════╪══════════╪═══════════╪═══╪══════════╪═══════════╪═══════════╪═══════════╡\n", - "│ 000001.SZ ┆ 20200102 ┆ 7.219126 ┆ 4.505425 ┆ … ┆ null ┆ 1.579213 ┆ null ┆ -0.004746 │\n", - "│ 000002.SZ ┆ 20200102 ┆ 7.219126 ┆ 2.764839 ┆ … ┆ null ┆ 1.579213 ┆ null ┆ -0.011057 │\n", - "│ 000004.SZ ┆ 20200102 ┆ 0.115067 ┆ -0.575482 ┆ … ┆ null ┆ -1.671014 ┆ null ┆ -0.000441 │\n", - "│ 000005.SZ ┆ 20200102 ┆ -0.29753 ┆ -0.285617 ┆ … ┆ null ┆ -0.862878 ┆ null ┆ 0.022337 │\n", - "│ 000006.SZ ┆ 20200102 ┆ 0.761125 ┆ -0.216351 ┆ … ┆ null ┆ 0.324248 ┆ null ┆ 0.012964 │\n", - "└───────────┴────────────┴──────────┴───────────┴───┴──────────┴───────────┴───────────┴───────────┘\n", + "┌───────────┬────────────┬───────────┬──────────┬───┬──────────┬───────────┬───────────┬───────────┐\n", + "│ ts_code ┆ trade_date ┆ low ┆ close ┆ … ┆ vol_ma20 ┆ market_ca ┆ high_low_ ┆ return_5 │\n", + "│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ p_rank ┆ ratio ┆ --- │\n", + "│ str ┆ str ┆ f64 ┆ f64 ┆ ┆ f64 ┆ --- ┆ --- ┆ f64 │\n", + "│ ┆ ┆ ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ │\n", + "╞═══════════╪════════════╪═══════════╪══════════╪═══╪══════════╪═══════════╪═══════════╪═══════════╡\n", + "│ 000001.SZ ┆ 20200102 ┆ 7.215424 ┆ 7.219817 ┆ … ┆ null ┆ 1.579213 ┆ null ┆ -0.004746 │\n", + "│ 000002.SZ ┆ 20200102 ┆ 7.215424 ┆ 7.219817 ┆ … ┆ null ┆ 1.579213 ┆ null ┆ -0.011057 │\n", + "│ 000004.SZ ┆ 20200102 ┆ 0.118662 ┆ 0.111432 ┆ … ┆ null ┆ -1.671014 ┆ null ┆ -0.000441 │\n", + "│ 000005.SZ ┆ 20200102 ┆ -0.292838 ┆ -0.29447 ┆ … ┆ null ┆ -0.862878 ┆ null ┆ 0.022337 │\n", + "│ 000006.SZ ┆ 20200102 ┆ 0.791109 ┆ 0.77345 ┆ … ┆ null ┆ 0.324248 ┆ null ┆ 0.012964 │\n", + "└───────────┴────────────┴───────────┴──────────┴───┴──────────┴───────────┴───────────┴───────────┘\n", "\n", " 训练集特征统计:\n", " 特征数: 15\n", @@ -651,14 +648,14 @@ ] } ], - "execution_count": 8 + "execution_count": 13 }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:55:04.341897Z", - "start_time": "2026-03-05T15:54:46.988330Z" + "end_time": "2026-03-07T16:28:09.621524Z", + "start_time": "2026-03-07T16:27:49.566330Z" } }, "source": [ @@ -709,14 +706,14 @@ ] } ], - "execution_count": 9 + "execution_count": 14 }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:55:04.405805Z", - "start_time": "2026-03-05T15:55:04.349104Z" + "end_time": "2026-03-07T16:28:09.687281Z", + "start_time": "2026-03-07T16:28:09.625395Z" } }, "source": [ @@ -756,14 +753,14 @@ ] } ], - "execution_count": 10 + "execution_count": 15 }, { "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:55:05.493456Z", - "start_time": "2026-03-05T15:55:04.412467Z" + "end_time": "2026-03-07T16:28:10.718020Z", + "start_time": "2026-03-07T16:28:09.691077Z" } }, "source": [ @@ -798,14 +795,14 @@ " 预测完成!\n", "\n", " 预测结果统计:\n", - " 均值: 0.000637\n", - " 标准差: 0.006533\n", - " 最小值: -0.125675\n", - " 最大值: 0.148845\n" + " 均值: 0.000635\n", + " 标准差: 0.006529\n", + " 最小值: -0.125836\n", + " 最大值: 0.149914\n" ] } ], - "execution_count": 11 + "execution_count": 16 }, { "cell_type": "markdown", @@ -818,8 +815,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:55:05.517099Z", - "start_time": "2026-03-05T15:55:05.500111Z" + "end_time": "2026-03-07T16:28:10.746425Z", + "start_time": "2026-03-07T16:28:10.723160Z" } }, "source": [ @@ -859,47 +856,48 @@ "================================================================================\n", "\n", "结果数据形状: (771207, 25)\n", - "结果列: ['ts_code', 'trade_date', 'high', 'vol', 'close', 'low', 'total_mv', 'f_ann_date', 'n_income', 'ma5', 'ma10', 'ma20', 'ma_ratio', 'volatility_5', 'volatility_20', 'vol_ratio', 'return_10', 'return_20', 'return_diff', 'vol_ma5', 'vol_ma20', 'market_cap_rank', 'high_low_ratio', 'return_5', 'prediction']\n", + "结果列: ['ts_code', 'trade_date', 'low', 'close', 'vol', 'high', 'total_mv', 'f_ann_date', 'n_income', 'ma5', 'ma10', 'ma20', 'ma_ratio', 'volatility_5', 'volatility_20', 'vol_ratio', 'return_10', 'return_20', 'return_diff', 'vol_ma5', 'vol_ma20', 'market_cap_rank', 'high_low_ratio', 'return_5', 'prediction']\n", "\n", "结果前10行预览:\n", "shape: (10, 25)\n", "┌───────────┬───────────┬───────────┬───────────┬───┬───────────┬───────────┬───────────┬──────────┐\n", - "│ ts_code ┆ trade_dat ┆ high ┆ vol ┆ … ┆ market_ca ┆ high_low_ ┆ return_5 ┆ predicti │\n", + "│ ts_code ┆ trade_dat ┆ low ┆ close ┆ … ┆ market_ca ┆ high_low_ ┆ return_5 ┆ predicti │\n", "│ --- ┆ e ┆ --- ┆ --- ┆ ┆ p_rank ┆ ratio ┆ --- ┆ on │\n", "│ str ┆ --- ┆ f64 ┆ f64 ┆ ┆ --- ┆ --- ┆ f64 ┆ --- │\n", "│ ┆ str ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ ┆ f64 │\n", "╞═══════════╪═══════════╪═══════════╪═══════════╪═══╪═══════════╪═══════════╪═══════════╪══════════╡\n", - "│ 000001.SZ ┆ 20250102 ┆ 7.219126 ┆ 5.477561 ┆ … ┆ 1.575139 ┆ -1.347097 ┆ -0.002622 ┆ -0.00447 │\n", + "│ 000001.SZ ┆ 20250102 ┆ 7.215424 ┆ 7.219817 ┆ … ┆ 1.575139 ┆ -1.347097 ┆ -0.002622 ┆ -0.00414 │\n", + "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 1 │\n", + "│ 000002.SZ ┆ 20250102 ┆ 7.215424 ┆ 7.219817 ┆ … ┆ 1.500066 ┆ -1.494802 ┆ -0.022509 ┆ -0.00644 │\n", "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 3 │\n", - "│ 000002.SZ ┆ 20250102 ┆ 7.219126 ┆ 3.337762 ┆ … ┆ 1.500066 ┆ -1.494802 ┆ -0.022509 ┆ -0.00736 │\n", - "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 9 │\n", - "│ 000004.SZ ┆ 20250102 ┆ -0.108318 ┆ -0.23312 ┆ … ┆ -1.525498 ┆ -1.110228 ┆ -0.064897 ┆ 0.017464 │\n", - "│ 000006.SZ ┆ 20250102 ┆ 1.444393 ┆ 0.396576 ┆ … ┆ 0.645142 ┆ -1.46853 ┆ -0.048278 ┆ -0.00465 │\n", - "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 7 │\n", - "│ 000007.SZ ┆ 20250102 ┆ -0.097078 ┆ -0.406275 ┆ … ┆ -1.232326 ┆ -0.209675 ┆ 0.015649 ┆ -0.00109 │\n", - "│ 000008.SZ ┆ 20250102 ┆ -0.054701 ┆ 3.045596 ┆ … ┆ 0.410216 ┆ -1.48541 ┆ -0.066939 ┆ -0.00931 │\n", - "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 9 │\n", - "│ 000009.SZ ┆ 20250102 ┆ 0.045687 ┆ 0.167823 ┆ … ┆ 1.197186 ┆ -1.358101 ┆ -0.036045 ┆ 0.001988 │\n", - "│ 000010.SZ ┆ 20250102 ┆ -0.289132 ┆ 0.530622 ┆ … ┆ -0.872494 ┆ -1.382331 ┆ 0.092123 ┆ -0.00750 │\n", - "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 5 │\n", - "│ 000011.SZ ┆ 20250102 ┆ -0.233641 ┆ -0.493267 ┆ … ┆ -0.098467 ┆ -1.409992 ┆ -0.022094 ┆ -0.00158 │\n", - "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 6 │\n", - "│ 000012.SZ ┆ 20250102 ┆ 0.540518 ┆ -0.084753 ┆ … ┆ 1.006268 ┆ -1.411495 ┆ -0.029188 ┆ 0.000647 │\n", + "│ 000004.SZ ┆ 20250102 ┆ -0.122611 ┆ -0.106629 ┆ … ┆ -1.525498 ┆ -1.110228 ┆ -0.064897 ┆ 0.018069 │\n", + "│ 000006.SZ ┆ 20250102 ┆ 1.429646 ┆ 1.41091 ┆ … ┆ 0.645142 ┆ -1.46853 ┆ -0.048278 ┆ -0.00495 │\n", + "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 8 │\n", + "│ 000007.SZ ┆ 20250102 ┆ -0.100317 ┆ -0.103205 ┆ … ┆ -1.232326 ┆ -0.209675 ┆ 0.015649 ┆ -0.00123 │\n", + "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 1 │\n", + "│ 000008.SZ ┆ 20250102 ┆ -0.063519 ┆ -0.067059 ┆ … ┆ 0.410216 ┆ -1.48541 ┆ -0.066939 ┆ -0.01023 │\n", + "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 3 │\n", + "│ 000009.SZ ┆ 20250102 ┆ 0.045333 ┆ 0.039996 ┆ … ┆ 1.197186 ┆ -1.358101 ┆ -0.036045 ┆ 0.002236 │\n", + "│ 000010.SZ ┆ 20250102 ┆ -0.293174 ┆ -0.293811 ┆ … ┆ -0.872494 ┆ -1.382331 ┆ 0.092123 ┆ -0.00730 │\n", + "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 3 │\n", + "│ 000011.SZ ┆ 20250102 ┆ -0.233141 ┆ -0.235741 ┆ … ┆ -0.098467 ┆ -1.409992 ┆ -0.022094 ┆ -0.00176 │\n", + "│ ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 3 │\n", + "│ 000012.SZ ┆ 20250102 ┆ 0.54057 ┆ 0.526749 ┆ … ┆ 1.006268 ┆ -1.411495 ┆ -0.029188 ┆ 0.000613 │\n", "└───────────┴───────────┴───────────┴───────────┴───┴───────────┴───────────┴───────────┴──────────┘\n", "\n", "结果后5行预览:\n", "shape: (5, 25)\n", "┌───────────┬───────────┬───────────┬───────────┬───┬───────────┬───────────┬──────────┬───────────┐\n", - "│ ts_code ┆ trade_dat ┆ high ┆ vol ┆ … ┆ market_ca ┆ high_low_ ┆ return_5 ┆ predictio │\n", + "│ ts_code ┆ trade_dat ┆ low ┆ close ┆ … ┆ market_ca ┆ high_low_ ┆ return_5 ┆ predictio │\n", "│ --- ┆ e ┆ --- ┆ --- ┆ ┆ p_rank ┆ ratio ┆ --- ┆ n │\n", "│ str ┆ --- ┆ f64 ┆ f64 ┆ ┆ --- ┆ --- ┆ f64 ┆ --- │\n", "│ ┆ str ┆ ┆ ┆ ┆ f64 ┆ f64 ┆ ┆ f64 │\n", "╞═══════════╪═══════════╪═══════════╪═══════════╪═══╪═══════════╪═══════════╪══════════╪═══════════╡\n", - "│ 605588.SH ┆ 20251231 ┆ -0.155411 ┆ -0.600921 ┆ … ┆ -1.041064 ┆ 0.083361 ┆ null ┆ 0.002664 │\n", - "│ 605589.SH ┆ 20251231 ┆ -0.286677 ┆ -0.172371 ┆ … ┆ 1.082326 ┆ 0.586743 ┆ null ┆ 0.003911 │\n", - "│ 605598.SH ┆ 20251231 ┆ 0.167069 ┆ -0.264286 ┆ … ┆ 0.865913 ┆ 1.46704 ┆ null ┆ -0.004255 │\n", - "│ 605599.SH ┆ 20251231 ┆ -0.361225 ┆ -0.487294 ┆ … ┆ 0.623404 ┆ 1.560273 ┆ null ┆ 0.004604 │\n", - "│ 689009.SH ┆ 20251231 ┆ -0.110062 ┆ -0.485904 ┆ … ┆ 1.304467 ┆ -1.339619 ┆ null ┆ -0.000968 │\n", + "│ 605588.SH ┆ 20251231 ┆ -0.150009 ┆ -0.151005 ┆ … ┆ -1.041064 ┆ 0.083361 ┆ null ┆ 0.002801 │\n", + "│ 605589.SH ┆ 20251231 ┆ -0.282833 ┆ -0.286372 ┆ … ┆ 1.082326 ┆ 0.586743 ┆ null ┆ 0.003757 │\n", + "│ 605598.SH ┆ 20251231 ┆ 0.163451 ┆ 0.166474 ┆ … ┆ 0.865913 ┆ 1.46704 ┆ null ┆ -0.003742 │\n", + "│ 605599.SH ┆ 20251231 ┆ -0.360996 ┆ -0.359651 ┆ … ┆ 0.623404 ┆ 1.560273 ┆ null ┆ 0.004761 │\n", + "│ 689009.SH ┆ 20251231 ┆ -0.101257 ┆ -0.108012 ┆ … ┆ 1.304467 ┆ -1.339619 ┆ null ┆ -0.000987 │\n", "└───────────┴───────────┴───────────┴───────────┴───┴───────────┴───────────┴──────────┴───────────┘\n", "\n", "每日预测样本数统计:\n", @@ -914,21 +912,21 @@ "│ --- ┆ --- ┆ --- ┆ --- │\n", "│ str ┆ str ┆ f64 ┆ f64 │\n", "╞═══════════╪════════════╪═══════════╪════════════╡\n", - "│ 000001.SZ ┆ 20250102 ┆ -0.002622 ┆ -0.004473 │\n", - "│ 000002.SZ ┆ 20250102 ┆ -0.022509 ┆ -0.007369 │\n", - "│ 000004.SZ ┆ 20250102 ┆ -0.064897 ┆ 0.017464 │\n", - "│ 000006.SZ ┆ 20250102 ┆ -0.048278 ┆ -0.004657 │\n", - "│ 000007.SZ ┆ 20250102 ┆ 0.015649 ┆ -0.00109 │\n", - "│ 000008.SZ ┆ 20250102 ┆ -0.066939 ┆ -0.009319 │\n", - "│ 000009.SZ ┆ 20250102 ┆ -0.036045 ┆ 0.001988 │\n", - "│ 000010.SZ ┆ 20250102 ┆ 0.092123 ┆ -0.007505 │\n", - "│ 000011.SZ ┆ 20250102 ┆ -0.022094 ┆ -0.001586 │\n", - "│ 000012.SZ ┆ 20250102 ┆ -0.029188 ┆ 0.000647 │\n", + "│ 000001.SZ ┆ 20250102 ┆ -0.002622 ┆ -0.004141 │\n", + "│ 000002.SZ ┆ 20250102 ┆ -0.022509 ┆ -0.006443 │\n", + "│ 000004.SZ ┆ 20250102 ┆ -0.064897 ┆ 0.018069 │\n", + "│ 000006.SZ ┆ 20250102 ┆ -0.048278 ┆ -0.004958 │\n", + "│ 000007.SZ ┆ 20250102 ┆ 0.015649 ┆ -0.001231 │\n", + "│ 000008.SZ ┆ 20250102 ┆ -0.066939 ┆ -0.010233 │\n", + "│ 000009.SZ ┆ 20250102 ┆ -0.036045 ┆ 0.002236 │\n", + "│ 000010.SZ ┆ 20250102 ┆ 0.092123 ┆ -0.007303 │\n", + "│ 000011.SZ ┆ 20250102 ┆ -0.022094 ┆ -0.001763 │\n", + "│ 000012.SZ ┆ 20250102 ┆ -0.029188 ┆ 0.000613 │\n", "└───────────┴────────────┴───────────┴────────────┘\n" ] } ], - "execution_count": 12 + "execution_count": 17 }, { "cell_type": "markdown", @@ -940,8 +938,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:55:05.827674Z", - "start_time": "2026-03-05T15:55:05.522095Z" + "end_time": "2026-03-07T16:28:11.060067Z", + "start_time": "2026-03-07T16:28:10.751743Z" } }, "cell_type": "code", @@ -1013,22 +1011,22 @@ "│ --- ┆ --- ┆ --- │\n", "│ str ┆ f64 ┆ str │\n", "╞════════════╪══════════╪═══════════╡\n", - "│ 2025-01-02 ┆ 0.130576 ┆ 603007.SH │\n", - "│ 2025-01-02 ┆ 0.088839 ┆ 603559.SH │\n", - "│ 2025-01-02 ┆ 0.060968 ┆ 000595.SZ │\n", - "│ 2025-01-02 ┆ 0.054302 ┆ 600811.SH │\n", - "│ 2025-01-02 ┆ 0.045811 ┆ 603366.SH │\n", + "│ 2025-01-02 ┆ 0.129296 ┆ 603007.SH │\n", + "│ 2025-01-02 ┆ 0.087661 ┆ 603559.SH │\n", + "│ 2025-01-02 ┆ 0.056859 ┆ 000595.SZ │\n", + "│ 2025-01-02 ┆ 0.052261 ┆ 600811.SH │\n", + "│ 2025-01-02 ┆ 0.046187 ┆ 603366.SH │\n", "│ … ┆ … ┆ … │\n", - "│ 2025-01-06 ┆ 0.143688 ┆ 603007.SH │\n", - "│ 2025-01-06 ┆ 0.063078 ┆ 002691.SZ │\n", - "│ 2025-01-06 ┆ 0.062373 ┆ 603959.SH │\n", - "│ 2025-01-06 ┆ 0.055252 ┆ 000638.SZ │\n", - "│ 2025-01-06 ┆ 0.047705 ┆ 002713.SZ │\n", + "│ 2025-01-06 ┆ 0.145456 ┆ 603007.SH │\n", + "│ 2025-01-06 ┆ 0.066654 ┆ 603959.SH │\n", + "│ 2025-01-06 ┆ 0.06255 ┆ 002691.SZ │\n", + "│ 2025-01-06 ┆ 0.054795 ┆ 000638.SZ │\n", + "│ 2025-01-06 ┆ 0.047319 ┆ 002713.SZ │\n", "└────────────┴──────────┴───────────┘\n" ] } ], - "execution_count": 13 + "execution_count": 18 }, { "cell_type": "markdown", @@ -1041,8 +1039,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:55:05.840200Z", - "start_time": "2026-03-05T15:55:05.836355Z" + "end_time": "2026-03-07T16:28:11.069209Z", + "start_time": "2026-03-07T16:28:11.065068Z" } }, "source": [ @@ -1062,21 +1060,21 @@ "text": [ "\n", "特征重要性:\n", - "return_10 3244.585386\n", - "ma_ratio 2871.645070\n", - "return_20 2686.807540\n", - "vol_ratio 2667.200664\n", - "high_low_ratio 2461.679219\n", - "return_diff 1491.578852\n", - "volatility_5 1360.579366\n", - "market_cap_rank 697.769018\n", - "vol_ma5 665.639110\n", - "vol_ma20 640.332628\n", - "n_income 536.010082\n", - "ma5 489.527820\n", - "ma20 481.715007\n", - "ma10 303.121463\n", - "volatility_20 224.481188\n", + "return_10 3245.995642\n", + "ma_ratio 2818.976538\n", + "vol_ratio 2701.151667\n", + "return_20 2681.762756\n", + "high_low_ratio 2469.737874\n", + "return_diff 1463.681328\n", + "volatility_5 1357.026476\n", + "market_cap_rank 722.088673\n", + "vol_ma5 653.087969\n", + "vol_ma20 631.252641\n", + "ma20 548.830554\n", + "n_income 495.525785\n", + "ma5 469.811824\n", + "ma10 305.156890\n", + "volatility_20 203.306830\n", "dtype: float64\n", "\n", "================================================================================\n", @@ -1085,7 +1083,7 @@ ] } ], - "execution_count": 14 + "execution_count": 19 }, { "cell_type": "markdown", @@ -1102,8 +1100,8 @@ "cell_type": "code", "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:55:06.004470Z", - "start_time": "2026-03-05T15:55:05.857163Z" + "end_time": "2026-03-07T16:28:11.377695Z", + "start_time": "2026-03-07T16:28:11.076235Z" } }, "source": [ @@ -1127,7 +1125,7 @@ ] } ], - "execution_count": 15 + "execution_count": 20 }, { "cell_type": "markdown", @@ -1144,8 +1142,8 @@ { "metadata": { "ExecuteTime": { - "end_time": "2026-03-05T15:55:06.162872Z", - "start_time": "2026-03-05T15:55:06.013403Z" + "end_time": "2026-03-07T16:28:11.542731Z", + "start_time": "2026-03-07T16:28:11.384139Z" } }, "cell_type": "code", @@ -1195,7 +1193,7 @@ "text/plain": [ "
" ], - "image/png": "iVBORw0KGgoAAAANSUhEUgAAA9wAAAMWCAYAAAADI47PAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjgsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvwVt1zgAAAAlwSFlzAAAPYQAAD2EBqD+naQAAwwhJREFUeJzs3QmcTfX/x/EPYydrWZLsIktEVEQlEUkbKpKoVFJZSkqSiFCURLtSWlW0SipptYQolFCSrWxFGGb+j/f39zj3f+fOvWO2Y2bOvJ6PxzXm3HPPPXO/c++cz/fz+X6/eRITExMNAAAAAABkqryZezgAAAAAAEDADQAAAACAT8hwAwAAAADgAwJuAAAAAAB8QMANAAAAAIAPCLgBAAAAAPABATcAAAAAAD4g4AYAAAAAwAcE3AAAAAAA+ICAGwAAIAts3LjRChUqZF999dVReb6ePXtalSpV0vXYu+66y5o1a5bp5wQAQUfADQAInGnTplmePHmi3hQ4+OHrr7+24cOH265duyy7vh6LFy+2nOqJJ55wP0eQjBgxwgWxzZs3T3bfggULrEuXLlaxYkUrUKCAlShRwu2rx2zduvWon+vtt99uy5cvt9mzZx/15waAnCxfVp8AAAB+UXBStWrVJNvq1avnW8B9//33uyxiyZIlfXmO3EwB97HHHute3yDYvn27vfDCC+4WadiwYfbAAw9YtWrV3M+rr/v377clS5bYww8/7B7z66+/pvk5n376aUtISEjX+ZYvX946depk48ePt4suuihdxwCA3IiAGwAQWBdccIE1adLEcrK9e/da0aJFLbfat2+fFSlSxILmpZdesnz58lnHjh2TbH/ttddcsK3s9vTp0112O9yECRPcLT3y58+foXPWOXXu3NnWrVvnOgEAAEdGSTkAINf68MMP7ayzznIB7THHHGMdOnSwH3/8Mck+P/zwQyjLqPG2yvT16tXL/v7779A+KiW/44473P+VUffK1zds2OBu+n+0cmht12PDj6NtP/30k1111VVWqlQpa9GiRZIgrXHjxla4cGErXbq0XXHFFW4ccHroZypWrJj9/vvvduGFF7r/q3x58uTJ7v4VK1bYueee616bypUr24wZM6KWqX/xxRfWp08fK1OmjBUvXtx69OhhO3fujJqhrlu3rhUsWNCOP/5469u3b7Ly+7PPPttVICiT27JlSxdo33333W7csdpl/vz5oddW+8qOHTts0KBBVr9+ffcz6BzU0aLy53Cff/65e9zrr79uo0aNshNOOMG1Z+vWrW3t2rXJzve7776z9u3buzbQa9CgQQN79NFHk+yzevVqu/zyy11b6Fjq3EltyfU777zjSsR1zpHZbWXyn3322WTBtqi0PPx3RmbNmuV+d/W66vWtXr26C9oPHz6c4hhu73dTWeunnnrKPU6PP+2002zRokXJnvu8884LPR8AIHXIcAMAAmv37t32119/JdmmYEaUPbzmmmusbdu29tBDD7lM6pQpU1yAu3Tp0lBgMnfuXJfRu/baa12wrcBPwYm+fvvtty5gufTSS+3nn3+2V155xWUfvec47rjjXOlwWimLWLNmTXvwwQctMTHRbVOQeO+997os43XXXeeOO2nSJBeY6nzTU8augEzBqY4xduxYe/nll+2WW25xAeY999xj3bp1cz/b1KlTXSB9xhlnJCvR1/56bgWBa9asca/hb7/9FgpwRfep3F4B20033RTaT0GdJgwLz7yqI0PnpM6E7t27W7ly5Vxw3a9fPxec6rxE20Vto+BVr5nOTeObn3zySWvVqpXruFAQGm7MmDGWN29eF6Tr90M/t35OBdgetbk6ISpUqGC33Xaba/dVq1bZe++9574Xtb/GXquTQvMC6DVTMH/xxRfbzJkz7ZJLLon5usfHx7ufXa9FOP0O6ab2jQzEU6LOD+0/YMAA9/XTTz91gfuePXts3LhxR3y8OlP++ecf13GiNtNronbXaxveNgr2FZSrzfr375/q8wOAXC0RAICAef755xWlRr3JP//8k1iyZMnE66+/PsnjtmzZkliiRIkk2/ft25fs+K+88oo71hdffBHaNm7cOLdt/fr1SfbV99quc4qk7ffdd1/oe/1f26688sok+23YsCExLi4ucdSoUUm2r1ixIjFfvnzJtsd6PRYtWhTads0117htDz74YGjbzp07EwsXLpyYJ0+exFdffTW0ffXq1cnO1Ttm48aNEw8ePBjaPnbsWLd91qxZ7vtt27YlFihQIPH8889PPHz4cGi/xx9/3O333HPPhba1atXKbZs6dWqyn6Fu3bru/kj79+9PclzvNS9YsGDiiBEjQts+++wzd+w6deokHjhwILT90Ucfddv1WsqhQ4cSq1atmli5cmX3eoRLSEgI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pZ8h/BzVwYCcL5/lAOrdGTVqlOs92rRpk/vlUwB9++23W+vWrS0o3nrrLXvwwQdt7dq17sOkZs2aNnDgQPcmTqtmo+fZoXxFfTlPZK2CcYk2tqlZveFz7MDhPDRHwNC+wUcbBxvtG3y08dGxYUwH9/Wjjz5Ksn3atGkuFliyZIm1bNnSbfv6669typQp1rRpU/f90KFDbcKECW4fZawLFCjgst8eXWfPmjXL+vXr5zLJosy4jqH7Xn/99VSd46FDh+y2226zcePGuWDac/LJJyfbV8dWVnvYsGH24YcfRj2efq6SJUum6rmRc2T7DPeGDRuscePG9umnn7pfZvVa6Y13zjnnuN6uICldurTdc8899s0339gPP/zgesp0mzNnTlafGgAAAJDldu/eHbpu9iiD/dprr9mOHTssISHBXn31VVcifvbZZ0c9hjLhKu/WdXZGfP/99y4ZmDdvXhfYV6hQwS644AJbuXJlkv1++uknGzFihL344otu31iUUNQx2rRp4zLlCIZsH3DffPPNrudp4cKFbixFrVq1rG7dujZgwABXWiK///67derUyYoVK2bFixd3JSRbt26NeUy9+ZQdD6exFhq34alSpYqNHDnSlajouJUrV3Zvzu3bt4eeSyUhixcvTtLjpl4pBch16tRx+7Rr186VhKSGzuuSSy5xj61evbrrMdNzfPnll+l45QAAAIDgUDCta/jmzZtbvXr1QtuVkVZmukyZMlawYEHr06ePvf3221ajRo2ox3n22Wetbdu2bjx1Rqxbty40fFVZ9ffee8+N4dY1vYJ/OXDggF155ZUucXjiiSdGPY6C7KlTp7rydN0qVarkjqGAHjlfti4p1y+qstkqJ1eZRyQFt3rjeQGwxniotEOZ765du7oJCDJCpSgq8b733nvd/1XarR60Xr16uTfN4MGDXUD+448/hspR9u3bZ+PHj7fp06e7Hqzu3bvboEGD7OWXX07TcycmJrqsvsZyPPTQQzH305tYN8+ePXvc14J5Ey0uLjHdPzuyL7Vt+FcEC+0bfLRxsNG+wUcbHx0KoCNpfLWyx5999lmS+1UhunPnThc3KOhWkkwJOF1L169fP8kx/vjjD5ccmzFjRtTn8LbpWjza/eEOHjzovt5111120UUXuf8/9dRTbmy4suzXX3+9ixdOOukkF5voeIpVvOfxjl+tWjV3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P2HCBPdBce+997r/q7xFPW+9evVy2fbBgwe7gFzjSPThI/v27bPx48e7njT1rnXv3t0GDRpkL7/88hGfT8d+6aWXXIDdtGlT92GlcofwsppIKo3RLbzEQQrmTbS4uGw/WgDpoLYN/4pgoX2DjzYONto3+HJqGyuQDadx2StXrnSTnXn3ecGwyrd1DStjx451AfbTTz/trsk1GvWmm25yZeV6bOHChe25556zjh07uuRRhQoV3PF0UyCusdSijHilSpVc9ltJpWg05lvl6Lr+V9CtZJcSaap0rV+/vstY6/kjfxbRfdquwNs7f8UDmlDt/vvvd4m7Dz/8MHTNfqTXKdpzIBjiM9jGaX1ctg64165d695UtWvXjrnPvHnzXJm5JkjQm9h7QysLrvEdmokxvVTXr541GTZsmBtTouN17tzZbVPAfcYZZ7hsumZT9Bpg6tSpVr169dCH2YgRI1L1fMpsa1yMZnrUz63OgxtvvDHFknKN79aHSKShjRKsSJHD6fq5kTM80CQhq08BPqJ9g482DjbaN/hyWhsrieN56qmnXAm2Eks//PCDu4lXIarAO3x/jVfV/tq2fPly91VJol27drnbBRdc4ILjoUOHusBWFaGiKs/w4ygjru91jRtJ+z7xxBP22GOPuTJylaOrPFxVproWVpCvkvc///wzyTEVaP/9999uf233klwak+5VmSpBpiBc2XaVw6eGOgYQbHPT2cZKsAYm4E7NfG4a66xA2wu2RZMpKPut+zIScKtk3KMxLKLetchtevN7AXeRIkVCwbaol0/3p4Yy8vrg04dNs2bNXIfDbbfd5iatUJY9miFDhrjy+vAMt16LkUvz2qH8cWn+mZH9qUddf+TvXZzXDiTknMlakDq0b/DRxsFG+wZfTm3jlcPbumtrlZFrImFNelazZs0k++h+JXKUtVbiyaP5hTTDuLapulQ0bFIVph79X8fTPioBnzRpkhu77WW4VbmqydU6dOjgSssjKYEmGjOuoZmeyZMnu+PouCoXf/zxx911t0rdvaBJ560klSZN0/W05oAKP38v8NaEcEqWpUTJMx1T58iY72CKz2AbexXFgQi49aZV2cfq1asz9bgq9Y4M5qOVBoQ3gFd+Em2b98ETeb+3T2ongldQrfJx9cB5wb0mo9BSByqxCV+OwaOxKbpF0h+AQzlo5kykndo4J82OirShfYOPNg422jf4clob6xpVcyNpkt5Zs2a5cc/KDHsZbAXZcscdd7gAWwGtVgV64YUX3FJdWg9bx9DM5BqrretVVYDqcSo3V5B70UUXuX1UaaohnwMHDnTZdM2xpCSRqla9IEcZaY0NV2WqhlLquleBuqpDNTxTJeVaZUjl7Fr+S49RMkyBvrLdqijV9bs6EK644gqXCReVtj/66KOuClRzISnIV4Zc9ysRl9oAS/sRcAdb/nS2cVofk60nTdMHgXrT1LMVvj6gRyUs6gHTjIfhsx7+9NNP7j5luqPRmJPwicxUiqIxLFlN5QmRQXVc3P+y1Dlg9TYAAABkYxoeqVm7NYGwqjC9m2YG9yiAVXDcv39/t762hm8qG+hVcGrZWo2x1thoZa81Y7hmMVcQr/09CqRVsamMtrLWClL0OC9YUbCsQN4rz9V2lYTrOl1Bs4JrHUMBf3i2WiXjCtwVrGu7hmIqqPfonNSpoGC9UaNGLkBXckrP7XUqAEdTts5wi4JtzZ6oni+NhdabT+M+9MbXh4aCa/WIdevWzY3L0H3qvdMbO3zJgHB6I6oMW+t668NDEzooQM9q+nDRuejDwSspV9Zb273AGwAAAEiP1CZwtEytbrHoGlur8qREWW0tcatbNFqRJ/J8VN2qTPqREnIKqFOijLduQHaQ7QPuatWq2ffff+9mRVRZijLT6vnSJAoKuFWyrR61fv36uckRlCFWT5bGjcSiWcY14YMmUNBSAurB07reWU0TTejn0VeV2Xg9fPrZ0+q7Ia1dKQ6CRz3C6gHWWCxKnYKH9g0+2jjYaN/go40BpEWeRGqVA0WD+DUOR7OdE3AH+w+9yqgIuIOH9g0+2jjYaN/go42DjfYNvvgMXkt78ZaGZ6iSI0eP4QYAAAAAIKci4D6KtFxCrNuCBQuO5qkAAAAAAHL7GO4g0ZqHsVSsWPGongsAAAAAwF8E3EeR1hYEAAAAAOQOlJQDAAAAAOADAm4AAAAAAHxAwA0AAAAAgA8IuAEAAAAA8AEBNwAAAAAAPiDgBgAAAADABwTcAAAAAAD4gIAbAAAAAAAfEHADAAAAAOADAm4AAAAAAHxAwA0AAAAAgA8IuAEAAAAA8AEBNwAAAAAAPiDgBgAAAADABwTcAAAAAAD4gIAbAAAAAAAfEHADAAAAAOADAm4AAAAAAHxAwA0AAAAAgA8IuAEAAAAA8AEBNwAAAAAAPiDgBgAAAADABwTcAAAAAAD4gIAbAAAAAAAfEHADAAAAAOADAm4AAAAAAHxAwA0AAAAAgA8IuAEAAICAGT16tJ122ml2zDHHWNmyZe3iiy+2NWvWJNvvm2++sXPPPdeKFi1qxYsXt5YtW9p///2XZJ/333/fmjVrZoULF7ZSpUq5Y3mmTZtmefLkiXrbtm1b1HPbsGGD9e7d26pWreqOWb16dbvvvvvs4MGDSfb74Ycf7KyzzrJChQpZpUqVbOzYsUnu//HHH+2yyy6zKlWquOebOHFiBl81IPPlioB7+PDh1rBhw6w+DQAAAOComD9/vvXt29e+/fZbmzt3rsXHx9v5559ve/fuTRJst2vXzm1fuHChLVq0yG655RbLm/f/Q4SZM2fa1Vdfbddee60tX77cvvrqK7vqqqtC93ft2tU2b96c5Na2bVtr1aqVC/SjWb16tSUkJNiTTz7pguYJEybY1KlT7e677w7ts2fPHndelStXtiVLlti4cePcNf1TTz0V2mffvn1WrVo1GzNmjJUvX96HVxHIuHyWA2zZssVGjRrletc2bdrk3rwKoG+//XZr3bq1BcmuXbvsnnvusbfeest27NjhPmTUW9e+ffs0HafZ6Hl2KF9R384TWadgXKKNbWpWb/gcO3A4D00RMLRv8NHGwUb7Bl9OaOMNYzrYRx99lGSbMtG6hlbwqiy29O/f32699Va76667QvuddNJJof8fOnTIbrvtNhfsKiPtOfnkk0P/V4ZaN8/27dvt008/tWeffTbm+SnI182joFnZ9ylTptj48ePdtpdfftllvJ977jkrUKCA1a1b15YtW2aPPPKI3XDDDW4fZfB1k/CfAchOsn2GWyUnjRs3dm9cvdlXrFjhPkDOOecc12sXJPpQadOmjfuZ33zzTffB8/TTT1vFihWz+tQAAACQg+3evdt9LV26tPuqcu/vvvvOBeFnnnmmlStXzmWlv/zyy9Bjvv/+e5fsUsa7UaNGVqFCBbvgggts5cqVMZ/nxRdftCJFitjll1+e5vPzzs3LvqtjQMG2R5lzXR/v3LkzTccGslK2D7hvvvlmNyZDZS4ao1GrVi3XwzVgwABXIiO///67derUyYoVK+bGnnTp0sW2bt0a85hnn322y46H01iUnj17hr7XWJCRI0dajx493HGVaZ49e7brtfOeq0GDBrZ48eIkPYclS5a0OXPmWJ06ddw+6r1TaU1qqAdPWe133nnHmjdv7s5BH3ynnHJKOl45AAAAwFz5tq59dX1Zr14995KsW7fOfVWZ9vXXX+8SWqeeeqqrHv3ll1+S7TN06FB777333BhuXUvrmjUaZbZVch6e9T6StWvX2qRJk6xPnz5JKlzVCRDO+173ATlFti4p1xtZb36Vk2sih0gKbvUB4gXAGqui0hdlvjWe5PPPP8/Q82s8yYMPPmj33nuv+7/Gr6gHsFevXi7bPnjwYBeQa+yJOgW8sSQqhZk+fbrrDezevbsNGjTIlcUciQL6M844w53/rFmz7LjjjnMfWHqeuLi4qI85cOCAu4WPd5GCeRMtLi4xQz8/sie1bfhXBAvtG3y0cbDRvsGXE9pY47XDaVy2stKfffZZ6D5vgrLrrrvOXa+KJiX75JNPXIWlrr+9fVSufdFFF7n/awy1Jjt79dVXXaAeTsmwVatW2fPPP5/sHGJRBl0JKiXWlPzyHpeYmOiu88OP4/1fX6Md//Dhw6l+3ljCnwPBFJ/BNk7r47J1wK3eLr3ZateuHXOfefPmuTLz9evXu9kLvVIWZcE18YM3riM9NG7a62kbNmyYG1ei43Xu3NltUyCsAFnZdG+iBjWAJn3QbIveB9yIESNS9XzqRVTpfLdu3eyDDz5wP78y/DqmZm6MNQPl/fffn2z70EYJVqTI4XT/7Mj+HmiSkNWnAB/RvsFHGwcb7Rt82bmNdR3pUYCs0nElkTTrt27iVYMqqA7fv0SJEm5/bVMVqTfHUPg+ynIreI8c9qgstYJxZaDD908puabMuSpYO3bsmOQxSqLpXMO36Zrf+6pr/3BKev3000+pet7U0ERzCLa56Wxj/a4FJuBWsH0k6kVToO0F295EDsp+676MBNwqGY8sYalfv36ybRoD4wXcGrPiBduisS6xlkSIpF48jaPRB6My2hq7rl4/ZdNjBdxDhgxx5fXhGW69FiOX5rVD+aNnxZGzqUddf+TvXZzXDiRkz8lakH60b/DRxsFG+wZfTmjjlcPbuutolZFrorEvvvjCatasmWQf3a+kjUq/wyfn1TWnxkprW4sWLdwQyzJlyoT2USJI4621lFj44/7991+XKdf+qZnsV9e4mrtIz/HCCy8kq+bcuHGjS3hpn/z587ttX3/9tQvONXw0kq7BFQOkdaLhSPr5FIiFPy+CJT6DbexVFAci4NYHg0q1tXRAZlKpd2QwH600ILwBvJLxaNsUKEd7jLdPajoOvOBcjw//wNFYcPUSqvcxfNIIT8GCBd0tkv4AHMqmM2cic6iNs+vsqMg42jf4aONgo32DLzu3sa4nVSU5Y8YMN0xRk5H9/fffoQy2N776jjvucAG2xm5rBSAFvpqUTEuB6RgKtG+88UZXram5hTSnkRJBcsUVVyS57tUKO8pKX3PNNcmuhzUXk4ZhqjJVWXEv2NbxNOu4MugeL4mloZwK3vX8qipVSfzjjz/uhnl6x9f1sbLa3v91zayhnhpqWqNGjQy/hgTcwZY/nW2c1sdk64BbHw7qYZs8ebJbsiByHLfenApI1QOmm5fl1htP94UvWRBOY6PDJzLTeA+9iTXzeVbSRBb6YFQA761/+PPPP7tAPFqwDQAAAESjoZCiCc7CaXy1N1GwMuD79+93y4OpvFsT9SrzF16tqQA7X758LgD+77//rFmzZm4IpMrKIydLu/TSS12VabQSXAXyXoJLz6Ghk7qdcMIJSfb1ElXqGPj444/d3Eaq+jz22GNdxttbEkz+/PNPN3u6R/Mo6aZJhzM6lxOQWbJ1wC0KthWINm3a1PWuqcxbvWd6o+qDRMG1yrw17lnrVes+9ejpjdakSZOox1QJjMqwta63PlAie9ayyk033eR67rTeYb9+/dwMkRpvo84GAAAAILVSW2GpCdFSWsNa2TwvkE2Jyr1jUdAffj4K+MNXB4pF1/0LFiyIeb+y7qn9OYGsku0D7mrVqrk1ADVT4sCBA11mWhlq9XQp4FbJtkplFKBqrT5lhjXToSZtiEWzjC9fvtyVtqjHTr16WZ3dFmXotaSYzkcfMCq5UfCtMpq0+m5Ia1cGhOBR77AmBNH4LEqdgof2DT7aONho3+CjjQGkRZ5EuoUCRYP4VYLz119/EXAH/A+9JgUh4A4e2jf4aONgo32DjzYONto3+OIzeC3txVuaPLB48eJH3P9/A4UBAAAAAECmIuA+ijRjYqxbSuNTAAAAAAA5T7Yfwx0kWgcxFo3XBgAAAAAEBwH3UZTR9QABAAAAADkHJeUAAAAAAPiAgBsAAAAAAB8QcAMAAAAA4AMCbgAAAAAAfEDADQAAAACADwi4AQAAAADwAQE3AAAAAAA+IOAGAAAAAMAHBNwAAAAAAPiAgBsAAAAAAB8QcAMAAAAA4AMCbgAAAAAAfEDADQAAAACADwi4AQAAAADwAQE3AAAAAAA+IOAGAAAAAMAHBNwAAAAAAPiAgBsAAAAAAB8QcAMAAAAA4AMCbgAAAAAAfEDADQAAAACADwi4AQAAAADwAQE3AAAAAAA+IOAGAAAAAMAHBNwAAAAAAPiAgBsAAAAAAB8QcAMAAAAA4AMCbgAAACDM6NGj7bTTTrNjjjnGypYtaxdffLGtWbMm6muUmJhoF1xwgeXJk8feeeedZPdPmzbNGjRoYIUKFXLH6tu3b+i+/fv3W8+ePa1+/fqWL18+9zyp9f7771uzZs2scOHCVqpUqSSP1XPqfKLdtm3bFtpv8uTJVqdOHXeMk046yV588UV+D4BMls9yuOHDh7sPt2XLlmX1qQAAACAA5s+f7wJjBd2HDh2yu+++284//3z76aefrECBAkn2nThxogtko3nkkUfs4YcftnHjxrngeO/evbZhw4bQ/YcPH3bB7q233mozZ85M9flp3+uvv94efPBBO/fcc905rly5MnR/165drV27dkkeo8BeAb6CfpkyZYoNGTLEnn76afdzLly40B1TwXvHjh1TfS4AsnnAvWXLFhs1apTrpdu0aZP7EGjYsKHdfvvt1rp1awuKH3/80YYNG2ZLliyx3377zSZMmOB+xnD64NPN+yCuW7eue4x6TdOq2eh5dihf0Uw7f2QfBeMSbWxTs3rD59iBw9H/wCPnon2DjzYONto359swpoN99NFHSbYpY6xrVF3HnXHGGaHtSvgooF68eLFVqFAhyWN27txpQ4cOtXfffTfJNa2y3Z6iRYu6az/56quvbNeuXUc8PwXXt912mwvie/fuHdp+8sknh/6vIF43z/bt2+3TTz+1Z599NrRt+vTp1qdPHxecS7Vq1WzRokX20EMPEXADQSkpV2DZuHFj9wGgD40VK1a4D7hzzjknSblNEOzbt899kI0ZM8bKly8fdZ8TTjjB3a8Pc31wq8eyU6dOLlgHAABA1ti9e7f7Wrp06STXdldddZUry452bTd37lxLSEhwCSWVbes6r0uXLrZx48YMncv333/vjpk3b15r1KiRC/SVnAnPcEdSqXiRIkXs8ssvD207cOCAK3MPpyBdme74+PgMnSOAbBJw33zzza4ER2/syy67zGrVquWyugMGDLBvv/3W7fP777+7oLNYsWJWvHhx90G1devWmMc8++yzk2WONaZFZTSeKlWq2MiRI61Hjx7uuJUrV7bZs2e73j/vudT7qKA3vGezZMmSNmfOHPehqX1UqrN58+ZU/awq1VGnwhVXXGEFCxaMuo/Kd9q3b281a9Z0r4Uy/3oe77UAAADA0aWgWdeWzZs3t3r16oW2Dxo0yM4880x37RjNunXr3GNV9q2y8zfffNN27Nhhbdq0sYMHD6b7fHRcb1ilMujvvfeeKwPXNbCOH40y2+ocCM96t23b1p555hmX6NE4dF336nsF23/99Ve6zw9ANikp1weCstkKKlVOE0nBrT6kvABYY2lUQqPMt0pfPv/88ww9v0q69QF47733uv9fffXV7kOzV69eLjAePHiwC8iVXfbG5agnc/z48a4ER72K3bt3dx+2L7/8smU2jel544033Fif8NKlSOqd1M2zZ88e97Vg3kSLi0vM9PNC1lPbhn9FsNC+wUcbBxvtm/NFZndvueUWlz3+7LPP3H26KVmk71WCHb6/rlW97719NY5bVYteprlSpUou+60x4eF03avbkbLLXrB+11132UUXXeT+/9RTT1nVqlXt1VdfdeOwwylxs2rVKnv++eeTHFuP//PPP+300093AXe5cuXcta1K5HUdmluz3OHth2CKz2Abp/VxWRZwr1271r25a9euHXOfefPmuTLz9evXuw8n74NKWXB9wClrnF7KJGvcimictMbP6HidO3d22xRwK9BVNt0rE9KLO3XqVKtevXroA3jEiBGWmfTz6nk1qYU6Gt5+++0kY3KizaJ5//33J9s+tFGCFSlyOFPPDdnLA00SsvoU4CPaN/ho42CjfXOuDz74IPR/BbLfffedS9L88MMP7ib6qkzzsccem+SxSgqpElIJJVVOiqohw4+pmc/1vYLzcH/88YdLtITvG42qP0XjvcP3VZZbnQAVK1ZMsv+kSZNcMK55kyKPfckll7gKSx1Lj//4449dFlzX2Uou5WbqFEGwzU1nGysJmyMCbgXbR6LeOAXaXrAtCj6V/dZ9GQm4wyesUI+eaEmGyG1aOsELuDX2xQu2RWNmwpdWyAxakkETcGiskEqPrrnmGpfdjxV0a3ZJleCHZ7j1eo1cmtcO5Y/L1HND9sme6ELu3sV57UACk6YFDe0bfLRxsNG+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wAcE3AAAAAAA+ICAGwAAAAAAHxBwAwAAAADgAwJuAAAAAAB8QMANAAAAAIAPCLgBAAAAACDgBgAAAAAgZyDDDQAAAACADwi4AQAAAADwAQE3AAAAAAA+IOAGAAAAAMAHBNwAAAAAAPiAgBsAAAAAAB8QcAMAAAAA4AMCbgAAAAAAfEDADQAAAACADwi4AQAAAADwAQE3AAAAAAA+IOAGAAAAAMAHBNwAAAAAAPiAgBsAAAAAAB8QcAMAAAAA4AMCbgAAAAAAfEDADQAAAACADwi4AQAAAADwAQE3AAAAAAA+yBUB9/Dhw61hw4ZZfRoAgGziiy++sI4dO9rxxx9vefLksXfeeSfZ343atWtb0aJFrVSpUnbeeefZd999l+w477//vjVr1swKFy7s9rv44ouT3P/7779bhw4drEiRIla2bFm744477NChQymeW5UqVdw5hd/GjBmT5Nwi79dN5+qJj4+3ESNGWPXq1a1QoUJ2yimn2EcffZSBVwwAAKRHPssBtmzZYqNGjXIXNps2bXIXLQqgb7/9dmvdurUF0auvvmpXXnmlderUKdmFYGo0Gz3PDuX7/4svBEfBuEQb29Ss3vA5duBwnqw+HWQy2tdfG8Z0cF/37t3rgtBevXrZpZdemmy/WrVq2eOPP27VqlWz//77zyZMmGDnn3++rV271o477ji3z8yZM+3666+3Bx980M4991wXSK9cuTJ0jMOHD7tgu3z58vb111/b5s2brUePHpY3b14788wzUzxPBcs6tueYY44J/X/QoEF24403JtlffwtPO+200PdDhw61l156yZ5++mnXcTBnzhy75JJL3Hk0atQoXa8dAAAIYMC9YcMGa968uZUsWdLGjRtn9evXdz33unjo27evrV692oJGP7MuqM4666ysPhUACKQLLrjA3WK56qqrknz/yCOP2LPPPms//PCDC24VXN92223u71Lv3r1D+5188smh/3/88cf2008/2SeffGLlypVzHcUPPPCADR48OElwHI0CbAXq0RQrVszdPMuXL3fPM3Xq1NC26dOn2z333GPt27d33990003uPB5++GEXiAMAgKMj25eU33zzza5UbuHChXbZZZe5rEPdunVtwIAB9u2334ZK9pQJ1gVI8eLFrUuXLrZ169aYxzz77LNddjycygB79uyZpKRv5MiRLhuh41auXNlm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TZamGwAAAAAAyEBJudbZfuCBB6xixYpWrFgxW7dundt+77332rPPPpueQwIAAAAAECjpCrhHjRpl06ZNs7Fjx1qBAgVC2+vVq+fW5AYAAAAAILdLV8CtNbifeuopt952XFxcaPspp5zixnMDAAAAAJDbpSvg3rRpk5sgLVJCQoLFx8dnxnkBAAAAAJD7Au6TTz7ZFixYkGz7m2++aY0aNcqM8wIAAAAAIPfNUj5s2DC75pprXKZbWe233nrL1qxZ40rN33vvvcw/SwAAAAAAgpzh1mzkiYmJ1qlTJ3v33Xftk08+saJFi7oAfNWqVW5bmzZt/DtbAAAAAACCmOGuWbOmbd682cqWLWtnnXWWlS5d2lasWGHlypXz7wwBAAAAAAh6hlvZ7XAffvih7d27N7PPCQAAAACA3DlpWqwAHAAAAAAApCPgzpMnj7tFbgMAAAAAABkYw62Mds+ePa1gwYLu+/3799uNN97oJk4Lp1nLAQAAAADIzdIUcGspsHDdu3fP7PMBAAAAACD3BdzPP/+8f2cCAAAAAECAZGjSNAAAAAAAEB0BNwAAAAAAPiDgBgAAAADABwTcAAAAAAD4gIAbAAAAAAAfEHADAAAAAOADAm4AAAAAAHyQ4wPu4cOHW8OGDbP6NABEsWnTJuvevbuVKVPGChcubPXr17fFixcn2WfVqlV20UUXWYkSJaxo0aJ22mmn2e+//x66/+yzz7Y8efIkud14441HfL2PdNw+ffpY9erV3Xkdd9xx1qlTJ1u9enWSY8ybN8/OPPNMO+aYY6x8+fI2ePBgO3ToEG0NAACAVMlnWWzLli02atQoe//9993FedmyZV0Affvtt1vr1q0tKH788UcbNmyYLVmyxH777TebMGGC+xkjTZ482caNG+del1NOOcUmTZpkTZs2TfPzNRs9zw7lK5pJZ4/spGBcoo1talZv+Bw7cDiPZUcbxnSwnTt3WvPmze2cc86xDz/80AW1v/zyi5UqVSq036+//motWrSw3r172/3332/Fixd375VChQolOd71119vI0aMCH1fpEiRFJ8/Ncdt3LixdevWzU488UTbsWOH67w7//zzbf369RYXF2fLly+39u3b2z333GMvvvii+3xSoH/48GEbP358pr5eAAAACKYsDbg3bNjgLshLlizpgkxlv+Lj423OnDnWt2/fZNmmnGzfvn1WrVo169y5s/Xv3z/qPq+99poNGDDApk6das2aNbOJEyda27Ztbc2aNa4jAshJHnroIatUqZI9//zzoW1Vq1ZNso+CWQW1Y8eODW1T1jmSAmxlmFMrNce94YYbQv+vUqWKjRw50nVy6XNJ++r92KBBA9dRJjVq1HDH69Kli913330u6w0AAABk25Lym2++2ZWHLly40C677DKrVauW1a1b1wWd3377rdtHJaAq9SxWrJjLUulid+vWrTGPqfLTyMzxxRdfbD179kx2cd2jRw933MqVK9vs2bNt+/btoefShXZ46eu0adNcx4A6A+rUqeP2adeunW3evDlVP6vKWdWpcMUVV1jBggWj7vPII4+4TN61115rJ598sgu8FWg899xzqXoOIDvRe6pJkyauk0kdRo0aNbKnn346dH9CQoKrbNH7Xh1L2kcdTe+8806yY7388st27LHHWr169WzIkCGuAyuWtBzXs3fvXtcxoA4BdRLIgQMHkmXaVX6+f/9+V6kCAAAAZNuAWyWcH330kctka3xlJAW3unBWAKx958+fb3PnzrV169ZZ165dM/z8KulWdn3p0qXWoUMHu/rqq10ArvGm33//vctw6fvExMTQY3SRr1LS6dOn2xdffOE6AwYNGmSZ4eDBg+4i/rzzzgtty5s3r/v+m2++yZTnAI4mvVenTJliNWvWdB1VN910k9166632wgsvuPu3bdtm//77r40ZM8Z1Xn388cd2ySWX2KWXXure756rrrrKXnrpJfvss89csK33n96nsaT2uPLEE0+4zjPdVPauz5gCBQq4+xSsf/311/bKK6+4MnKVlHtl7antaAMAAEDulmUl5WvXrnXBbO3atWPuowmLVqxY4cZUelknjaVUFnzRokUua5xeKjfVpEmiklEFBjqesnGiyZHOOOMMl033SllV7q6ss1eaessttyQZV5oRf/31l7uoL1euXJLt+j6l0npl4XTz7Nmzx30tmDfR4uL+v7MAwaG2Df+aHem9og4zjZPWGGpRdvqHH35w7zUF0d7vbceOHd17SfTe/vLLL10grMnKRBUfHn1eaCy4gmG9L6KVn6f2uKKKGVXFaM4EVZjo/a+gXJltjT1X0K5x2+qQU2XK3XffbQsWLHA/m35Gv1678K8IHto42Gjf4KONg432Db74DF5rpfVxWRZwh2eOU5plWIG2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5wikx0MPPeQyx88//3xoW9WqVZPtpw61fv36ufd3hw4dkty3atUq++ijj2zRokXWpEkTt23SpEnWvn17Gz9+fNQAXcID4ipVqrjAWu8hfbYo862g/6abbgrtU7lyZbv55pvd542nUaNG7hZ+nLfeessWLFhAwA0AAICcW1KuC1+Vli5cuNAuu+wyq1WrltWtW9cGDBjgsmDy+++/uwxVsWLFXKlply5dbOvWrTGPefbZZyfLHCtL3LNnz2QX5j169HDH1UX47Nmzbfv27aHnUrYrvCR22rRprmNAwUKdOnXcPipVVUYuNU477TR3kX/FFVe40tZoLrjgAndel1xySaqOCWQHeu8oSFZnkipUFLw+/fTTSfZJSEiwq6++2u644w73Ho/0zTffuPeXF2zLeeed5zLU3333XarOQx1WCvoV7KsDIJo///zTBdOtWrWKeZylS5fa119/neI+AAAAQLYOuFXSqYyWMtkq3Yyki29dpCsA1r7z5893pabr1q2zrl27Zvj5VdKt7LourpVtUzCgAFzjUL///nuXHdP3iYmJSbLUyrZNnz7dlX+rM2DQoEEZPhcgJ9N7csqUKVazZk3XIaWM8q233movvPBCkix4vnz53PZYQ0sUrIfT/qVLl3b3peSJJ55wHWC6qaRdnxMFChRIss+VV15pRYoUsYoVK7qOu2eeeSbZcU444QTXGaagX59L1113XRpfCQAAACCblJRrLKWCWU1QFMu8efNsxYoVbjyml7F68cUXXYZMpafKGqeXSlU1TlM0tloBg46nLJ0MHjzYzjjjDJdNL1++vNumcvepU6e6YFw07nPEiBGWlQ4cOOBuHm8yqIJ5Ey0u7v87CxAcatvwr1lJ7wl1jGks9f333++21atXz3744Qf3nrrqqqtcB9ajjz7qMtWHDh0KPfbw4cPu8d7/9XngfR8ufL9oVPWiyhYF5o888oh7D6uDrlChQqF9xo4da3fffbcbWz506FBXBaOS9XCffvqpm6RNFTf33HOPq4RRRcrR5v2sKf3MyNlo42CjfYOPNg422jf44jN4rZXWx2VZwB2eOY5F4zoVaIeXh5588sku+637MhJwq2TcU65cOfdVY8gjt23bti0UcCtD5gXbUqFCBXd/Vho9enQo0Ak3tFGCFSlyOEvOCUfHA00Ssvyl/uCDD9z7Udll/d+jwFrBrbap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1apldevWdRmyb7/91u3z+++/uwv2YsWKWfHixV02b+vWrTGPefbZZycpwRUFtsrweapUqeKCAgU1Om7lypVdxnD79u2h51KAoqyhZ9q0aa5jQJ0BderUcfsoANm8eXOqftZHH33U7X/HHXe4xz/wwAOuHFhZSCDcU0895SoflKmOdOaZZ9prr71mO3bscBnnV1991fbv3+9+7+XAgQNWoECBUMArKgGXL7/8MsUX+vPPP3cVJieddJLddNNN9vfff6e4vzLYpUuXDn3fuHFj97zKkivw1v3Tp093PwfBNgAAAIImWwfcChg++ugjl8nWWNRICm4VUCgA1r7z58+3uXPn2rp161y5bEYpK6js+tKlS61Dhw5uXKwC8O7du7uss8ao6vvExMTQY/bt2+eyeQoivvjiC9cZoAxeanzzzTfJAqi2bdu67YBHwfSvv/6aLLPtef311122WGOzlZHu06ePvf3226HM9bnnnuuGaahiROOrd+7caXfddZe7L6XOIXUGvfjiizZv3jw31EHvtwsuuMAFztEoWz5p0iT3/B6N7/7444/t7rvvduem9/Aff/zhzhkAAAAImmxdUq4LdgWztWvXjrmPLv5XrFjhxoZWqlTJbVNQoCz4okWL7LTTTkv38yuD6AULw4YNc6WxOl7nzp3dtsGDB9sZZ5zhsulema0CHZXnKhiXW265xUaMGJGq51MQVK5cuSTb9L22x6JspW4ejceVgnkTLS7u/zsCkPPpd2vjxo2uuuOee+6xuLg4t03vEXU86f+i+xREq7NKQbcqM1T18emnn7ohGaoSefbZZ+3OO++0IUOGuOPo91S/azqWd5xIqjDx6D2pKgx9/eSTT1wQH05zLShA12NUOeIdU7/L1113neu0UqeYJmq7//773X4ffvihq2bJ7bzXKlY7IOejjYON9g0+2jjYaN/gi8/gtVZaH5etA+7wzHEsq1atcoG2F2zLySef7DJnui8jAXf4ZFReIKyAJXLbtm3bQgF3kSJFQsG2VKhQwd3vF433VsASaWijBCtSJHrmETnTBx984IZRaFiDgm7dRMH2ggUL3Jhs3Z544gl77LHHXBm5Al+VcWtIhLLKKgOXEiVKuMnNNLmaMs0KdCdOnOi+1/OkloZwzJo1yz2XR9UmGjeuwL5jx45JjqeJ0qRly5ahbLqqRBSE6/lVqo7/UbUO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" + "image/png": "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8847Q50FAwcOtOeee87OOeccW7x4sdumRIkS1r59e7fNoUOHrFWrVu6x3njjDXcMVapUsRNPPNH8litJr2AWp16PkSNH2owZM1zD6YVSL8c999xjLVu2DEzA3bx5c5s3b16K69u2beuee1rs2bPHihUrZlX6vWkJeQr5cJTIbPnikmxMw8N23+I4O3g4V2YfDjIY7Rt8tHGw0b7BRxsHW05s342j20W9vmTJki6brAA60ttvv21du3a1ffv2WZ48/5fDVfD75ptv2pAhQ1yc9vfff1vx4sVDGe4LL7ww2XVHct1111l8fLx7PI+C7zFjxthvv/3mMuSNGze2Jk2aJMt89+vXzxYtWmRffvml+33y5Mnu9rVr17rfldlWjJU3b147Gl7MpSx/eOdBtsxwb9y40b2AahS9SLVr13Yv+qxZs1xJgPeiBcF7773nel/CyzHOOuss69ixY6YeFwAAAICc4fDhwy7AVTCt0vJovEAzPNhevXq1DRs2zAW6v/zyS8z9161b1w4ePGi1atVyiVHFerFoO5WSh1N2+/fff3eZ9sqVK7tt8ufPn2IbZboVNyqonj59unsuih+nTZvmtv/+++/tgQcesLi4OMvRY7h79uzpei70gl111VV2+umnW82aNa1v3772zTffuG3Uu6GSh8KFC7uG79Spk23bti3VTLKy4+Euv/xy6969e+h3Nd6IESOsW7dubr8aL6CG2rFjR+ixVCqxdOnS0H2mTJniOgbUGaAxBNqmTZs2tmXLljQ9V/UilStXLnSZPXu2e4MRcAMAAADw08qVK138ki9fPlcy/v7777sS8kh//vmnDR8+3G677bbQdQp6r732Wpcg1RjpaMqXL+8yze+++667VKxY0cVl3333Xcxjat26tUtKzpkzxxITE+3HH3+0xx9/3N3mxVja5vnnn7dvv/3Wlb8rPtPvCrZ1rKIOAJW/qzNBMZ3ixfHjx7t4z29ZOsOtAfqffPKJKycvVChlebSCW73wXgCscuyEhATXc9G5c2dXtnAsxo0bZ4888ogNHjzY/Xz99de7koWbbrrJvZkGDBjgAvIffvjBdQrI/v373fiGqVOnWu7cuV2pRf/+/e21115L9+O/8MILds0110R97uFvbl3CyxskX+4ki4vL8qMFcBTUtuH/I1ho3+CjjYON9g0+2jjYcmL7KjCV0047zZYs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DQAAAACADwi4AQAAAADwAQE3AAAAAAA+IOAGAAAAAMAHBNwAAAAAAPiAgBsAAAAAAB8QcAMAAAAA4AMCbgAAAAAAfEDADQAAAACADwi4AQAAAADwAQE3AAAAAAA+IOAGAAAAAMAHBNwAAAAAAPiAgBsAAAAAAB8QcAMAAAAA4AMCbgAAAAAAfEDADQCAD+bPn2/t27e3k046yXLlymUffPBBzG1vv/12t8348eNT3DZjxgxr1KiRFShQwEqUKGGXX3556La//vrL2rRp4x4jX758VrFiRbvzzjttz549Rzy+1PYrS5YssZYtW1rx4sXd7a1bt7YVK1aEbj9w4IB1797dateubXny5ElxfwAAkEMC7qFDh1rdunUz+zAAADnIvn377KyzzrKJEyemut37779v33zzjQuaI7377rt2/fXX24033uiC3a+++squu+660O25c+e2Dh062PTp0+3HH3+0KVOm2GeffeYC+NQcab///POPC+RPOeUUW7RokX355ZdWpEgRF3THx8e7bQ4fPuyC9bvuussuuuiio3iFAAAIvjyWDWzdutVGjhzpeuM3b95sZcqUcQH0Pffc43rfg0InMaNGjbKXX37ZPc8zzjjDHn30UXfSk16NRs2xhDyFfDlOZK58cUk2pqFZraGz7ODhXDRHwNC+2d/G0e3c/5dccom7pEbf9b1797ZZs2ZZu3b/u58nISHB7r77bhs7dqzdfPPNoevPPPPM0M/KPN9xxx2h3ytVqmQ9e/Z094klLftdu3at7dy504YNG+ay5vLQQw9ZnTp17Ndff7WqVataoUKFbNKkSe42Bey7du1K0+sDAEBOkuUz3Bs3brT69evb559/7k4OVq5caZ988oldeOGF1qtXLwuSQYMG2X/+8x+bMGGCrV692mUorrjiClu2bFlmHxoAIIMlJia6LPO9995rNWvWTHH7d9995wJyZbHr1atn5cuXdwH8qlWrYu7zjz/+sPfee8+aNWsWc5u07FcdvqVKlbIXXnjBDh06ZP/++6/7uUaNGla5cuUMePYAAOQMWT7gVk+9xrUtXrzYrrrqKjv99NPdiUnfvn1dCZ789ttvrqSucOHCVrRoUevUqZNt27Yt5j6bN2/usuPhNPZMY9E8OqEYMWKEdevWze1XWQOV7O3YsSP0WOrpX7p0aeg+KuXTWDdlKnRSom2Und6y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uu6dd95x2+szpu+RV1991QXdX3/9td12220WFxdnd955Z8zHV7C9ZcsWmz17tvtOu/HGG939Xn/99dBQmg4dOljfvn3ttddec0F+nz597Morr7TvvvvObTNp0iQbOHCgPffcc3bOOefY4sWL7dZbb7USJUpY+/btfX4FAQAAEIiA+++//05x3U8//WR33HGH3XvvvWnejzJDTZo0cdmksWPHWu3atd2JrrJIymYp8AwKdUicdtppLmjQSXo08+bNc89bJ+oJCQn2wAMP2MUXX2yrV69OMRM8EFTKHIcbPXq0ValSxZo1a+Yy3e+++27oNl2vDruuXbu6z0yePHnspptuSnZ/fe4WLlzoOrNiBdxr1qyxTz75xAX7DRo0cNdNmDDB2rZt64L7k046yQXy6ggYMWKE5c79v+Kg/v37uyBc31t58+a1qVOnWo8ePaxz586hx9Y+1XFGwA0AAJDzHFVJeTTVqlVzJ8aR2e8jLS+mE2hlgVSaefrpp1vNmjVdBumbb75x2/z222/uhLZw4cKu1LNTp062bdu2mPts3rx5iszx5Zdfbt27d09WsqqTZmXitV+NSZ8+fbrt2LEj9Fha2mzp0qWh+0yZMsV1DKgzQOWi2qZNmzYuI5YWCqLVqaAZ3vPlyxd1G53w6zj1Gpx11lnuMfX8daIP5ESHDh1ymWoF0fquiEaZZn03KNiORduULFky5u0KyPX59oJtueiii1xgvWjRIve7lkDU7y+99JILvLVPBdjaTsG2HDx40PLnz59s36pW0XecgnIAAADkLBkWcItOeFXamRYaL6kAUxndaNlbnfwmJia6AFjbKvurUs9ffvkllD06FirpVnZ92bJl1q5dO7v++utdAK5MmcpDlTnT71rqLDxLrWyXTrLnz5/vgmFluPzijUtNLVAAguyDDz6wXbt2JeswC/fnn3/a8OHDXel3LCopf/PNN1PdRkNbVIYe+X2mz55uk1NPPdU+/fRTV3miTjN9R/3+++/21ltvhe7TunVre/75510nmb471Gmn3xVs61gBAACQsxxVSbmyweF0YqlM79NPP+2C2LRYv369u1/16tVjbjNnzhxbuXKlGzupsZiiCYiUAVaZprLGR0uloir9FI2t1thL7U8l3zJgwAA777zzXDa9XLly7jqdNE+ePNkF46Ly1GHDhpkf1NmgTL1ez1q1asXc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" }, "metadata": {}, "output_type": "display_data", @@ -1209,28 +1207,28 @@ "text": [ "\n", "[特征重要性排名 - Gain]\n", - "return_10 3244.585386\n", - "ma_ratio 2871.645070\n", - "return_20 2686.807540\n", - "vol_ratio 2667.200664\n", - "high_low_ratio 2461.679219\n", - "return_diff 1491.578852\n", - "volatility_5 1360.579366\n", - "market_cap_rank 697.769018\n", - "vol_ma5 665.639110\n", - "vol_ma20 640.332628\n", - "n_income 536.010082\n", - "ma5 489.527820\n", - "ma20 481.715007\n", - "ma10 303.121463\n", - "volatility_20 224.481188\n", + "return_10 3245.995642\n", + "ma_ratio 2818.976538\n", + "vol_ratio 2701.151667\n", + "return_20 2681.762756\n", + "high_low_ratio 2469.737874\n", + "return_diff 1463.681328\n", + "volatility_5 1357.026476\n", + "market_cap_rank 722.088673\n", + "vol_ma5 653.087969\n", + "vol_ma20 631.252641\n", + "ma20 548.830554\n", + "n_income 495.525785\n", + "ma5 469.811824\n", + "ma10 305.156890\n", + "volatility_20 203.306830\n", "dtype: float64\n", "\n", "所有特征都有一定重要性\n" ] } ], - "execution_count": 16 + "execution_count": 21 } ], "metadata": {