Files
ljwx-stock/DATA_SOURCE_ANALYSIS.md
brunoandClaude Sonnet 4.5 c553009853 feat: 添加全量A股数据抓取系统 v2.1.0
新增功能:
- 5个专业数据抓取器(公司信息、板块、财务、资金流、龙虎榜)
- 一键执行脚本 run_all_fetchers.sh(完整/测试/自定义三种模式)
- 扩展数据库Schema(11张新表)
- 数据源迁移至免费API(东方财富、新浪、腾讯)

数据能力:
- 公司基础信息:5,295只A股
- 板块数据:~400个板块 + 20万成分股关系
- 财务报表:利润表+资产负债表(最近4季)
- 资金流:主力资金、大单、中单、小单(700天)
- 龙虎榜:上榜记录+营业部明细(2年)
- 总数据量:~395万条记录,3-5GB存储

技术亮点:
- 断点续传支持
- UPSERT策略避免重复
- API限流控制
- 实时进度显示
- 错误容错机制
- 完整日志记录

文档更新:
- README添加"全量数据抓取"章节
- 60+页技术方案文档
- 完整的使用指南和维护文档

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <[email protected]>
2025-12-22 08:35:43 +08:00

18 KiB
Raw Permalink Blame History

数据源分析与推荐方案

📊 一、需要获取的数据类型

基于现有系统分析(backend/app/models/stock_models.py 和 backend/database/schema_v2.sql),系统需要以下数据:

1. 股票基本信息 (stocks 表)

字段 说明 示例
symbol 股票代码 "600000"
name 股票名称 "浦发银行"
market 市场类型 "A_SHARE", "US", "HK", "FOREX"
industry 所属行业 "银行"
list_date 上市日期 "1999-11-10"

2. 日线行情数据 (daily_quotes 表)

字段 说明 数据类型
symbol 股票代码 VARCHAR(20)
trade_date 交易日期 DATE
open 开盘价 DECIMAL(12,4)
high 最高价 DECIMAL(12,4)
low 最低价 DECIMAL(12,4)
close 收盘价 DECIMAL(12,4)
volume 成交量 BIGINT
amount 成交额 DECIMAL(20,2)
turnover_rate 换手率 DECIMAL(8,4)

数据量需求: 至少1年历史数据(约250个交易日/股票)

3. 技术指标数据 (technical_indicators 表)

字段 说明 计算方法
ma5, ma10, ma20, ma60 移动均线 基于收盘价计算
rsi 相对强弱指标 RSI(14)
macd, macd_signal, macd_hist MACD指标 12-26-9
bollinger_upper/middle/lower 布林带 20日标准差
atr 平均真实波幅 ATR(14)
obv 能量潮 累计成交量指标

计算策略: 从日线数据计算得出,无需单独获取

4. 基本面数据 (fundamentals 表)

字段 说明 更新频率
pe_ratio 市盈率 每日
pb_ratio 市净率 每日
ps_ratio 市销率 每季度
roe 净资产收益率 每季度
roa 资产收益率 每季度
gross_margin 毛利率 每季度
net_margin 净利率 每季度
debt_to_equity 资产负债率 每季度
current_ratio 流动比率 每季度
total_revenue 总营收 每季度
net_profit 净利润 每季度
total_assets 总资产 每季度
total_equity 总权益 每季度

5. 实时行情数据 (缓存层)

字段 说明 TTL
price 当前价格 60秒
bid 买一价 60秒
ask 卖一价 60秒
volume 成交量 60秒
timestamp 时间戳 -

🔍 二、数据源测试结果

测试方法

  • 运行 backend/test_data_sources.py - 测试新浪、东方财富、雪球、网易
  • 运行 backend/test_akshare.py - 测试 AkShare 数据库

测试结果汇总

数据源 实时行情 历史K线 基本面 免费 认证 稳定性 推荐
新浪财经 ✅ ❌ ❌ ✅ 无需 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐
东方财富 ✅ ⚠️ ⚠️ ✅ 无需 ⭐⭐⭐⭐ ⭐⭐⭐
AkShare ✅ ✅ ✅ ✅ 无需 ⭐⭐⭐⭐ ⭐⭐⭐⭐⭐
雪球 ⚠️ ❌ ❌ ✅ 需要 ⭐⭐ ⭐
网易财经 ❌ ❌ ❌ ✅ 无需 ⭐ ⭐
TuShare ✅ ✅ ✅ ⚠️ API Key ⭐⭐⭐⭐ ⭐⭐

图例: ✅ 可用 | ⚠️ 部分可用 | ❌ 不可用

详细测试数据

1. 新浪财经实时行情 ✅

URL: http://hq.sinajs.cn/list=sh600000,sz000001
响应格式: GBK编码文本

优点:

  • ✅ 完全免费,无需API key
  • ✅ 响应速度快(<100ms)
  • ✅ 数据字段丰富(32个字段)
  • ✅ 稳定性高,多年未变

缺点:

  • ❌ 仅支持实时行情,无历史数据
  • ❌ 返回格式为文本,需要解析

可用字段:

{
    "name": "浦发银行",
    "price": 11.69,       # 最新价
    "open": 11.72,        # 开盘价
    "pre_close": 11.78,   # 昨收
    "high": 11.80,        # 最高
    "low": 11.65,         # 最低
    "bid": 11.69,         # 买一
    "ask": 11.70,         # 卖一
    "volume": 67815119,   # 成交量(股)
    "amount": 794336354,  # 成交额(元)
    "date": "2025-12-19",
    "time": "15:00:03"
}

2. 东方财富实时行情 ✅

URL: http://push2.eastmoney.com/api/qt/stock/get
参数: secid=1.600000&fields=f43,f44,f45,f46,f47,f48,f168
响应格式: JSON

优点:

  • ✅ 返回JSON格式,易于解析
  • ✅ 包含换手率字段(新浪不提供)
  • ✅ 数据准确,来源权威

缺点:

  • ⚠️ 价格数据需除以100

可用字段:

{
    "symbol": "1.600000",
    "name": "浦发银行",
    "price": 11.69,
    "open": 11.72,
    "high": 11.80,
    "low": 11.65,
    "volume": 678151,      # 成交量(手)
    "amount": 794336354,
    "turnover_rate": 0.20  # 换手率%
}

3. AkShare ⭐⭐⭐⭐⭐ (强烈推荐)

安装:

pip install akshare

测试结果:

  • ✅ 实时行情: 5790只股票
  • ✅ 历史K线: 6211条数据(1999-11-10至今)
  • ✅ 基本面: 个股信息、行业分类
  • ✅ 股票列表: 5461只
  • ✅ 行业分类: 86个行业

代码示例:

import akshare as ak

# 1. 实时行情
df = ak.stock_zh_a_spot_em()
# 返回: 5790只股票的实时数据
# 字段: 代码、名称、最新价、涨跌幅、成交量、成交额、换手率、市盈率、市净率等23个字段

# 2. 历史K线(日线)
df = ak.stock_zh_a_hist(symbol="600000", period="daily", adjust="qfq")
# 返回: 从1999年至今的所有日线数据
# 字段: 日期、开盘、收盘、最高、最低、成交量、成交额、振幅、涨跌幅、涨跌额、换手率

# 3. 个股基本信息
df = ak.stock_individual_info_em(symbol="600000")
# 返回: 总股本、流通股、总市值、行业、上市时间等

# 4. 股票列表
df = ak.stock_info_a_code_name()
# 返回: 5461只A股代码和名称

# 5. 行业分类
df = ak.stock_board_industry_name_em()
# 返回: 86个申万行业分类

# 6. 行业成分股
df = ak.stock_board_industry_cons_em(symbol="房地产服务")
# 返回: 该行业所有成分股及实时行情

优点:

  • ✅ 完全免费,无需API key
  • ✅ 数据覆盖全面(实时+历史+基本面)
  • ✅ 接口简单,返回pandas DataFrame
  • ✅ 数据来源权威(东方财富、新浪等)
  • ✅ 社区活跃,更新及时
  • ✅ 中文文档完善

缺点:

  • ⚠️ 数据来源于公开接口,存在反爬风险
  • ⚠️ 某些接口可能不稳定
  • ⚠️ 不支持分钟级历史数据

🎯 三、推荐方案

方案A: AkShare单一数据源(推荐)⭐⭐⭐⭐⭐

架构:

┌─────────────────────────────────────────────────────────┐
│  数据采集层 (AkShare)                                   │
├─────────────────────────────────────────────────────────┤
│  - 实时行情: ak.stock_zh_a_spot_em()                    │
│  - 历史K线: ak.stock_zh_a_hist()                        │
│  - 基本面: ak.stock_individual_info_em()                │
│  - 股票列表: ak.stock_info_a_code_name()                │
│  - 行业分类: ak.stock_board_industry_name_em()          │
├─────────────────────────────────────────────────────────┤
│  数据处理层 (feature_engineer.py)                       │
├─────────────────────────────────────────────────────────┤
│  - 技术指标计算: MA, RSI, MACD, Bollinger, ATR, OBV    │
│  - 数据清洗和标准化                                     │
├─────────────────────────────────────────────────────────┤
│  缓存层 (Redis)                                         │
├─────────────────────────────────────────────────────────┤
│  - 实时行情: TTL 60s                                    │
│  - 历史数据: TTL 300s                                   │
│  - 基本面: TTL 3600s                                    │
├─────────────────────────────────────────────────────────┤
│  持久化层 (PostgreSQL)                                  │
├─────────────────────────────────────────────────────────┤
│  - daily_quotes: 日线数据(1年+)                       │
│  - technical_indicators: 技术指标                       │
│  - fundamentals: 基本面数据                             │
│  - stocks: 股票基本信息                                 │
└─────────────────────────────────────────────────────────┘

优点:

  • ✅ 架构简单,维护成本低
  • ✅ 单一数据源,数据一致性好
  • ✅ 完全免费,无API key管理
  • ✅ 接口稳定,社区支持好

缺点:

  • ⚠️ 单点依赖,若AkShare不可用则全部失败
  • ⚠️ 数据源变更风险

适用场景: ✅ 开发阶段、MVP、中小规模生产环境

方案B: 多数据源冗余(高可用)⭐⭐⭐⭐

架构:

┌─────────────────────────────────────────────────────────┐
│  数据采集层(多源容错)                                 │
├─────────────────────────────────────────────────────────┤
│  实时行情 (优先级):                                     │
│    1. AkShare (主)                                      │
│    2. 新浪财经 (备用1)                                  │
│    3. 东方财富 (备用2)                                  │
│                                                         │
│  历史K线:                                               │
│    1. AkShare (主)                                      │
│    2. 本地缓存 (备用)                                   │
│                                                         │
│  基本面:                                                │
│    1. AkShare (主)                                      │
│    2. 爬虫 (备用,需开发)                               │
└─────────────────────────────────────────────────────────┘

代码示例:

async def get_realtime_quote(symbol: str) -> Dict:
    """多数据源容错获取实时行情"""

    # 优先级1: AkShare
    try:
        df = ak.stock_zh_a_spot_em()
        quote = df[df['代码'] == symbol].iloc[0]
        return parse_akshare_quote(quote)
    except Exception as e:
        logger.warning(f"AkShare failed: {e}")

    # 优先级2: 新浪财经
    try:
        return fetch_sina_quote(symbol)
    except Exception as e:
        logger.warning(f"Sina failed: {e}")

    # 优先级3: 东方财富
    try:
        return fetch_eastmoney_quote(symbol)
    except Exception as e:
        logger.error(f"All sources failed for {symbol}")
        raise DataSourceException("No available data source")

优点:

  • ✅ 高可用性,单个数据源故障不影响系统
  • ✅ 数据交叉验证

缺点:

  • ❌ 复杂度高,维护成本大
  • ❌ 数据一致性难保证

适用场景: ✅ 大规模生产环境、金融级应用

方案C: 混合模式(平衡方案)⭐⭐⭐⭐

数据源分工:

  • 实时行情: 新浪财经(速度快、稳定)
  • 历史K线: AkShare(数据完整、免费)
  • 基本面: AkShare + 定期爬虫
  • 技术指标: 本地计算(基于历史数据)

优点:

  • ✅ 发挥各数据源优势
  • ✅ 风险分散

缺点:

  • ⚠️ 维护复杂度中等

适用场景: ✅ 中等规模生产环境


📋 四、最终推荐

开发阶段(当前): 方案A - AkShare单一数据源

理由:

  1. 快速迭代,无需API key管理
  2. 数据覆盖全面,满足所有需求
  3. 接口简单,开发效率高
  4. 完全免费,无成本

生产环境(未来): 方案C - 混合模式

迁移路径:

阶段1 (当前): AkShare单一数据源
         ↓
阶段2 (3个月后): 添加新浪财经实时行情作为备用
         ↓
阶段3 (6个月后): 评估付费数据源(TuShare Points、东方财富Choice)
         ↓
阶段4 (1年后): 自建数据爬虫+商业数据源混合

🛠️ 五、实施计划

第一阶段: 数据获取模块重构(本周)

任务:

  1. ✅ 安装 akshare: pip install akshare

  2. 创建新的数据获取模块: backend/app/modules/data_fetcher_v2.py

  3. 实现以下接口:

    • fetch_stock_list() - 获取股票列表
    • fetch_realtime_quotes(symbols) - 批量实时行情
    • fetch_historical_kline(symbol, start_date, end_date) - 历史K线
    • fetch_stock_info(symbol) - 基本信息
    • fetch_industry_classification() - 行业分类
  4. 编写单元测试: backend/tests/test_data_fetcher_v2.py

第二阶段: 数据库初始化(本周)

任务:

  1. 创建数据库迁移脚本: backend/db/migration/V001__init_tables.sql
  2. 使用现有 schema_v2.sql
  3. 初始化股票列表(5461只A股)
  4. 批量加载1年历史数据(约250个交易日 × 5461只 = 136万条记录)

数据加载策略:

# 分批加载,避免内存溢出
async def load_historical_data():
    stock_list = await fetch_stock_list()

    for i in range(0, len(stock_list), 100):  # 每批100只
        batch = stock_list[i:i+100]

        for symbol in batch:
            df = ak.stock_zh_a_hist(symbol=symbol, period="daily", adjust="qfq")
            # 筛选最近1年数据
            df_1year = df[df['日期'] >= '2024-12-21']
            # 批量插入数据库
            await bulk_insert_daily_quotes(df_1year)

        await asyncio.sleep(1)  # 避免请求过快

第三阶段: API接口适配(下周)

任务:

  1. 更新 backend/app/routes/recommendations.py
  2. 移除 TuShare 依赖
  3. 测试所有API端点

第四阶段: 前端适配(下周)

任务:

  1. 验证前端数据展示正常
  2. 测试实时刷新功能

📈 六、性能优化建议

1. 缓存策略

# Redis缓存配置
CACHE_CONFIG = {
    "realtime_quote": {
        "ttl": 60,        # 实时行情缓存60秒
        "key_pattern": "quote:{symbol}"
    },
    "historical_kline": {
        "ttl": 3600,      # 历史K线缓存1小时
        "key_pattern": "kline:{symbol}:{period}"
    },
    "fundamentals": {
        "ttl": 86400,     # 基本面缓存24小时
        "key_pattern": "fund:{symbol}"
    }
}

2. 数据预热

# 在交易日开盘前(9:00)预加载热门股票数据
async def prewarm_cache():
    top_stocks = await get_top_100_stocks()

    for symbol in top_stocks:
        # 预加载到Redis
        await fetch_and_cache_quote(symbol)
        await fetch_and_cache_fundamentals(symbol)

3. 限流策略

# 避免被封IP
import asyncio
from functools import wraps

def rate_limit(calls_per_second=2):
    """限流装饰器"""
    min_interval = 1.0 / calls_per_second
    last_called = [0.0]

    def decorator(func):
        @wraps(func)
        async def wrapper(*args, **kwargs):
            elapsed = time.time() - last_called[0]
            if elapsed < min_interval:
                await asyncio.sleep(min_interval - elapsed)
            last_called[0] = time.time()
            return await func(*args, **kwargs)
        return wrapper
    return decorator

@rate_limit(calls_per_second=2)
async def fetch_with_limit(symbol):
    return ak.stock_zh_a_hist(symbol=symbol)

🎓 七、参考资料

AkShare 官方文档

数据源对比

数据源 优势 劣势 官网
AkShare 免费、全面 反爬风险 akshare.akfamily.xyz
TuShare 数据权威 需积分 tushare.pro
新浪财经 实时快速 仅实时 finance.sina.com.cn
东方财富 JSON格式 接口变化 quote.eastmoney.com

📝 八、总结

当前状态: 已完成数据源调研和验证

下一步行动:

  1. ✅ 实施方案A(AkShare单一数据源)
  2. 创建 data_fetcher_v2.py 模块
  3. 初始化数据库(加载1年历史数据)
  4. 更新API接口
  5. 测试端到端流程

预期收益:

  • ❌ 移除 TuShare 依赖(节省 API token 管理成本)
  • ✅ 完全免费的数据获取方案
  • ✅ 更简单的架构,降低维护成本
  • ✅ 更快的开发迭代速度

风险:

  • ⚠️ AkShare 单点依赖(通过本地数据库缓存缓解)
  • ⚠️ 反爬风险(通过限流和User-Agent轮换缓解)

生成时间: 2025-12-21 版本: v1.0 作者: Claude Code