第二十章 实盘部署架构:服务器选型、API对接、日志监控、自动重启

各位,前面我们把策略逻辑讲得差不多了。但说实话,策略写得再好,部署环节出问题,一切归零。

我见过太多人,回测曲线漂亮得不行,一上实盘就崩。为什么?服务器挂了没人管,API断了没发现,日志堆满磁盘都不知道。今天这章,咱们就把这些「脏活累活」一次性讲透。

20.1 服务器选型:别在硬件上省钱

我个人习惯,实盘服务器首选腾讯云轻量应用服务器或者阿里云ECS。为什么?稳定、便宜、运维省心。

配置项 推荐规格 说明
CPU 4核及以上 基差计算、信号生成、订单管理并行跑
内存 8GB起步 行情数据缓存、日志缓冲都需要内存
磁盘 50GB SSD 日志文件增长很快,SSD保证读写速度
带宽 5Mbps以上 期货行情推送、API请求都需要带宽
系统 Ubuntu 20.04 LTS 稳定、社区活跃、Python生态友好
我的经验:别用Windows服务器跑实盘。Windows的定时任务、进程管理、远程维护都比Linux麻烦。我曾经在Windows上部署过一个套利策略,半夜系统自动更新重启,第二天发现仓位全平了……从那以后,我只用Linux。

20.2 API对接:稳定是第一要义

API对接,说白了就是让你的策略跟交易所「对话」。这里有几个关键点:

20.2.1 选择API协议

国内期货市场,主流是CTP(综合交易平台)。CTP是上期技术开发的,几乎所有期货公司都支持。我个人建议直接用vnpy或者backtrader封装好的CTP接口,别自己从头写。

20.2.2 连接管理

API连接不是一劳永逸的。网络波动、交易所维护、API超时,都会导致断连。你需要一个心跳检测+自动重连机制。

import time
import threading

class CTPConnection:
    def __init__(self, broker_id, user_id, password, front_addr):
        self.broker_id = broker_id
        self.user_id = user_id
        self.password = password
        self.front_addr = front_addr
        self.api = None
        self.connected = False
        self.heartbeat_thread = None

    def connect(self):
        """建立连接"""
        # 初始化CTP API
        self.api = MdApi.CreateFtdcMdApi()
        self.api.RegisterSpi(self)
        self.api.RegisterFront(self.front_addr)
        self.api.Init()
        print(f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] 正在连接CTP...")

    def OnFrontConnected(self):
        """连接成功回调"""
        print("CTP连接成功")
        self.connected = True
        # 开始心跳检测
        self.start_heartbeat()

    def OnRspUserLogin(self, pRspUserLogin, pRspInfo, nRequestID, bIsLast):
        """登录回调"""
        if pRspInfo.ErrorID == 0:
            print(f"登录成功,交易日:{pRspUserLogin.TradingDay}")
        else:
            print(f"登录失败:{pRspInfo.ErrorMsg}")

    def start_heartbeat(self):
        """启动心跳线程"""
        def heartbeat():
            while self.connected:
                # 发送心跳请求
                self.api.ReqUserLogin(...)
                time.sleep(30)  # 每30秒一次
        self.heartbeat_thread = threading.Thread(target=heartbeat, daemon=True)
        self.heartbeat_thread.start()

    def reconnect(self):
        """自动重连"""
        print("检测到连接断开,尝试重连...")
        self.connected = False
        self.connect()
注意:CTP的API是C++写的,Python调用需要封装。vnpy已经帮你做好了,直接用就行。别自己造轮子,容易出bug。

20.3 日志监控:出了问题能追溯

实盘交易,日志就是你的「黑匣子」。没有日志,出了问题你都不知道从哪查起。

20.3.1 日志分级

我习惯分三级:

  • INFO:正常交易记录,比如「开仓成功」「平仓成功」
  • WARNING:异常但不致命,比如「API响应超时,重试中」
  • ERROR:致命错误,比如「连接断开」「资金不足」

20.3.2 日志轮转

日志文件会越来越大,必须做轮转。Python的logging.handlers.RotatingFileHandler可以搞定。

import logging
from logging.handlers import RotatingFileHandler

def setup_logger(name, log_file, level=logging.INFO):
    """配置日志记录器"""
    formatter = logging.Formatter(
        '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    )

    # 文件日志,每个文件10MB,保留5个备份
    file_handler = RotatingFileHandler(
        log_file, maxBytes=10*1024*1024, backupCount=5
    )
    file_handler.setFormatter(formatter)

    # 控制台日志
    console_handler = logging.StreamHandler()
    console_handler.setFormatter(formatter)

    logger = logging.getLogger(name)
    logger.setLevel(level)
    logger.addHandler(file_handler)
    logger.addHandler(console_handler)

    return logger

# 使用示例
trade_logger = setup_logger('trade', 'logs/trade.log')
error_logger = setup_logger('error', 'logs/error.log', level=logging.ERROR)

trade_logger.info('开仓成功:rb2405,方向多,手数2')
error_logger.error('CTP连接断开,正在重连...')
避坑指南:我曾经遇到过日志文件写满磁盘,导致策略进程直接挂掉。从那以后,我强制要求日志目录单独挂载,并且设置磁盘告警阈值。日志很重要,但别让它成为系统的「杀手」。

20.4 自动重启:保证策略7x24小时运行

实盘交易,最怕的就是进程意外退出。网络波动、内存泄漏、系统更新,都可能导致进程挂掉。你需要一个进程守护机制。

20.4.1 使用systemd

Linux自带的systemd是最靠谱的进程管理工具。配置一个service文件,就能实现自动重启。

[Unit]
Description=Base Trade Strategy
After=network.target

[Service]
Type=simple
User=ubuntu
WorkingDirectory=/home/ubuntu/strategy
ExecStart=/usr/bin/python3 /home/ubuntu/strategy/main.py
Restart=always
RestartSec=10
StandardOutput=append:/home/ubuntu/strategy/logs/stdout.log
StandardError=append:/home/ubuntu/strategy/logs/stderr.log

[Install]
WantedBy=multi-user.target

配置好之后,执行:

sudo systemctl enable base_trade
sudo systemctl start base_trade
sudo systemctl status base_trade

这样,即使进程崩溃,systemd会在10秒后自动重启。嗯,这里要注意:RestartSec别设太短,否则频繁重启反而会加重问题。

20.4.2 使用supervisor

如果你不想用systemd,supervisor也是个好选择。它更轻量,配置也更简单。

[program:base_trade]
command=python3 /home/ubuntu/strategy/main.py
directory=/home/ubuntu/strategy
user=ubuntu
autostart=true
autorestart=true
startretries=3
stderr_logfile=/home/ubuntu/strategy/logs/supervisor_err.log
stdout_logfile=/home/ubuntu/strategy/logs/supervisor_out.log
警告:自动重启虽然好,但别盲目依赖。如果策略本身有bug,重启一百次也没用。我建议在重启前,先检查一下错误日志,确认不是代码逻辑问题。

20.5 整体架构图

下面这张图,是我个人常用的实盘部署架构。你看一眼就明白了。

基差交易实盘部署架构 行情源(CTP/交易所) API对接层 策略引擎 日志监控 自动重启(systemd) 数据库(MySQL/Redis) 数据流:行情源 → API对接 → 策略引擎 → 数据库 监控流:API对接/策略引擎 → 日志监控 → 自动重启

你看,整个架构分三层:数据接入层(行情源+API)、策略执行层(策略引擎+数据库)、运维保障层(日志监控+自动重启)。每一层各司其职,出了问题能快速定位。

20.6 总结

实盘部署,说白了就是三个字:稳、快、省。稳是稳定,快是响应快,省是省心省力。

  • 服务器选型,别贪便宜,4核8G起步
  • API对接,用成熟框架,别自己造轮子
  • 日志监控,分级记录,自动轮转
  • 自动重启,systemd或supervisor二选一

嗯,这些经验都是我踩坑踩出来的。你照着做,至少能少走一半弯路。

核心要点:实盘交易,技术只是基础,运维才是关键。一个稳定的部署架构,能让你睡个安稳觉。

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