3. 策略代码工程化:项目目录结构设计、配置文件管理(YAML/JSON)、日志系统搭建(logging模块)

好,咱们进入第三个核心话题。代码能跑了,不代表能上线赚钱了。

实盘和回测最大的区别是什么?回测挂了可以重来,实盘挂了,亏的是真金白银。所以,代码必须工程化。说白了,就是让你的策略代码像一台精密的仪器,而不是一堆实验台上的电线。

我个人习惯,在写第一行策略逻辑之前,先把架子搭好。这个架子,就是项目目录结构、配置文件管理和日志系统。这三样东西,决定了你未来运维的幸福感。

3.1 项目目录结构设计:别把鸡蛋放在一个篮子里

很多新手喜欢把所有代码塞进一个文件夹,甚至一个文件里。刚开始觉得方便,但策略一多,或者需要多人协作时,就彻底乱套了。

我见过最夸张的项目,一个 main.py 文件有 3000 行。你想改个参数,得在 3000 行里 Ctrl+F 找半天。这哪是交易,这是考古。

一个合理的目录结构,应该像这样:

my_quant_strategy/
├── config/                 # 配置文件目录
│   ├── settings.yaml       # 主配置
│   └── instruments.yaml    # 交易标的配置
├── data/                   # 数据相关
│   ├── fetcher.py          # 数据获取
│   └── processor.py        # 数据清洗
├── strategy/               # 策略逻辑
│   ├── base.py             # 策略基类
│   ├── ma_cross.py         # 均线策略
│   └── arbitrage.py        # 套利策略
├── engine/                 # 引擎核心
│   ├── backtest.py         # 回测引擎
│   └── live.py             # 实盘引擎
├── risk/                   # 风控模块
│   └── manager.py          # 风控管理器
├── utils/                  # 工具函数
│   ├── logger.py           # 日志配置
│   └── helpers.py          # 辅助函数
├── logs/                   # 日志输出目录
├── tests/                  # 单元测试
│   └── test_strategy.py
├── requirements.txt        # 依赖清单
└── main.py                 # 程序入口

核心原则:高内聚,低耦合。每个模块只做一件事,并且做好一件事。数据模块别去管策略逻辑,策略模块也别直接写文件。

嗯,这里要注意,logs/ 目录不要提交到 Git 仓库。记得在 .gitignore 里加上它。我曾经有一次不小心把几十 GB 的日志文件 push 到了远程仓库,结果同事拉代码拉了半小时,差点被骂死。

3.2 配置文件管理:把参数从代码里「赶」出去

为什么要把参数写进配置文件?因为实盘和回测的参数往往不一样。比如回测时手续费是万二,实盘时券商给你万一点五。你总不能每次改参数都去改代码吧?

我个人强烈推荐使用 YAML 格式。它比 JSON 更易读,支持注释,写起来也舒服。

一个典型的 settings.yaml 长这样:

# 主配置
exchange:
  name: "binance"
  api_key: "${BINANCE_API_KEY}"   # 从环境变量读取,别硬编码!
  api_secret: "${BINANCE_SECRET}"

strategy:
  name: "ma_cross"
  params:
    fast_ma: 5
    slow_ma: 20
    position_size: 0.1   # 每次开仓比例

risk:
  max_drawdown: 0.15     # 最大回撤 15%
  max_position: 0.5      # 最大仓位 50%

logging:
  level: "INFO"
  file: "logs/trade.log"

避坑指南:API Key 和 Secret 绝对不要直接写在 YAML 文件里!用环境变量或者专门的密钥管理服务。我曾经见过有人把密钥提交到 GitHub 公开仓库,结果几分钟内账户就被盗了,损失惨重。

Python 读取 YAML 的代码示例:

import yaml
import os

def load_config(path="config/settings.yaml"):
    with open(path, 'r') as f:
        config = yaml.safe_load(f)
    
    # 替换环境变量占位符
    for key, value in config.items():
        if isinstance(value, str) and value.startswith("${"):
            env_var = value[2:-1]
            config[key] = os.environ.get(env_var)
    
    return config

# 使用
config = load_config()
print(config['strategy']['params']['fast_ma'])  # 输出 5

你看,这样改参数只需要改 YAML 文件,代码完全不用动。而且 YAML 支持嵌套结构,比扁平化的 JSON 清晰多了。

3.3 日志系统搭建:让程序「开口说话」

实盘交易时,程序在后台跑,你不可能一直盯着屏幕。那怎么知道它有没有正常执行?有没有报错?有没有成交?

答案就是日志。日志是程序的「黑匣子」。出了问题,第一件事就是翻日志。

Python 自带的 logging 模块足够强大,别用 print。为什么?因为 print 只能输出到控制台,而 logging 可以同时输出到控制台、文件、甚至网络。

一个标准的日志配置:

import logging
import logging.handlers
import os

def setup_logger(name="trading", log_file="logs/trade.log"):
    # 创建日志目录
    os.makedirs(os.path.dirname(log_file), exist_ok=True)
    
    # 创建 logger
    logger = logging.getLogger(name)
    logger.setLevel(logging.DEBUG)
    
    # 格式:时间 - 级别 - 模块 - 消息
    formatter = logging.Formatter(
        '%(asctime)s - %(levelname)s - %(name)s - %(message)s'
    )
    
    # 控制台处理器(输出 INFO 及以上)
    console_handler = logging.StreamHandler()
    console_handler.setLevel(logging.INFO)
    console_handler.setFormatter(formatter)
    
    # 文件处理器(输出 DEBUG 及以上,按天轮转)
    file_handler = logging.handlers.TimedRotatingFileHandler(
        log_file, when='midnight', backupCount=30
    )
    file_handler.setLevel(logging.DEBUG)
    file_handler.setFormatter(formatter)
    
    # 添加处理器
    logger.addHandler(console_handler)
    logger.addHandler(file_handler)
    
    return logger

# 使用
logger = setup_logger()
logger.info("策略启动成功")
logger.warning("连接交易所超时,正在重试...")
logger.error("下单失败:余额不足")

注意:日志文件一定要做轮转(Rotating)。否则跑个一年半载,日志文件能大到几百 GB,磁盘爆了程序就挂了。我建议按天轮转,保留 30 天。

日志级别怎么选?

级别 使用场景 示例
DEBUG 调试信息,开发时用 「收到 ticker: BTC/USDT, price=50000」
INFO 正常流程信息 「策略启动成功」「订单已提交」
WARNING 可能有问题,但不影响运行 「网络延迟较高」「API 限频接近阈值」
ERROR 发生了错误,但程序还能跑 「下单失败:价格超出限制」
CRITICAL 严重错误,程序即将退出 「数据库连接丢失,无法恢复」

实盘时,我一般把控制台设为 INFO 级别,文件设为 DEBUG 级别。这样平时看控制台只看到关键信息,出问题时再去翻详细的 DEBUG 日志。

3.4 知识体系总览

下面这张图,帮你把这三块内容串起来。你想想看,一个策略从启动到运行,数据是怎么流动的?

策略代码工程化核心流程 配置文件管理 YAML / JSON 策略引擎 读取配置 + 执行逻辑 日志系统 logging 模块 项目目录结构(支撑层) config/ → 提供配置参数 strategy/ → 策略逻辑实现 engine/ → 回测/实盘引擎 logs/ → 日志输出存储 data/ → 数据获取与处理 risk/ → 风控模块 utils/ → 工具函数 tests/ → 单元测试

说白了,目录结构是骨架,配置文件是血肉,日志系统是神经。三者缺一不可。

我的个人习惯:每次新建一个策略项目,先花 10 分钟把目录结构、配置文件和日志系统搭好。这 10 分钟,能为你未来省下 10 个小时的排查时间。

好了,这一章的内容就到这里。记住,工程化不是炫技,是为了让你睡得安稳。实盘时,日志里每一行输出,都是你判断系统是否健康的依据。


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