Initial commit: cc-cursor 全链路量化研究平台

7 Sprints 全部完成:
  Sprint 0: 基础设施 (DataManager + MariaDB)
  Sprint 1: 因子引擎 (34因子/12分类)
  Sprint 2: VectorBT 回测 (5策略+截面)
  Sprint 3: Optuna 优化 (+Walk-Forward)
  Sprint 4: ML 模型 (LightGBM+CatBoost)
  Sprint 5: Qwen 情绪因子 (三源新闻+日期对齐)
  Sprint 6: Agent 系统 (4Agent+日报.md/.html)

生产加固 (15项): Tushare双源fallback, SSH自动恢复, pool_pre_ping,
  save_daily先删后插, load_dotenv绝对路径, 日报5d/20d修复,
  RiskAgent改上证指数, 昨日对比+数据截止, mac_report utf8mb4,
  CLAUDE-*.md 9条已知Bug, demo全参数化, djapi数据源归一化,
  indexDatas API修正

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 15:59:05 +08:00
co-authored by Claude Opus 4.7
commit 271a9343a5
293 changed files with 59598 additions and 0 deletions
+145
View File
@@ -0,0 +1,145 @@
import pandas as pd
# 导入当站目录的config文件
try:
# 尝试相对导入(作为包的一部分)
from .config import TS_TOKEN, START_DATE, END_DATE, PRECISION_CONFIG
from .stock_utils import *
except (ImportError, SystemError):
# 失败则使用绝对导入(直接运行脚本)
from config import TS_TOKEN, START_DATE, END_DATE, PRECISION_CONFIG
from stock_utils import *
from .data_source import get_tushare_pro
pro = get_tushare_pro()
def get_index_by_name(index_name: str) -> pd.DataFrame:
"""
通过指数名称查询指数基本信息(使用tushare的index_basic接口)
Args:
index_name (str): 要查询的指数名称(支持模糊匹配,如"上证"
Returns:
pd.DataFrame: 包含查询结果的DataFrame,列包括:
- ts_code: 指数代码
- name: 指数名称
- fullname: 指数全称
- market: 市场
- publisher: 发布方
- index_type: 指数类型
- etc.
Raises:
Exception: 当tushare接口调用失败时抛出异常
Example:
>>> df = get_index_by_name("上证50")
>>> print(df[['ts_code', 'name']])
"""
try:
# 调用tushare接口查询指数信息
df = pro.index_basic(name=index_name)
# 检查返回结果是否为空
if df.empty:
print(f"未找到名称包含'{index_name}'的指数")
return pd.DataFrame() # 返回空DataFrame保持类型一致
return df
except Exception as e:
print(f"查询指数信息失败: {str(e)}")
return pd.DataFrame()
def get_index_daily_data(ts_code: str, start_date: str = START_DATE, end_date: str = END_DATE) -> pd.DataFrame:
"""
通过指数代码查询日线行情数据(合并基本行情和扩展行情)
Args:
ts_code (str): 指数代码(如"000001.SH"
start_date (str): 开始日期(格式"YYYYMMDD",默认使用config中的START_DATE
end_date (str): 结束日期(格式"YYYYMMDD",默认使用config中的END_DATE
Returns:
pd.DataFrame: 合并后的日线行情数据,包含以下列(示例):
- ts_code: 指数代码
- trade_date: 交易日期
- close: 收盘点位
- open: 开盘点位
- high: 最高点位
- low: 最低点位
- pe: 市盈率
- pb: 市净率
- etc.
Raises:
Exception: 当tushare接口调用失败或数据合并失败时抛出异常
Example:
>>> df = get_index_daily_data("000001.SH")
>>> print(df[['trade_date', 'close', 'pe']].head())
"""
try:
start_date = date_format_correction(start_date)
end_date = date_format_correction(end_date)
# 1. 查询日线基本行情(核心数据,必须成功)
daily_df = pro.index_daily(
ts_code=ts_code,
start_date=start_date,
end_date=end_date,
fields="ts_code,trade_date,open,high,low,close,pre_close,change,pct_chg,vol,amount"
)
if daily_df is None or daily_df.empty:
print("未找到指数{}{}{}期间的行情数据".format(ts_code, start_date, end_date))
return pd.DataFrame()
# 2. 尝试查询扩展行情(PE/PB 等,需要高权限,失败不阻塞)
try:
daily_basic_df = pro.index_dailybasic(
ts_code=ts_code,
start_date=start_date,
end_date=end_date,
fields="ts_code,trade_date,total_mv,float_mv,pe,pe_ttm,pb,turnover_rate,turnover_rate_f"
)
if daily_basic_df is not None and not daily_basic_df.empty:
daily_df = pd.merge(
daily_df, daily_basic_df,
on=['ts_code', 'trade_date'],
how='left'
)
except Exception as e:
print("index_dailybasic 不可用(权限不足或接口变更): {}".format(e))
return daily_df
except Exception as e:
print("查询指数日线行情失败: {}".format(e))
raise # 抛出而非静默返回空,让 view 层返回错误信息
if __name__ == "__main__":
# 测试指数查询
print("测试指数查询:")
index_df = get_index_by_name("中证500")
if not index_df.empty:
print(index_df[['ts_code', 'name']].head())
else:
print("未查询到指数信息")
'''# 测试指数行情获取
print("\n测试指数日线行情:")
test_code = "000016.SH" # 上证50指数代码
daily_data = get_index_daily_data(test_code, start_date="20230101", end_date="20231231")
if not daily_data.empty:
print(f"获取到{daily_data.shape[0]}条数据")
# 显示关键列的前5行
print(daily_data[['trade_date', 'close', 'pe', 'pb']].head())
# 数据完整性检查
print("\n数据完整性检查:")
print(daily_data[['close', 'pe']].describe())
else:
print(f"未获取到指数{test_code}的行情数据")'''