首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >云上量化微服务:用 FastAPI + Redis 搭建多策略共享的“行情缓存网关”

云上量化微服务:用 FastAPI + Redis 搭建多策略共享的“行情缓存网关”

原创
作者头像
用户9138916
发布2026-07-11 13:31:51
发布2026-07-11 13:31:51
240
举报

在设计分布式量化交易系统(如多策略并行、多容器运行)时,我们经常会遇到一个棘手的网络吞吐瓶颈:多个独立的策略进程盘中需要高频获取同一批热门股票的最新价格。

如果每个策略进程(例如 5 个回测容器、3 个实盘容器)都直接独立向外部金融数据 API 发起 HTTP 请求:

  1. API 配额损耗极快:相同的标的被重复请求了 8 次,浪费了大量的 API 访问配额。
  2. 极易触及频次限制(Rate Limit):高频并发请求可能导致外部服务器返回 429 Too Many Requests,甚至造成策略断流。
  3. 整体网络时延偏高:每次请求都要跨越公网,RTT(往返时延)通常在几十到几百毫秒级别。

为了解决这个架构痛点,本文将介绍如何基于 FastAPI + Redis,在云端(如腾讯云 CVM 或轻量应用服务器)搭建一个轻量级的内部行情缓存代理网关(Cache Gateway)。所有内部策略进程统一向该网关请求数据,通过 Cache-Aside(旁路缓存)模式大幅降低公网回源频率。


一、 架构设计:双层缓存代理网关

架构的逻辑非常简单直观:

代码语言:txt
复制
┌──────────────┐    ┌──────────────┐    ┌──────────────┐
│  策略容器 A  │    │  策略容器 B  │    │  策略容器 C  │
└──────┬───────┘    └──────┬───────┘    └──────┬───────┘
       │                   │                   │
       └─────────────┬─────┴───────────────────┘
                     │ (内网 HTTP 请求)
                     ▼
             ┌──────────────┐       读取缓存 (0.1ms)   ┌──────────────┐
             │ 行情代理网关  ├─────────────────────────►│  腾讯云Redis │
             │  (FastAPI)   │◄─────────────────────────┤ (TencentDB)  │
             └──────┬───────┘       未命中则写入缓存   └──────────────┘
                    │
                    │ 缓存失效 / 未命中时回源 (公网 REST API)
                    ▼
             ┌──────────────┐
             │ QuantDash API│
             └──────────────┘
  • 数据源选择:我们选择 QuantDash (quantdash.net) 作为外部回源 API。其 quotes 接口返回的数据结构轻量、规范,非常适合作为 JSON 格式缓存存入 Redis。
  • 缓存时效(TTL):由于盘中实时行情具有极强的时效性,我们将 Redis 的 Key 过期时间设为 2 秒。这既能保证策略拿到的是高频热数据,又能最大程度地将回源请求合并。

二、 核心代码实现

在云服务器中,我们通过 Python 快速构建这个微服务。

代码语言:bash
复制
pip install fastapi uvicorn redis quantdash
代码语言:python
复制
import os
import json
import redis
from fastapi import FastAPI, HTTPException
from quantdash import QuantDash

app = FastAPI(title="Internal Quant Data Cache Gateway")

# 1. 连接本地或腾讯云 TencentDB for Redis
REDIS_HOST = os.getenv("REDIS_HOST", "127.0.0.1")
REDIS_PORT = int(os.getenv("REDIS_PORT", 6379))
r = redis.Redis(host=REDIS_HOST, port=REDIS_PORT, decode_responses=True)

# 2. 初始化外部行情源 QuantDash 客户端
QD_API_KEY = os.getenv("QUANTDASH_API_KEY", "your_api_key_here")
qd = QuantDash(api_key=QD_API_KEY)

# 定义盘中热行情缓存生存时间(TTL = 2秒)
CACHE_TTL_SECONDS = 2

@app.get("/v1/quote/{symbol}")
def get_quote_with_cache(symbol: str):
    """
    获取实时行情接口 (Cache-Aside 模式)
    """
    cache_key = f"realtime_quote:{symbol.upper()}"
    
    # 尝试一:读取 Redis 缓存(内网连接,时延 < 1ms)
    try:
        cached_data = r.get(cache_key)
        if cached_data:
            return {
                "status": "success",
                "source": "local_redis_cache",
                "data": json.loads(cached_data)
            }
    except Exception as redis_err:
        # 降级处理:若 Redis 宕机,记录日志并继续通过 API 回源,保证业务不中断
        print(f"Redis Connection Error: {redis_err}")

    # 尝试二:缓存未命中,回源公网 QuantDash API
    try:
        # 获取单只标的的盘中实时行情数据 (SDK 默认支持 A/港/美 统一代码)
        quote_res = qd.quotes.get(symbols=[symbol])
        
        if not quote_res:
            raise HTTPException(status_code=404, detail=f"Symbol {symbol} not found.")
        
        # 适配返回数据结构(QuantDash quotes 返回通常为字典或列表)
        single_quote = quote_res[0] if isinstance(quote_res, list) else quote_res
        
        # 异步/同步写入 Redis 并设置 2s 自动过期
        try:
            r.setex(cache_key, CACHE_TTL_SECONDS, json.dumps(single_quote))
        except Exception as redis_err:
            print(f"Redis Write Error: {redis_err}")
            
        return {
            "status": "success",
            "source": "quantdash_origin_api",
            "data": single_quote
        }
        
    except Exception as api_err:
        raise HTTPException(
            status_code=500, 
            detail=f"Failed to fetch data from origin API: {str(api_err)}"
        )
三、 性能与配额开销对比分析

我们来算一笔“技术账”,看看这个简单的缓存层能为云上系统带来多大改观。

你部署了 10 个策略容器,每个容器盘中每 1 秒就需要读取一次 00700.HK 的最新价。

  • 传统直连架构
    • 10 个容器每秒发起 10 次公网 HTTP 请求。
    • 公网 API 消耗:600 次/分钟
    • 请求平均耗时:100ms - 300ms (依赖公网 RTT)。
  • 缓存网关架构 (TTL = 2s)
    • 在 2 秒的生命周期内,第一个容器发起请求时未命中,网关向 QuantDash 公网发起 1 次回源,随后将数据存入 Redis。接下来的 2 秒内,其余 9 个容器的所有高频请求,全部在局域网内直接读取 Redis。
    • 公网 API 消耗:30 次/分钟
    • 配额节省率:达 95%
    • 内网 Redis 延迟:< 1ms

四、 云端生产环境部署建议

若要在腾讯云生产环境中落地该架构,建议结合以下云原生最佳实践:

  1. 容器化部署 (Docker & K8s): 利用 Dockerfile 将此 FastAPI 脚本打包为微服务镜像,在腾讯云容器服务 TKE 或轻量应用服务器中拉起多副本。
  2. 多标的批量预加载 (Pre-heating): 如果监控的股票池是固定的(如 50 只核心自选股),可以在网关中加入后台定时任务,每隔 2 秒**批量(Bulk)**调用 qd.quotes.get 刷新这 50 只股票的缓存。这样内部策略请求时永远都是 100% 缓存命中 (Cache Hit),进一步消除了首次回源的阻塞时间。
  3. 内网高可用连接: 建议将网关与腾讯云云数据库 TencentDB for Redis 部署在同一 VPC(私有网络) 下。利用腾讯云 Redis 的高可用内网免去自建维护成本,并获得极低的网络抖动率。

总结

微服务设计的一大原则是“单一职责”。通过将行情获取职责收敛到独立的缓存网关,不仅能帮我们省下可观的外部 API 调用费,还为下游策略逻辑屏蔽了复杂的网络回源和错误处理,是中大型云上量化交易系统不可或缺的一环。

如果你也正处于多策略扩展的阶段,建议尽早用这套低成本方案将数据读取层解耦。

参考文档:https://quantdash.net/

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、 架构设计:双层缓存代理网关
  • 二、 核心代码实现
  • 三、 性能与配额开销对比分析
  • 四、 云端生产环境部署建议
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档