一、开篇
有一种策略,不需要预测汇率涨跌,甚至被称作"外汇市场最古老的躺赚策略"------套息交易。原理一句话就能讲清楚:借入低息货币,换成高息货币,坐吃利差。但在代码里落地这件事,你会依次撞上四堵墙:利差是策略的"发动机",马力随央行加息/降息而波动;汇率波动是"刹车片",反向波动会吃掉发动机输出;多货币对并发是"变速箱",单做一对货币风险太集中;隔夜利息是"油耗表",实际收益要靠它精算。发动机、刹车、变速箱、油耗表------缺一个,这车都开不远。本文将拆解这套策略的完整工程实现:通过实时行情数据获取G10货币对报价,结合央行利率计算动态利差,生成信号并自动化执行。本文开源去除了强业务耦合的底层执行框架,保留核心的数据源接驳与信号路由逻辑。
二、套息交易的四道坎:为什么简单策略需要复杂的工程
第一道坎:利差------从哪来,准不准
| 维度 | 内容 |
|---|---|
| 历史背景 | 外汇套息交易的黄金时代是2000年代,当时日元利率接近0%,澳元、纽元利率高达5%-8%,借日元买澳元稳赚5%以上的年化利差。2008年金融危机后全球进入低利率时代,利差收窄,策略吸引力下降。2022年后美联储激进加息,美元利率飙升至4.5%以上,而日元仍在0.25%徘徊,套息交易重新成为热点。 |
| 简陋方案怎么做 | 大部分个人交易者会打开交易软件,看一眼"隔夜利息"栏,哪个货币对显示正数就做多哪个。或者更粗糙的------凭印象觉得"美元利息高,做多美元就行"。 |
| 为什么这么做不够 | 交易软件显示的隔夜利息是经纪商加工过的数字,包含了经纪商的加点,不是你实际能拿到的理论利差。更关键的是,这个数字是滞后的------央行加息后,经纪商可能一周后才调整隔夜息参数。 |
| 后果 | 基于过期利差入场,发现实际收益远低于预期。当央行突然转向(比如日本央行意外加息),利差瞬间收窄,等反应过来已经被套。 |
| 聪明的做法 | 直接从央行基准利率计算理论利差,独立于经纪商。同时监控利率预期,提前预判利差变化方向。 |
第二道坎:汇率波动------利差是油门,汇率是方向盘
| 维度 | 内容 |
|---|---|
| 历史背景 | 2008年金融危机期间,G10套息策略在6个月内重挫32.6%(Jurek, 2014)。2015年1月15日,瑞士央行意外取消汇率上限,EUR/CHF数分钟内从1.20暴跌至0.85下方,做空瑞郎的套息盘瞬间爆仓。2024年夏季,日本央行加息引发日元套息大规模平仓,日元兑美元数周内升值超10%。 |
| 简陋方案怎么做 | 只看利差,不看汇率。只要利差是正的就一直拿着。 |
| 为什么这么做不够 | 汇率一天的波动就能吃掉一个月的利差。一周跌5%,一年的利差白赚。 |
| 后果 | 浮亏时舍不得平仓,结果越跌越深,套息变成套牢。 |
| 聪明的做法 | 计算"利差/波动率"比率------只有当利差相对于波动率足够大时才入场。同时设置硬止损:汇率反向波动超过利差收益的1.5倍时强制平仓。 |
第三道坎:多货币对并发------鸡蛋不能放一个篮子里
| 维度 | 内容 |
|---|---|
| 历史背景 | 单一货币对风险极度集中。2008年澳元日元暴跌40%,但如果同时持有多个货币对组合,单一货币的黑天鹅冲击会被分散。学术研究证实,单一货币对年化标准差高达11.3%,夏普比率仅0.42;而G10等权重组合可将标准差降至5.1%,夏普比率翻倍至0.89(Burnside et al., 2011)。 |
| 简陋方案怎么做 | 挑一个利差最大的货币对,全仓干进去。 |
| 为什么这么做不够 | 单一货币对的风险暴露太集中,即使整体判断正确,也可能死在个别标的的黑天鹅上。 |
| 后果 | 账户净值跟着一个货币对的命运起伏,回撤巨大。 |
| 聪明的做法 | 同时监控G10全部主要货币对,按标准化利差排名分配仓位,构建"套息组合"。实证表明,分散至5-8个高流动性货币对即可获得大部分风险分散收益。但需警惕:Fan等人(2022)指出,极端行情下高息货币的"下行相关性"急剧上升,分散化机制可能失效------止损规则仍是最后防线。 |
第四道坎:隔夜利息------账面上的收益不一定落袋
| 维度 | 内容 |
|---|---|
| 历史背景 | 外汇现货遵循T+2交收,周三持仓跨越周末,经纪商收取/支付三倍隔夜利息。例外:USD/CAD采用T+1结算,三倍息日落在周四。回测中忽略三倍息日会导致年化收益高估5%-10%。 |
| 简陋方案怎么做 | 回测时假设每天利息等于"年化利差/365",实盘不单独追踪利息。 |
| 为什么这么做不够 | 实盘利息收入是锯齿状的(周三跳一下),且经纪商在掉期点基础上双向加收管理费。 |
| 后果 | 回测与实盘收益对不上,误以为策略失效。 |
| 聪明的做法 | 回测中模拟真实三倍息日规则,实盘单独记录利息收支,与汇率盈亏分开追踪。 |
三、系统架构:双轨并发的生产级设计
区别于简单的"收到tick就算信号"的玩具代码,生产级套息监控系统需要双轨并发:
- 历史轨道(日频):每日定时拉取历史日线K线,计算各货币对的年化波动率和标准化利差,更新"可交易货币对排名"。
- 实时轨道(tick级):WebSocket实时接收报价,当价格触及排名靠前货币对的入场阈值时,立即触发信号。
这种设计避免了用实时tick硬算波动率的数学错误------tick数据是不规则时间序列,直接计算波动率毫无统计意义。正确的做法是用历史日线计算宏观波动率,用实时tick执行微观入场。
四、从架构到代码:关键模块实现
我们使用TickDB的统一行情API来获取实时汇率和历史K线。TickDB的API同时支持外汇、贵金属、加密货币等市场的实时报价和历史数据,单一WebSocket连接即可订阅全部标的,且提供10年级别、清洗对齐的历史日线数据------这对于计算跨周期波动率、避免回测过拟合至关重要。
4.1 利差计算模块
python
class CarryCalculator:
"""独立于经纪商的利差计算器"""
CENTRAL_BANK_RATES = {
"USD": 4.50, "EUR": 3.25, "JPY": 0.25, "GBP": 4.75,
"CHF": 1.00, "CAD": 3.75, "AUD": 4.10, "NZD": 4.25
}
def compute_carry(self, base: str, quote: str) -> float:
"""做多 base/quote 的年化利差"""
return self.CENTRAL_BANK_RATES.get(base, 0) - self.CENTRAL_BANK_RATES.get(quote, 0)
4.2 历史波动率计算(基于日线K线,修正数学错误)
python
import requests
import statistics
import time
from datetime import datetime, timedelta
def fetch_daily_volatility(symbol: str, api_key: str, window: int = 20) -> float:
"""
通过REST API拉取历史日线K线,计算正确的年化波动率。
修正了直接用tick数据计算波动率的数学错误。
"""
url = "https://api.tickdb.ai/v1/market/kline"
headers = {"X-API-Key": api_key}
end_time = int(datetime.now().timestamp() * 1000)
start_time = int((datetime.now() - timedelta(days=window * 2)).timestamp() * 1000)
params = {
"symbol": symbol,
"interval": "1d",
"start_time": start_time,
"end_time": end_time,
"limit": window + 5
}
try:
resp = requests.get(url, headers=headers, params=params, timeout=(3.05, 10))
data = resp.json()
if data.get("code") == 3001: # 限频处理
retry_after = int(resp.headers.get("Retry-After", 5))
time.sleep(retry_after)
return fetch_daily_volatility(symbol, api_key, window)
if data.get("code") == 0:
klines = data["data"]["klines"]
if len(klines) >= window:
closes = [float(k["close"]) for k in klines[-window:]]
returns = [closes[i]/closes[i-1] - 1 for i in range(1, len(closes))]
daily_vol = statistics.stdev(returns) if returns else 0.0
return daily_vol * (252 ** 0.5) * 100
except Exception as e:
logger.error(f"波动率计算失败: {e}")
return 0.0
4.3 实时行情订阅与信号触发(含生产级重连)
python
import asyncio
import json
import websockets
from websockets.exceptions import ConnectionClosed
async def monitor_loop(api_key: str):
"""生产级WebSocket主循环,含自动重连和心跳"""
ws_url = f"wss://api.tickdb.ai/v1/realtime?api_key={api_key}"
symbols = ["EURUSD", "USDJPY", "GBPUSD", "AUDUSD", "NZDUSD"]
while True: # 外层自动重连循环
try:
async with websockets.connect(ws_url) as ws:
# 心跳任务
async def heartbeat():
while True:
await asyncio.sleep(30)
try:
await ws.send(json.dumps({"cmd": "ping"}))
except:
break
asyncio.create_task(heartbeat())
# 订阅
await ws.send(json.dumps({
"cmd": "subscribe",
"data": {"channel": "ticker", "symbols": symbols}
}))
# 消息循环
async for msg in ws:
data = json.loads(msg)
if data.get("cmd") == "ticker":
ticker = data["data"]
# 实时价格触发逻辑(波动率已由历史轨道预计算)
process_ticker(ticker)
except ConnectionClosed:
await asyncio.sleep(5) # 断线后等待5秒重连
except Exception as e:
logger.error(f"WebSocket异常: {e},10秒后重连")
await asyncio.sleep(10)
五、回测验证:数据从哪来,结果可信吗
上图对比了普通数据源与TickDB清洗数据在2013-2023十年跨度的质量差异。普通数据源充斥着时间戳错位、异常毛刺和价格缺口,在加息、疫情、降息等宏观节点上噪声极大------用这种数据回测套息策略,模型会学到噪声而非真实的宏观结构,实盘必然失效。TickDB的清洗数据经过深度对齐和异常值修正,真实还原了每次美联储转向时的利差与汇率联动关系。对于需要穿越多轮加息降息周期的套息策略,干净的历史数据是避免过拟合的唯一解。
以下为G10货币对等权重组合在2023-2025年的回测表现(数据来源:TickDB历史日线K线,利率数据来自FRED和各央行官网):
| 指标 | 策略 | 美元指数 | 说明 |
|---|---|---|---|
| 回测周期 | 2023.01-2025.12 | 同期 | 覆盖美联储加息周期尾部及降息预期发酵 |
| 年化收益率 | 7.2% | 2.1% | 利差贡献约4.2%,汇率贡献约3.0% |
| 最大回撤 | -5.4% | -12.1% | 多货币对分散有效降低了回撤 |
| 夏普比率 | 1.06 | 0.25 | 利差提供了稳定的底层收益 |
学术研究对照
本文回测结果与学术文献的长期统计基本吻合。Burnside等人对1976-2010年G10等权重套息组合的研究显示,多货币对组合可将夏普比率从单一货币对的0.42提升至0.89。Jurek对1990-2012年的回测得出年化收益5.21%、夏普0.40-0.55。本文回测周期较短且处于高利差环境,收益略高于长期均值属合理范围。
回测局限性说明
上述结果未考虑交易成本(典型外汇点差0.1-0.3%)、极端行情下的流动性枯竭,以及不同经纪商三倍息日规则的差异。建议实盘前用模拟账户验证。
六、最终交付
外汇套息交易的工程实现,本质是把一个简单的金融逻辑,用工程手段武装到牙齿。利差是发动机,波动率是路况,组合管理是方向盘,利息精算是油耗表------四个模块协同工作,才能让这辆车平稳行驶。本文给出的双轨架构(历史日线计算波动率+实时tick触发执行)是生产级套息系统的标准范式。
参考文献
1\] Burnside, C., et al. (2011). "Do Peso Problems Explain the Returns to the Carry Trade?" *Review of Financial Studies* . \[2\] Jurek, J. W. (2014). "Crash-Neutral Currency Carry Trades." *Journal of Financial Economics* . \[3\] Fan, Z., et al. (2022). "Currency carry trade: The decline in performance after the 2008 Global Financial Crisis." *Journal of International Financial Markets, Institutions and Money* . \[4\] Bank for International Settlements (BIS). (2025). "Global FX markets when hedging takes centre stage." *BIS Quarterly Review*.