Skip to content

订单执行与做市策略

概述

订单执行 (Order Execution) 和做市 (Market Making) 是微观市场结构 (Market Microstructure) 中的核心问题。最优执行的目标是在给定时间内完成大额订单交易,同时最小化市场冲击 (Market Impact)。做市策略则通过持续提供买卖报价赚取价差收益。本文介绍经典的 Almgren-Chriss 模型、TWAP/VWAP 算法,以及基于强化学习的做市与库存管理方法。

最优执行:Almgren-Chriss 模型

问题设定

交易者需在时间 \([0, T]\) 内卖出 \(X\) 股股票。将时间离散化为 \(N\) 个区间,第 \(k\) 期的交易量为 \(n_k\),剩余持仓为 \(x_k\)

\[x_0 = X, \quad x_k = x_{k-1} - n_k, \quad x_N = 0\]

市场冲击模型

价格演变包含永久性冲击 (Permanent Impact) 和临时性冲击 (Temporary Impact):

\[S_k = S_{k-1} - g(n_k/\tau) + \sigma \sqrt{\tau} \xi_k\]
\[\tilde{S}_k = S_k - h(n_k/\tau)\]

其中:

  • \(g(v) = \gamma v\) 为永久性冲击函数(线性模型)
  • \(h(v) = \eta v\) 为临时性冲击函数
  • \(\sigma\) 为价格波动率
  • \(\xi_k \sim \mathcal{N}(0, 1)\)

执行成本与风险

期望执行成本 (Implementation Shortfall):

\[\mathbb{E}[\text{IS}] = \frac{1}{2}\gamma X^2 + \eta \sum_{k=1}^{N} \frac{n_k^2}{\tau}\]

执行风险 (Variance):

\[\text{Var}[\text{IS}] = \sigma^2 \tau \sum_{k=0}^{N-1} x_k^2\]

均值-方差最优策略

\[\min_{\{n_k\}} \; \mathbb{E}[\text{IS}] + \lambda \cdot \text{Var}[\text{IS}]\]

最优交易轨迹为双曲线形式:

\[x_k^* = X \cdot \frac{\sinh\left(\kappa(T - t_k)\right)}{\sinh(\kappa T)}\]

其中 \(\kappa = \sqrt{\frac{\lambda \sigma^2}{\eta/\tau}}\) 为紧迫性参数 (Urgency Parameter)。

风险厌恶与执行速度

\(\lambda \rightarrow 0\)(风险中性)时,最优策略趋近于 TWAP(匀速交易)。当 \(\lambda \rightarrow \infty\)(极度风险厌恶)时,策略趋近于立即执行。\(\lambda\) 的选择反映了交易者对执行成本与时间风险之间的权衡。

TWAP 与 VWAP

TWAP (Time-Weighted Average Price)

在交易窗口内均匀分配交易量:

\[n_k = \frac{X}{N}, \quad \forall k\]

TWAP 简单稳健,但忽略了市场流动性的时变特征。

VWAP (Volume-Weighted Average Price)

按历史成交量分布分配交易量:

\[n_k = X \cdot \frac{\hat{V}_k}{\sum_{j=1}^{N} \hat{V}_j}\]

其中 \(\hat{V}_k\) 为第 \(k\) 期的预期成交量。

def vwap_schedule(total_qty, volume_profile, n_slices):
    """生成 VWAP 交易计划"""
    # volume_profile: 日内成交量占比分布
    total_volume = sum(volume_profile[:n_slices])
    schedule = []
    for k in range(n_slices):
        slice_qty = total_qty * volume_profile[k] / total_volume
        schedule.append({
            'slice': k,
            'target_qty': round(slice_qty),
            'pct_of_total': volume_profile[k] / total_volume
        })
    return schedule

def adaptive_vwap(target_qty, actual_volume, predicted_volume,
                  completed_qty, remaining_slices):
    """自适应 VWAP: 根据实时成交量调整"""
    remaining_qty = target_qty - completed_qty
    volume_ratio = actual_volume / predicted_volume
    # 如果实际成交量高于预期,可以更激进
    adaptive_rate = remaining_qty / remaining_slices * volume_ratio
    return min(adaptive_rate, remaining_qty)

TWAP vs VWAP 的选择

场景 推荐算法 原因
大盘蓝筹 VWAP 流动性充足,可跟踪市场节奏
小市值股 TWAP 成交量分布不稳定
紧急交易 IS 最优 最小化 Implementation Shortfall
隐蔽交易 随机化 TWAP 降低信息泄漏风险

RL-based 做市策略

做市商的角色

做市商 (Market Maker) 持续在买卖两侧挂单,赚取买卖价差 (Bid-Ask Spread):

\[\text{PnL}_t = (p_{\text{ask}} - p_{\text{bid}}) \cdot q_t - \text{Adverse Selection Cost}\]

核心挑战是逆向选择 (Adverse Selection):知情交易者的订单会导致做市商持续亏损。

Avellaneda-Stoikov 模型

经典的做市模型给出最优报价偏移:

\[\delta_{\text{bid}} = \delta_{\text{ask}} = \frac{1}{\gamma}\ln\left(1 + \frac{\gamma}{\kappa}\right) + \frac{\gamma \sigma^2 (T-t)}{2}\]
\[r_{\text{bid}} = s_t - \delta_{\text{bid}} + q_t \cdot \gamma \sigma^2 (T-t)\]
\[r_{\text{ask}} = s_t + \delta_{\text{ask}} + q_t \cdot \gamma \sigma^2 (T-t)\]

其中 \(q_t\) 为库存 (Inventory),\(\gamma\) 为风险厌恶系数。库存偏斜项使报价随库存调整。

RL 做市 Agent

class MarketMakingEnv:
    def __init__(self, mid_price_process, max_inventory=100):
        self.mid_price = mid_price_process
        self.max_inventory = max_inventory
        self.inventory = 0
        self.pnl = 0
        self.t = 0

    def get_state(self):
        return np.array([
            self.mid_price[self.t],
            self.inventory / self.max_inventory,
            self.get_spread(),
            self.get_volatility(),
            self.get_order_flow_imbalance(),
            (self.T - self.t) / self.T  # 剩余时间比例
        ])

    def step(self, action):
        """
        action: (bid_offset, ask_offset, bid_size, ask_size)
        """
        bid_offset, ask_offset, bid_size, ask_size = action
        bid_price = self.mid_price[self.t] - bid_offset
        ask_price = self.mid_price[self.t] + ask_offset

        # 模拟订单成交
        bid_filled = self.simulate_fill(bid_price, 'buy', bid_size)
        ask_filled = self.simulate_fill(ask_price, 'sell', ask_size)

        # 更新库存和 PnL
        self.inventory += bid_filled - ask_filled
        self.pnl += ask_filled * ask_price - bid_filled * bid_price

        # 库存标记市值变化
        mid_change = self.mid_price[self.t+1] - self.mid_price[self.t]
        self.pnl += self.inventory * mid_change

        # 奖励: PnL 变化 - 库存风险惩罚
        reward = (ask_filled * ask_price - bid_filled * bid_price
                  + self.inventory * mid_change
                  - self.phi * self.inventory ** 2)

        self.t += 1
        done = self.t >= self.T - 1
        return self.get_state(), reward, done

class RLMarketMaker:
    def __init__(self, state_dim=6, action_dim=4):
        self.actor = ContinuousActor(state_dim, action_dim)
        self.critic = Critic(state_dim)
        # 使用 SAC 算法处理连续动作空间
        self.sac_optimizer = SACOptimizer(self.actor, self.critic)

    def get_quotes(self, state):
        action = self.actor.sample(state)
        bid_offset = torch.sigmoid(action[0]) * self.max_spread
        ask_offset = torch.sigmoid(action[1]) * self.max_spread
        bid_size = torch.sigmoid(action[2]) * self.max_size
        ask_size = torch.sigmoid(action[3]) * self.max_size
        return bid_offset, ask_offset, bid_size, ask_size

库存管理 (Inventory Management)

做市策略的核心是库存风险管理。库存过高暴露于方向性风险,过低则丧失做市机会。

库存惩罚

在奖励函数中加入库存惩罚项:

\[r_t = \text{Spread PnL}_t - \phi \cdot q_t^2 - \psi \cdot |q_t| \cdot \sigma_t\]

其中 \(\phi\) 控制库存惩罚的强度,\(\psi\) 在高波动率时加大库存惩罚。

动态库存限制

\[|q_t| \leq Q_{\max} \cdot \left(1 - \frac{t}{T}\right)^\alpha\]

随时间推移逐步收紧库存限制,确保交易结束时库存趋近于零。

做市策略的极端风险

在市场剧烈波动时(如"闪崩"事件),做市商可能积累巨额单边库存并遭受重大损失。RL 做市 Agent 的训练数据中必须包含极端市场情景,并设置硬性库存上限 (Hard Inventory Limit) 和自动对冲 (Auto-hedging) 机制。

小结

订单执行和做市是微观市场结构中的经典优化问题。Almgren-Chriss 模型提供了执行优化的解析框架,TWAP/VWAP 是工业界的主力算法。RL 的引入使得策略能够适应实时市场状态——自适应地调整交易节奏和报价参数。然而,RL 做市策略的部署需要极高的工程可靠性和风险控制能力,模拟到实盘的迁移 (Sim-to-Real Transfer) 仍是核心挑战。