跳转至

StockDataMaster 接口调用规范与最佳实践

版本: v1.2
更新日期: 2026-04-30
适用版本: StockDataMaster 2.0.0+


目录

  1. 接口概览
  2. 日K线数据接口
  3. 分钟K线数据接口
  4. 缓存机制说明
  5. 使用场景与最佳实践
  6. 约束条件与限制

接口概览

核心接口

from StockDataMaster import StockDataMaster

master = StockDataMaster()

df   = master.get_kline(code, freq, start_date, end_date, count, adjust, use_cache)
df   = master.get_valuation(code, start_date, end_date)
tick = master.get_tick(code)
name = master.get_stock_name(code)
n    = master.warmup_stock_names()   # 批量预热股票名称缓存

数据源优先级

数据类型 P1 P2 P3 说明
日K线 Tushare Baostock Mootdx 带双源校验缓存
分钟K线 xtquant Baostock Mootdx 不缓存
估值数据 Tushare Baostock - 不缓存
实时Tick xtquant Mootdx - xtquant 需 QMT
校验源 Baostock xtquant(交易时段) - 串行短路
股票名称 Baostock xtquant Tushare 四级查找链

日K线数据接口

接口定义

def get_kline(
    code: str,
    freq: str = 'd',
    start_date: Optional[str] = None,
    end_date: Optional[str] = None,
    count: Optional[int] = None,
    adjust: str = 'qfq',
    use_cache: bool = True
) -> pd.DataFrame

请求模式

模式1:按数量请求(推荐)

df = master.get_kline('600519', freq='d', count=120)
  • 盘中时段:每次实时获取,不缓存当日
  • 盘后时段:缓存收盘数据,后续命中缓存

模式2:按日期范围请求(历史数据最优)

df = master.get_kline('600519', freq='d',
                      start_date='2025-10-01',
                      end_date='2025-10-24')
  • end_date < 今天 → 直接命中缓存,不请求数据源
  • 历史数据缓存命中率接近 100%

模式3:开始日期 + 数量

df = master.get_kline('600519', freq='d', start_date='2025-10-01', count=20)

缓存行为

盘中(< 15:00)

请求类型 缓存行为
count=N(包含今日) 每次实时获取
end_date < 今天 直接命中缓存

盘后(≥ 15:00)

请求类型 缓存行为
首次请求今日数据 写入收盘缓存
后续请求 命中缓存

周末/节假日

所有请求直接命中最新交易日的缓存,不触发数据源请求。

返回格式

         date     open     high      low    close     volume        amount
0  2026-04-28  1455.00  1469.50  1454.88  1457.93  2594988.0  3.793284e+09
1  2026-04-29  1459.00  1469.94  1455.50  1462.26  2544267.0  3.727984e+09
...

df.attrs['source']  # 'cache' / 'tushare' / 'baostock' / ...

分钟K线数据接口

支持的频率

频率 说明 主数据源 单次最大条数
'5m' 5分钟线 xtquant / Mootdx 800
'15m' 15分钟线 xtquant / Mootdx 800
'30m' 30分钟线 xtquant / Mootdx 800
'60m' 60分钟线 xtquant / Mootdx 800

分钟线不缓存,每次实时获取。

使用建议

# ✅ 推荐:合理的数据量
df = master.get_kline('600519', freq='5m', count=48)   # 约1天
df = master.get_kline('600519', freq='15m', count=80)  # 约1周

# ❌ 避免:超过 800 条
df = master.get_kline('600519', freq='5m', count=5000)  # 会失败

注意:Mootdx 分钟线前复权存在已知问题,如需精确复权数据建议通过 xtquant 获取。


缓存机制说明

缓存策略总览

数据类型 缓存 存储 默认上限
日K线 ✅ 智能缓存 SQLite 520条/股票
分钟K线 - -
估值数据 - -
Tick - -
股票名称 ✅ 持久化 SQLite 30天过期

数据库结构

kline_cache 表

CREATE TABLE kline_cache (
    code TEXT, date TEXT,
    open REAL, high REAL, low REAL, close REAL,
    volume REAL, amount REAL,
    source1 TEXT,      -- 主数据源
    source2 TEXT,      -- 校验数据源
    validated INTEGER, -- 0/1
    created_at TEXT, updated_at TEXT,
    UNIQUE(code, date)
);

缓存写入条件

  1. freq='d'use_cache=True
  2. 不在盘中时段(或数据日期 < 今日)
  3. 通过双源校验(价格容差 ±0.01元 或 ±0.5%,成交量 ±5%,通过率 ≥ 80%)

串行短路校验

校验顺序:xtquant(~50ms,仅交易时段)→ baostock(~2-3s,全时段)

xtquant 通过 → 立即写缓存(短路,不再等 baostock)
xtquant 失败 → 等待 baostock 结果

效果:交易时段节省约 2s 等待时间。

缓存管理

# 查看统计
stats = master.get_cache_statistics()
# {'stock_count': 25, 'total_records': 12000, 'db_size_mb': 1.8, ...}

# 清理旧数据(保留最近 520 天)
master.cleanup_cache(days=520)

使用场景与最佳实践

场景1:实时监控(盘中)

# 最新日K线(盘中不缓存,保证实时)
df = master.get_kline('600519', freq='d', count=1)

# 5分钟K线(最近1天)
df_5m = master.get_kline('600519', freq='5m', count=48)

# 真实Tick(需QMT)
tick = master.get_tick('600519')

场景2:历史数据分析

# 历史范围请求,全部命中缓存
df = master.get_kline('600519', freq='d',
                      start_date='2024-01-01',
                      end_date='2025-12-31')

场景3:回测(长周期)

import pandas as pd
from datetime import datetime, timedelta

def get_long_history(code, years=2):
    end = datetime.now()
    start = end - timedelta(days=years * 365)
    # 缓存上限 520 天,2年数据可一次拉取
    return master.get_kline(code, freq='d',
                            start_date=start.strftime('%Y-%m-%d'),
                            end_date=end.strftime('%Y-%m-%d'))

df = get_long_history('600519', years=2)

场景4:多股票批量查询

from concurrent.futures import ThreadPoolExecutor

codes = ['600519', '000001', '000858', '601318']

def fetch(code):
    return code, master.get_kline(code, freq='d', count=1)

# 控制并发数避免限流
with ThreadPoolExecutor(max_workers=3) as pool:
    results = dict(pool.map(lambda c: fetch(c), codes))

场景5:盘后定时更新

import schedule, time

def daily_update():
    codes = ['600519', '000001', '000858']
    for code in codes:
        master.get_kline(code, freq='d', count=1)  # 触发缓存写入

# 每天 15:30 执行
schedule.every().day.at("15:30").do(daily_update)
while True:
    schedule.run_pending()
    time.sleep(60)

约束条件与限制

数据源限制

数据源 限制
Tushare 按积分等级限流(默认 500次/分钟);分钟线需足够积分
Baostock 免费但较慢(2-3s);已升级 0.9.1,服务器迁移至 public-api.baostock.com
Mootdx 分钟线最多 800 条;前复权有已知问题
xtquant 依赖本地 QMT 客户端;Tick 是真实行情;其他源 Tick 是日K线模拟

格式约束

# 股票代码
'600519'     # ✅ 6位数字
'sh.600519'  # ✅ 带前缀(内部自动转换)
'600519.SH'  # ❌ 后缀格式,不支持

# 日期
'2025-10-24' # ✅ YYYY-MM-DD
'2025/10/24' # ❌

# 复权
adjust='qfq' # ✅ 唯一支持(前复权)
adjust='hfq' # ❌

缓存限制

配置项 默认值 说明
cache.max_days_per_stock 520 单只股票最大缓存天数
cache.validation.price_tolerance_abs 0.01 价格绝对容差(元)
cache.validation.price_tolerance_pct 0.005 价格相对容差
cache.validation.volume_tolerance_pct 0.05 成交量容差
cache.validation.min_pass_rate 0.8 最低通过率

附录:最小 config.json 示例

{
  "data_sources": {
    "tushare": {
      "enabled": true,
      "token": "你的Token",
      "roles": {
        "kline_day": { "priority": 1 },
        "valuation":  { "priority": 1 }
      }
    },
    "baostock": {
      "enabled": true,
      "roles": {
        "kline_day":  { "priority": 2 },
        "validation": { "priority": 1 },
        "stock_name": { "priority": 1 }
      }
    },
    "mootdx": {
      "enabled": true,
      "roles": {
        "kline_day":    { "priority": 3 },
        "kline_minute": { "priority": 3 },
        "tick":         { "priority": 2 }
      }
    },
    "xtquant": {
      "enabled": true,
      "roles": {
        "tick":         { "priority": 1 },
        "kline_minute": { "priority": 1 },
        "validation":   { "priority": 2, "time_slot": "trading" }
      }
    }
  },
  "cache": {
    "enabled": true,
    "max_days_per_stock": 520
  },
  "health_check": {
    "enabled": true,
    "interval_seconds": 60
  }
}