精华帖子

量化交易中的数学基础

由bqu1vdra创建,最终由bqu1vdra 被浏览 2 用户

量化交易就是”用数学和代码做交易”。价格、收益、风险、回撤……在数学里都可以被抽象成变量和公式。本质上,我们就是在处理一串随机数(收益序列),用统计和概率的工具去度量”好不好”“稳不稳”。

本文将系统介绍量化交易中常用的数学公式和指标,包括:夏普比率Sortino 比率、VaR、CVaR、期望收益均值不利变动(MAE)、回撤、Calmar 比率等。

全文默认你已经知道”买卖股票/期货”这种基本概念,但可以不了解高深数学。

一、从最基础开始:收益率与波动率

收益率的数学定义

收益率

对数收益的好处是:多个时期可以直接相加对应”复利”,数学上很方便。

在量化里,我们把rt视为随机变量R的一次”抽样”,然后用统计量来刻画它:

期望(平均收益):

方差 & 标准差(波动率):

直观解释:

二、风险收益比:夏普比、Sortino 比、Calmar 比

夏普比(Sharpe Ratio) 公式:

其中:

更精确一点:如果我们有一串周期收益 风险收益率为 则样本夏普是:

直观理解:

夏普比 = “每承受 1 单位波动风险,能多赚多少超额收益”。

  • 夏普 ≈ 1:一般
  • 夏普 ≈ 2:很不错
  • 夏普 > 3:通常是非常优秀(也要警惕过拟合)

年化夏普

N是一年交易日数(股票常用 252)

Python 代码示例:计算夏普比

import numpy as np

def sharpe_ratio(returns, risk_free_rate=0.0, periods_per_year=252):
    """
    returns: 一维 np.array 或 pandas.Series,周期收益,例如每日收益
    risk_free_rate: 年化无风险收益率,例如 0.02 代表 2%
    """
    rf_per_period = risk_free_rate / periods_per_year
    excess = returns - rf_per_period
    mean_excess = excess.mean()
    std_excess = excess.std(ddof=1)  # ddof=1 是样本标准差

    if std_excess == 0:
        return np.nan

    sharpe = np.sqrt(periods_per_year) * mean_excess / std_excess
    return sharpe

Sortino 比率:只惩罚”下行波动”的夏普

有些策略,比如趋势策略,向上猛涨和向下暴跌都会带来高波动,但我们只讨厌”跌”,不讨厌”涨”。

Sortino 比率就是只计算”下行波动”的夏普。

公式:

其中:

数学表达:

直观理解:

Sortino 比率 = “每承受 1 单位’亏钱波动’,能赚多少超额收益”。 当策略有很多剧烈上行收益时,Sortino 会比 Sharpe 大,说明”风险其实没那么可怕”。

def sortino_ratio(returns, target_return=0.0, periods_per_year=252):
    """
    target_return: 年化目标收益(通常设为 0 或无风险收益率)
    """
    target_per_period = target_return / periods_per_year
    downside = np.minimum(0, returns - target_per_period)
    downside_std = downside.std(ddof=1)

    if downside_std == 0:
        return np.nan

    mean_return = returns.mean()
    sortino = np.sqrt(periods_per_year) * (mean_return - target_per_period) / abs(downside_std)
    return sortino

回撤与 Calmar 比

回撤(Drawdown)

公式:

更完整地说:

某个时刻的回撤:

全过程的最大回撤(Max Drawdown, MDD):

直观:从账户最高点跌到最低点,跌了多少。

Calmar 比率

公式:

其中: CAGR 公式:

直观解释:

Calmar = “每承受 1 单位最大回撤,能带来多少年化收益”。 它比夏普更关注”路径风险”,尤其适合评估 CTA、对冲基金等长期策略。

Python:最大回撤与 Calmar

import pandas as pd
import numpy as np

def max_drawdown(equity_curve):
    """
    equity_curve: pandas.Series 或 np.array,表示随时间变化的账户净值
    返回:max_dd (负数),drawdown_series(同长度的回撤序列)
    """
    equity = pd.Series(equity_curve)
    running_max = equity.cummax()
    drawdown = equity / running_max - 1.0
    max_dd = drawdown.min()  # 最低(最负)的值

    return max_dd, drawdown

def calmar_ratio(equity_curve, years):
    """
    years: 回测覆盖的年数,例如 3 年数据则 years=3
    """
    equity = np.array(equity_curve)
    cagr = (equity[-1] / equity[0])**(1 / years) - 1
    max_dd, _ = max_drawdown(equity)
    if max_dd == 0:
        return np.nan
    # max_dd 是负数,所以取绝对值
    return cagr / abs(max_dd)

三、尾部风险:VaR 与 CVaR(条件 VaR)

VaR(Value at Risk,风险价值)

数学写法:

直白地说:在给定置信水平 (比如 95%)下,未来某一时间(比如 1 天)最大可能亏损不超过 VaR。 通常表述成:“1 天 95% VaR = 100 万”

含义是:在正常市场下,有 95% 的概率,明天亏损不超过 100 万;也就是有 5% 的概率亏损大于 100 万。

更标准的数学写法(以”亏损L“为正数):

计算方法(常用三种)

  1. 历史模拟法(Historical VaR)

用过去 N 天的真实收益

换算成亏损 取95%分位数

2. 参数法(Parametric VaR,正态假设)

假设收益 对给定置信度alpha ,找正态分布分位点

3. 蒙特卡洛模拟

  • 建立收益或价格的随机模型
  • 模拟很多路径,统计亏损分布

CVaR / ES(条件 VaR、预期损失)

定义:

意思是:

在已经发生”很糟糕”的那部分(损失超过 VaR)的情况下,平均还会亏多少。 相比 VaR 只给出一个”门槛”,CVaR 给你看真正”尾部”的平均损失,监管和风险管理更喜欢用它。

Python:用历史模拟计算 VaR & CVaR

下面把收益视为随机变量,假设我们有一串每日策略收益 returns(单位是百分比或小数形式),资金规模记为 1(方便),则损失就是 -returns。

def var_cvar_from_returns(returns, alpha=0.95):
    """
    returns: np.array 或 pandas.Series,策略的周期收益(如日度收益)
    alpha: 置信水平,例如 0.95 或 0.99
    返回: VaR, CVaR(都以"亏损比例"表示,是正数)
    """
    returns = np.asarray(returns)
    losses = -returns  # 亏损为正

    var = np.quantile(losses, alpha)  # alpha 分位数

    tail_losses = losses[losses >= var]
    if len(tail_losses) == 0:
        cvar = var
    else:
        cvar = tail_losses.mean()

    return var, cvar

例子(概念性的):

假设 var = 0.03,表示 95% VaR 为 3%

cvar = 0.06,表示最糟的 5% 情况下,平均亏损是 6%

四、交易系统视角:期望值(Expectancy)

公式:

变量解释:

更数学化一点,把一笔交易的收益记为随机变量X ,则:

其中:

很多交易书上喜欢把亏损写成正数,于是公式变成:

例子:

则:

平均每笔交易期望赚 0.3%。

即使胜率不高,只要盈亏比足够大,期望仍然为正 —— 这就是趋势交易或”止损让利润奔跑”的数学基础。

Python:根据交易结果计算期望值

假设你有每笔交易的收益列表:

def trade_expectancy(trade_returns):
    """
    trade_returns: 每笔交易的收益,例如 +0.02, -0.01 代表 +2%, -1%
    返回: expectancy, win_rate, avg_win, avg_loss
    """
    trade_returns = np.asarray(trade_returns)
    wins = trade_returns[trade_returns > 0]
    losses = trade_returns[trade_returns < 0]

    win_rate = len(wins) / len(trade_returns) if len(trade_returns) > 0 else np.nan
    avg_win = wins.mean() if len(wins) > 0 else 0.0
    avg_loss = -losses.mean() if len(losses) > 0 else 0.0  # 转成正数表示亏损幅度

    expectancy = win_rate * avg_win - (1 - win_rate) * avg_loss

    return expectancy, win_rate, avg_win, avg_loss

五、单笔交易的风险剖面:MAE

MAE(Mean Adverse Excursion,均值不利变动)

公式:

解释:

直观理解:

MAE = “即使最后赚钱了,中间最难受的时候亏到什么程度”。

用途:

  • 统计历史交易的 MAE,可以帮助你决定止损应该放多远
  • 如果绝大多数盈利交易的 MAE 不超过 2%,那你把止损放 2% 附近可能比较合理 如果止损放得比 MAE 典型值还紧,很多原本可以获利的交易会被”洗出去”
  • 通常也会配套看 MFE(Mean Favorable Excursion,均值有利变动),即持仓期间曾经出现的最大浮盈,用来研究”止盈”和”移动止损”的策略。

Python:一个简化版 MAE 计算示例

真正的 MAE 需要逐笔交易的”内层价格路径”。这里给一个概念性的写法:

def mae_for_trade(prices_during_trade, direction='long'):
    """
    prices_during_trade: 列表,包含从开仓到平仓的价格序列
    direction: 'long' 或 'short'
    """
    entry_price = prices_during_trade[0]
    prices = np.asarray(prices_during_trade)

    if direction == 'long':
        min_price = prices.min()
        mae = entry_price - min_price  # 价格跌了多少
    else:  # 空头
        max_price = prices.max()
        mae = max_price - entry_price  # 价格涨了多少,对空头不利

    return mae

在实盘/回测系统中,会在每笔交易生命周期内实时更新”到目前为止的最低点/最高点”,最终统计所有交易的 MAE 分布。

六、组合层面的数学:相关性、分散化与夏普的提升

虽然前面主要是”单策略/单资产”的指标,但量化交易中非常重要的一块,是组合优化。这里简要说一下最核心的数学思想。

这就是”不要把鸡蛋放在一个篮子里”的数学版本。

七、把这些指标串起来:一个小小的”量化评估流程”

假设你写了一个简单策略,得到一串每日收益 daily_returns,和对应的账户净值 equity_curve。你可以这样评估它:

import numpy as np

periods_per_year = 252
years = len(daily_returns) / periods_per_year

# 1. 年化收益(CAGR)
cagr = (equity_curve[-1] / equity_curve[0])**(1/years) - 1

# 2. 夏普 & Sortino
sharpe = sharpe_ratio(daily_returns, risk_free_rate=0.02, periods_per_year=periods_per_year)
sortino = sortino_ratio(daily_returns, target_return=0.0, periods_per_year=periods_per_year)

# 3. 回撤 & Calmar
max_dd, dd_series = max_drawdown(equity_curve)
calmar = calmar_ratio(equity_curve, years)

# 4. VaR & CVaR(例如 95%)
var95, cvar95 = var_cvar_from_returns(daily_returns, alpha=0.95)

得到这些指标后,你可以这样解读:

  • CAGR 高、夏普 & Sortino 高 —— 策略长期赚钱且”单位风险收益高”
  • MaxDD 不大、Calmar 不错 —— 账户回撤可以承受
  • VaR/CVaR 可用来设置仓位上限,比如”日 VaR 不超过总资金的 2%”
  • 再配合 Expectancy + MAE/MFE 分析单笔交易结构,看止损/止盈是否合理

\

标签

量化交易
{link}