From 0a161295488df7ff8449508e02347596cd3699ea Mon Sep 17 00:00:00 2001 From: liaozhaorun <1300336796@qq.com> Date: Sun, 22 Feb 2026 14:41:32 +0800 Subject: [PATCH] =?UTF-8?q?feat(factors):=20=E6=B7=BB=E5=8A=A0=E5=9B=A0?= =?UTF-8?q?=E5=AD=90=E8=AE=A1=E7=AE=97=E6=A1=86=E6=9E=B6=20-=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=9B=A0=E5=AD=90=E5=9F=BA=E7=B1=BB=20(BaseFactor,=20?= =?UTF-8?q?CrossSectionalFactor,=20TimeSeriesFactor)=20-=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=95=B0=E6=8D=AE=E8=A7=84=E6=A0=BC=E5=92=8C=E4=B8=8A?= =?UTF-8?q?=E4=B8=8B=E6=96=87=E7=B1=BB=20(DataSpec,=20FactorContext,=20Fac?= =?UTF-8?q?torData)=20-=20=E6=96=B0=E5=A2=9E=E6=95=B0=E6=8D=AE=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E5=99=A8=20(DataLoader)=20=E5=92=8C=E6=89=A7=E8=A1=8C?= =?UTF-8?q?=E5=BC=95=E6=93=8E=20(FactorEngine)=20-=20=E6=96=B0=E5=A2=9E?= =?UTF-8?q?=E7=BB=84=E5=90=88=E5=9B=A0=E5=AD=90=E6=94=AF=E6=8C=81=20(Compo?= =?UTF-8?q?siteFactor,=20ScalarFactor)=20-=20=E6=B7=BB=E5=8A=A0=E5=9B=A0?= =?UTF-8?q?=E5=AD=90=E6=A8=A1=E5=9D=97=E5=AE=8C=E6=95=B4=E6=B5=8B=E8=AF=95?= =?UTF-8?q?=E7=94=A8=E4=BE=8B=20-=20=E6=B7=BB=E5=8A=A0=20Git=20=E6=8F=90?= =?UTF-8?q?=E4=BA=A4=E8=A7=84=E8=8C=83=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .kilocode/rules/project_rules.md | 107 -- .../rules/python-development-guidelines.md | 356 ----- .kilocode/rules/security_rules.md | 285 ---- docs/code_review_factors_20260222.md | 227 +++ docs/factor_framework_design.md | 1303 +++++++++++++++++ docs/factor_implementation_plan.md | 846 +++++++++++ docs/hdf5_to_duckdb_migration.md | 1149 +++++++++++++++ src/factors/__init__.py | 65 + src/factors/base.py | 274 ++++ src/factors/composite.py | 201 +++ src/factors/data_loader.py | 183 +++ src/factors/data_spec.py | 242 +++ src/factors/engine.py | 367 +++++ tests/factors/__init__.py | 2 + tests/factors/factor_test_report.md | 143 ++ tests/factors/test_base.py | 406 +++++ tests/factors/test_composite.py | 417 ++++++ tests/factors/test_data_loader.py | 248 ++++ tests/factors/test_data_spec.py | 328 +++++ tests/factors/test_engine.py | 266 ++++ tests/factors/test_factor_validation.py | 397 +++++ 21 files changed, 7064 insertions(+), 748 deletions(-) delete mode 100644 .kilocode/rules/project_rules.md delete mode 100644 .kilocode/rules/python-development-guidelines.md delete mode 100644 .kilocode/rules/security_rules.md create mode 100644 docs/code_review_factors_20260222.md create mode 100644 docs/factor_framework_design.md create mode 100644 docs/factor_implementation_plan.md create mode 100644 docs/hdf5_to_duckdb_migration.md create mode 100644 src/factors/__init__.py create mode 100644 src/factors/base.py create mode 100644 src/factors/composite.py create mode 100644 src/factors/data_loader.py create mode 100644 src/factors/data_spec.py create mode 100644 src/factors/engine.py create mode 100644 tests/factors/__init__.py create mode 100644 tests/factors/factor_test_report.md create mode 100644 tests/factors/test_base.py create mode 100644 tests/factors/test_composite.py create mode 100644 tests/factors/test_data_loader.py create mode 100644 tests/factors/test_data_spec.py create mode 100644 tests/factors/test_engine.py create mode 100644 tests/factors/test_factor_validation.py diff --git a/.kilocode/rules/project_rules.md b/.kilocode/rules/project_rules.md deleted file mode 100644 index 4887b93..0000000 --- a/.kilocode/rules/project_rules.md +++ /dev/null @@ -1,107 +0,0 @@ -# ProStock 项目规则 - -本项目使用 Kilo Code 规则系统来确保代码质量和一致性。 - -## 项目概述 - -- **项目名称**: ProStock -- **主要语言**: Python -- **框架**: 待定 -- **代码目录**: `src/` -- **配置目录**: `config/` - -## 核心原则 - -1. **代码质量**: 所有代码必须符合 Python PEP 8 编码规范 -2. **类型提示**: 建议为公共函数和类添加类型注解 -3. **文档字符串**: 使用 Google 风格的 docstring -4. **测试覆盖**: 关键业务逻辑应有对应的单元测试 - -## Python 运行规范 - -**⚠️ 本项目强制使用 uv 作为 Python 包管理器和运行工具。禁止直接使用 `python` 或 `pip` 命令。** - -### 禁止的命令 ❌ - -```bash -# 禁止直接使用 python -python -c "..." # 禁止! -python script.py # 禁止! -python -m pytest # 禁止! -python -m pip install # 禁止! - -# 禁止直接使用 pip -pip install -e . # 禁止! -pip install package # 禁止! -pip list # 禁止! -``` - -### 正确的 uv 用法 ✅ - -```bash -# 运行 Python 代码 -uv run python -c "..." # ✅ 正确 -uv run python script.py # ✅ 正确 - -# 安装依赖 -uv pip install -e . # ✅ 正确 -uv pip install package # ✅ 正确 - -# 运行测试 -uv run pytest # ✅ 正确 -uv run pytest tests/test_sync.py # ✅ 正确 -``` - -## 目录结构规范 - -``` -project/ -├── src/ # 源代码主目录 -├── config/ # 配置文件目录(禁止直接读取) -├── docs/ # 文档目录 -├── tests/ # 测试目录 -├── .kilocode/ # Kilo Code 配置 -│ └── rules/ # 规则文件 -├── requirements.txt # 依赖管理 -└── README.md # 项目说明 -``` - -## 文件命名规范 - -- **Python 文件**: 使用小写下划线命名法 (`snake_case.py`) -- **配置文件**: 使用小写下划线命名法 (`config_settings.py`) -- **测试文件**: 使用 `test_` 前缀 (`test_example.py`) -- **常量文件**: 使用 `constants_` 前缀 (`constants_sizes.py`) - -## 代码组织 - -- 每个 Python 模块应尽可能保持简洁,职责单一 -- 避免在 `__init__.py` 中放置过多逻辑 -- 使用相对导入 (`from .module import ...`) 而非绝对导入 -- 配置应集中管理,避免硬编码 - -## 导入顺序规范 - -```python -# 1. 标准库导入 -import os -import sys -from datetime import datetime - -# 2. 第三方库导入 -import pandas as pd -from flask import Flask - -# 3. 本地应用导入 -from src.config.settings import Settings -from src.models.user import User -``` - -## 提交前检查 - -在提交代码前,请确保: -- [ ] 所有代码通过类型检查(如使用 mypy) -- [ ] 代码格式符合规范(使用 black/isort) -- [ ] 没有未使用的导入或变量 -- [ ] 关键功能有对应的测试 -- [ ] 文档已更新(如需要) diff --git a/.kilocode/rules/python-development-guidelines.md b/.kilocode/rules/python-development-guidelines.md deleted file mode 100644 index b7d1a2d..0000000 --- a/.kilocode/rules/python-development-guidelines.md +++ /dev/null @@ -1,356 +0,0 @@ -# Python 开发规范 - -## 1 代码风格规范 - -### 1.1 缩进与空格 -- 使用 **4个空格** 进行缩进(禁止使用Tab) -- 每行代码最大长度限制为 **120字符** -- 二元运算符前后使用空格(链式赋值除外) -- 函数参数周围空格一致 - -```python -# 正确示例 -def calculate_total_price(price: float, tax_rate: float) -> float: - total = price * (1 + tax_rate) - return round(total, 2) - -# 错误示例 -def calculate_total_price(price:float,tax_rate:float)->float: - total=price*(1+tax_rate) - return round(total,2) -``` - -### 1.2 导入规范 -- 导入位于文件顶部,位于模块注释和文档字符串之后 -- 标准库导入放在最前面,其次是第三方库,最后是本地应用模块 -- 使用绝对导入,禁止使用通配符导入(`from module import *`) -- 每组导入之间保留一个空行 - -```python -# 标准库 -import os -import sys -from datetime import datetime - -# 第三方库 -import numpy as np -import pandas as pd -from pydantic import BaseModel - -# 本地模块 -from src.config import settings -from src.utils.logger import get_logger -``` - -### 1.3 命名规范 - -| 类型 | 规范 | 示例 | -|------|------|------| -| 模块 | 全小写,下划线分隔 | `data_processor.py` | -| 包 | 全小写,禁止下划线 | `src/utils` | -| 类 | PascalCase,首字母大写 | `UserAccount`, `DataValidator` | -| 函数 | snake_case,全小写 | `get_user_data()`, `calculate_total()` | -| 变量 | snake_case,全小写 | `user_name`, `total_count` | -| 常量 | UPPER_SNAKE_CASE | `MAX_RETRY_COUNT`, `DEFAULT_TIMEOUT` | -| 私有方法/变量 | 单下划线前缀 | `_internal_method()`, `_private_var` | -| 类型变量 | PascalCase | `UserType`, `T = TypeVar('T')` | - -### 1.4 注释规范 -- 使用英文注释,禁止使用中文注释 -- 复杂逻辑必须添加注释说明意图 -- 注释与代码同步更新,禁止过时注释 - -```python -# 单行注释(与代码同行时,注释前保留2个空格) -def process_data(data: list) -> dict: # Process input data and return statistics - pass - -# 多行文档字符串(Google风格) -def calculate_metrics(values: list[float]) -> dict[str, float]: - """Calculate statistical metrics for a list of values. - - Args: - values: List of numeric values to analyze - - Returns: - Dictionary containing mean, median, and standard deviation - - Raises: - ValueError: If input list is empty - """ - pass -``` - -## 2 架构设计规范 - -### 2.1 模块结构 -``` -src/ -├── core/ # 核心业务逻辑 -├── modules/ # 功能模块 -├── utils/ # 工具函数 -├── config/ # 配置管理 -├── services/ # 服务层 -├── models/ # 数据模型 -├── repositories/ # 数据访问层 -└── schemas/ # Pydantic模型 -``` - -### 2.2 依赖原则 -- **依赖倒置**:高层模块不依赖低层模块,两者都依赖抽象 -- **禁止循环依赖**:模块间引用必须形成有向无环图 -- **单一职责**:每个类/模块只负责一项职责 - -```python -# 错误示例:高内聚低耦合违反 -class UserService: - def __init__(self, db_connection, email_sender, cache_manager): - pass - -# 正确示例:通过抽象接口解耦 -class UserService: - def __init__(self, user_repository: IUserRepository): - self.repository = user_repository -``` - -### 2.3 函数设计 -- **单一职责**:每个函数只做一件事 -- **参数控制**:函数参数不超过5个,超过则使用对象封装 -- **返回值明确**:返回类型必须注解 - -```python -# 错误示例:函数职责过多 -def process_user_registration(name, email, password, send_email, create_session): - if send_email: - send_verification_email(email) - if create_session: - create_user_session(email) - return save_user(name, email, password) - -# 正确示例:单一职责拆分 -class UserRegistrationService: - def register(self, user_data: UserCreateDto) -> User: - user = self._validate_and_create_user(user_data) - self._send_verification_email(user) - self._create_session(user) - return user - - def _validate_and_create_user(self, data: UserCreateDto) -> User: - pass - - def _send_verification_email(self, user: User) -> None: - pass -``` - -## 3 配置管理规范 - -### 3.1 禁止硬编码 -**所有关键配置必须外置,禁止在代码中硬编码** - -| 类型 | 必须外置的配置 | -|------|----------------| -| 数据库连接 | HOST, PORT, USER, PASSWORD, DATABASE | -| API密钥 | SECRET_KEY, API_KEY | -| 外部服务 | ENDPOINT, TIMEOUT, RETRY_COUNT | -| 业务参数 | MAX_RETRIES, CACHE_TTL, RATE_LIMIT | - -### 3.2 配置目录结构 -``` -config/ -├── .env.example # 环境变量模板(不包含敏感信息) -├── .env.local # 本地环境配置(被.gitignore忽略) -├── config.yaml # 通用配置 -├── config.development.yaml # 开发环境配置 -├── config.production.yaml # 生产环境配置 -└── config.test.yaml # 测试环境配置 -``` - -### 3.3 配置加载示例 -```python -# src/config/settings.py -from pydantic_settings import BaseSettings -from functools import lru_cache - - -class Settings(BaseSettings): - """应用配置类,从环境变量加载""" - - # 数据库配置 - database_host: str = "localhost" - database_port: int = 5432 - database_name: str = "prostock" - database_user: str - database_password: str - - # API配置 - api_key: str - secret_key: str - jwt_algorithm: str = "HS256" - access_token_expire_minutes: int = 30 - - # Redis配置 - redis_host: str = "localhost" - redis_port: int = 6379 - - class Config: - env_file = ".env.local" - env_file_encoding = "utf-8" - - -@lru_cache() -def get_settings() -> Settings: - """获取配置单例""" - return Settings() -``` - -### 3.4 .env.example 模板 -```bash -# =========================================== -# ProStock 环境变量配置模板 -# 复制此文件为 .env.local 并填入实际值 -# =========================================== - -# 数据库配置 -DATABASE_HOST=localhost -DATABASE_PORT=5432 -DATABASE_NAME=prostock -DATABASE_USER=your_username -DATABASE_PASSWORD=your_password - -# API密钥配置 -API_KEY=your_api_key -SECRET_KEY=your_secret_key_here - -# Redis配置(可选) -REDIS_HOST=localhost -REDIS_PORT=6379 -``` - -## 4 错误处理规范 - -### 4.1 异常分类 -```python -# src/core/exceptions.py -class BaseCustomException(Exception): - """基础异常类""" - status_code: int = 500 - detail: str = "An unexpected error occurred" - - def __init__(self, detail: str = None): - self.detail = detail or self.detail - super().__init__(self.detail) - - -class ValidationError(BaseCustomException): - """数据验证异常""" - status_code = 422 - detail = "Validation error" - - -class AuthenticationError(BaseCustomException): - """认证异常""" - status_code = 401 - detail = "Authentication required" - - -class AuthorizationError(BaseCustomException): - """授权异常""" - status_code = 403 - detail = "Permission denied" - - -class NotFoundError(BaseCustomException): - """资源不存在""" - status_code = 404 - detail = "Resource not found" -``` - -### 4.2 错误处理原则 -- 向上层传递有意义的信息 -- 记录详细日志(不含敏感信息) -- 区分可恢复和不可恢复错误 - -## 5 测试规范 - -### 5.1 测试要求 -- 所有核心功能必须有单元测试 -- 关键业务逻辑测试覆盖率不低于80% -- 使用 `pytest` 作为测试框架 -- 使用 `pytest-cov` 生成覆盖率报告 - -### 5.2 测试文件结构 -``` -tests/ -├── conftest.py # 共享fixtures -├── unit/ # 单元测试 -│ ├── test_models.py -│ ├── test_services.py -│ └── test_utils.py -├── integration/ # 集成测试 -│ └── test_api.py -└── fixtures/ # 测试数据 -``` - -### 5.3 Mock 使用规范 -- **默认不使用 Mock**:单元测试应直接调用真实 API 或服务 -- **仅在必要时使用 Mock**: - - 测试错误处理场景(如网络超时、服务不可用) - - 测试空结果或边界情况 - - 隔离外部依赖的不确定性 -- **禁止全面 Mock**:不应为避免配置或环境问题而使用 Mock -- **真实环境验证**:确保至少有一个测试套件直接调用真实 API - -```python -# 正确示例:直接调用真实 API -class TestUserService: - def test_get_user(self): - result = get_user('user_id') - assert result.name == "John" - - def test_empty_result_with_mock(self): # 特殊场景使用 mock - with patch('module.api_call', return_value=pd.DataFrame()): - result = get_user('invalid_id') - assert result.empty - -# 错误示例:过度使用 mock -class TestUserService: - def test_get_user(self): - mock_data = {"name": "John"} - with patch('module.api_call', return_value=mock_data): - result = get_user('user_id') - assert result == mock_data -``` - -## 6 Git提交规范 - -### 6.1 提交信息格式 -``` -(): - - - -