3、项目初始化与环境搭建:FastAPI框架选型、项目目录结构、依赖管理、配置文件设计

好,咱们正式开始动手了。

这一章,说白了就是搭架子。架子搭得稳,后面写代码才不慌。我在多个量化项目里踩过不少坑,比如目录乱成一锅粥、依赖冲突到崩溃、配置写死在代码里导致部署时手忙脚乱……嗯,这些教训让我对项目初始化这件事格外重视。

今天咱们就用 FastAPI 来搭一个因子工厂的架子。为什么选它?我后面会细说。

3.1 为什么选 FastAPI?

选框架这事儿,我个人的习惯是:不追新,但要够用且好用。

FastAPI 有几个点特别打动我:

  • 性能好:基于 Starlette 和 Pydantic,异步原生支持。做量化因子计算,经常要并行拉数据、算指标,异步 IO 能省下大把时间。
  • 自动生成文档:Swagger 和 ReDoc 开箱即用。你想想看,团队协作时,接口文档自动生成,省了多少沟通成本。
  • 类型校验强:Pydantic 做数据模型,请求参数、响应数据都能自动校验。我在项目中遇到过因为因子参数传错类型导致计算崩溃的惨案,有了类型校验,这类问题基本绝迹。
  • 社区活跃:遇到问题,Stack Overflow 上一搜一大把。生态也成熟,ORM、缓存、消息队列都有现成方案。

核心观点:FastAPI 不是万能的,但在量化因子工厂这个场景下,它几乎是完美的选择。轻量、高效、易维护。

3.2 项目目录结构

目录结构这事儿,我建议一开始就定好规矩。别等到项目大了再重构,那滋味可不好受。

下面是我在多个项目中沉淀下来的结构,你可以直接拿来用:

factor_factory/
├── app/                    # 主应用目录
│   ├── __init__.py
│   ├── main.py            # 应用入口
│   ├── api/               # API 路由层
│   │   ├── __init__.py
│   │   ├── v1/            # API 版本控制
│   │   │   ├── __init__.py
│   │   │   ├── factors.py # 因子相关接口
│   │   │   └── health.py  # 健康检查
│   ├── core/              # 核心配置
│   │   ├── __init__.py
│   │   ├── config.py      # 配置管理
│   │   └── security.py    # 安全相关
│   ├── models/            # 数据模型
│   │   ├── __init__.py
│   │   ├── factor.py      # 因子模型
│   │   └── response.py    # 通用响应模型
│   ├── services/          # 业务逻辑层
│   │   ├── __init__.py
│   │   ├── factor_calc.py # 因子计算服务
│   │   └── data_feed.py   # 数据接入服务
│   ├── db/                # 数据库相关
│   │   ├── __init__.py
│   │   ├── session.py     # 数据库会话
│   │   └── base.py        # 基类模型
│   └── utils/             # 工具函数
│       ├── __init__.py
│       ├── logger.py      # 日志工具
│       └── helpers.py     # 辅助函数
├── tests/                 # 测试目录
│   ├── __init__.py
│   ├── test_factors.py
│   └── conftest.py
├── logs/                  # 日志文件
├── data/                  # 数据文件(本地开发用)
├── .env                   # 环境变量(不提交到 Git)
├── .env.example           # 环境变量示例
├── .gitignore
├── requirements.txt       # 依赖清单
├── pyproject.toml         # 项目元数据
└── README.md

这个结构有几个好处:

  • 分层清晰:API、业务逻辑、数据模型各司其职,互不干扰。
  • 版本控制:api/v1 目录方便后续接口升级,不会影响老版本。
  • 测试独立:tests 目录和主代码分离,跑测试时不会污染业务代码。

小提示:我个人习惯把 .env 文件放在项目根目录,但绝不提交到 Git。你可以在 .env.example 里写个模板,方便新同事快速上手。

3.3 依赖管理

依赖管理这事儿,说大不大,说小不小。我曾经在一个项目里因为依赖版本冲突,排查了整整两天。从那以后,我对依赖管理就格外上心。

我推荐用 pip + requirements.txt 的组合,简单直接。如果你喜欢更现代的方案,Poetry 或 PDM 也可以,但咱们这个课程里,我选择最通用的方式。

下面是我们因子工厂的核心依赖:

# requirements.txt
fastapi==0.104.1
uvicorn[standard]==0.24.0
pydantic==2.5.2
pydantic-settings==2.1.0
sqlalchemy==2.0.23
asyncpg==0.29.0
redis==5.0.1
pandas==2.1.4
numpy==1.26.2
python-dotenv==1.0.0
loguru==0.7.2
httpx==0.25.2
pytest==7.4.3
pytest-asyncio==0.23.2

安装命令很简单:

pip install -r requirements.txt

注意:我建议你使用虚拟环境。不管是 venv 还是 conda,都行。千万别把项目依赖装到全局 Python 里,否则后面有你哭的。

3.4 配置文件设计

配置文件,说白了就是项目的「开关面板」。环境变了,改配置就行,不用改代码。

我习惯用 pydantic-settings 来管理配置。为什么?因为它能自动从环境变量读取值,还能做类型校验。你想想看,如果配置里有个端口号写成了字符串,程序启动时直接报错,总比运行时莫名其妙出问题强。

来看一个完整的配置示例:

# app/core/config.py
from pydantic_settings import BaseSettings
from typing import Optional

class Settings(BaseSettings):
    # 应用基础配置
    APP_NAME: str = "Factor Factory API"
    APP_VERSION: str = "1.0.0"
    DEBUG: bool = False
    
    # 服务端口
    HOST: str = "0.0.0.0"
    PORT: int = 8000
    
    # 数据库配置
    DATABASE_URL: str = "postgresql+asyncpg://user:pass@localhost:5432/factor_db"
    DB_POOL_SIZE: int = 10
    DB_MAX_OVERFLOW: int = 20
    
    # Redis 配置
    REDIS_URL: str = "redis://localhost:6379/0"
    REDIS_TIMEOUT: int = 5
    
    # 因子计算配置
    FACTOR_CACHE_TTL: int = 3600  # 因子缓存时间,单位秒
    MAX_CONCURRENT_CALC: int = 4  # 最大并发计算数
    
    # 日志配置
    LOG_LEVEL: str = "INFO"
    LOG_FILE: str = "logs/factor_factory.log"
    
    class Config:
        env_file = ".env"
        env_file_encoding = "utf-8"

settings = Settings()

对应的 .env 文件:

# .env
APP_NAME=Factor Factory API
DEBUG=true
PORT=8000
DATABASE_URL=postgresql+asyncpg://dev_user:dev_pass@localhost:5432/factor_dev
REDIS_URL=redis://localhost:6379/0
LOG_LEVEL=DEBUG

使用方式也很简单:

from app.core.config import settings

print(settings.APP_NAME)  # 输出:Factor Factory API
print(settings.DATABASE_URL)  # 输出:postgresql+asyncpg://dev_user:dev_pass@localhost:5432/factor_dev

关键点:配置文件和代码分离,这是 12-Factor App 方法论的核心原则之一。你的代码应该能在任何环境中运行,只需要换一套配置就行。

3.5 知识体系结构图

下面这张图,是我用 SVG 画的,展示了本章的知识脉络。你可以把它当作一张地图,随时回来看看自己走到哪了。

项目初始化与环境搭建 - 知识体系 因子工厂项目初始化 FastAPI 框架选型 异步支持、自动文档、类型校验 项目目录结构 分层清晰、版本控制、测试独立 依赖管理 requirements.txt、虚拟环境 配置文件设计 pydantic-settings、环境变量 目标:可维护、可扩展、可部署

3.6 启动你的第一个 FastAPI 应用

架子搭好了,咱们跑起来看看。

app/main.py 里写个最简单的入口:

# app/main.py
from fastapi import FastAPI
from app.core.config import settings

app = FastAPI(
    title=settings.APP_NAME,
    version=settings.APP_VERSION,
    debug=settings.DEBUG
)

@app.get("/")
async def root():
    return {"message": "Factor Factory API is running!"}

@app.get("/health")
async def health_check():
    return {"status": "healthy"}

启动命令:

uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload

打开浏览器,访问 http://localhost:8000/docs,你会看到 FastAPI 自动生成的 Swagger 文档页面。嗯,这个感觉就对了。

小技巧:加上 --reload 参数,代码改了会自动重启。开发时特别方便,省得你每次改完代码还要手动重启服务。

好了,项目初始化这块就聊到这儿。架子搭好了,后面咱们就可以往里面填东西了。记住,好的开始是成功的一半,别嫌这一步麻烦。


公众号:蓝海资料掘金营,微信deep3321