基于Avellaneda-Stoikov模型的加密货币对做市商算法构建指南
大家好!今天我将带你一步步构建一个适用于USD+/wETH和USD+/cbbtc等加密货币对的做市商算法。我们将采用Avellaneda-Stoikov(A-S)模型,并结合强化学习(PPO)算法实现动态价差优化。听起来很复杂?别担心,我会拆解成易懂的步骤,即使是初学者也能上手。
什么是做市商?为什么需要做市商?
做市商是一种策略,交易者同时挂出买单和卖单,通过买卖价差(spread)获利。在DeFi领域,做市商为市场提供流动性,减少其他参与者的滑点。
想象你是市场上的小贩,总是愿意以略低于市场价买入、略高于市场价卖出。你的利润就是买卖价差。但有个问题:如果价格突然单边波动,你可能会积累过多库存,或者反过来,手里什么都没有。
Avellaneda-Stoikov模型:让数学服务于交易
A-S模型是一种确定做市最优价格的数学方法。它的最大优势在于,不仅考虑当前市场价格,还结合了你的持仓(库存)、市场波动率和风险偏好。
核心公式如下:
δ_a = S_t + (1/γ) * ln(1 + γ/k) + q_t * σ² * T
δ_b = S_t - (1/γ) * ln(1 + γ/k) - q_t * σ² * T
其中:
δ_a和δ_b分别为卖出价和买入价S_t当前市场价格γ风险参数(越大价差越宽)k市场订单到达率q_t当前库存σ波动率T时间窗口
链上交易的特殊性
将算法迁移到链上,会遇到额外挑战:
- 延迟——区块链交易非即时,订单成交前价格可能已变
- Gas费——每笔交易都要支付网络手续费
- AMM/PMM机制——流动性池机制与传统交易所有所不同
下面看看如何在算法中考虑这些因素。
步骤1:环境搭建与数据采集
首先需要搭建环境以获取市场数据。我们用Binance API获取当前价格和订单簿深度。
std::tuple MarketMaker::get_binance_data(const std::string& pair) {
// 实际代码中这里会请求Binance API
// 返回:mid_price, bid, ask, bid_volume, ask_volume
double mid_price = 2000.0;
double bid = mid_price - 1.0;
double ask = mid_price + 1.0;
double bid_volume = 10.0;
double ask_volume = 8.0;
return {mid_price, bid, ask, bid_volume, ask_volume};
}
还需要链上指标,如gas费和网络延迟:
std::pair MarketMaker::get_onchain_metrics() {
// 实际代码中这里会请求以太坊节点
// 返回:gas_price (wei), latency (秒)
return {50e9, 12.0};
}
步骤2:实现基础A-S模型
现在实现A-S模型的价差计算:
std::pair MarketMaker::calculate_spreads(double S_t, double sigma, double k, double q_t) {
// Avellaneda-Stoikov公式
double spread_term = (1.0 / gamma_) * log(1.0 + gamma_ / k);
double inventory_term = q_t * sigma * sigma * T_;
double delta_a = S_t + spread_term + inventory_term; // 卖出价
double delta_b = S_t - spread_term - inventory_term; // 买入价
return {delta_a, delta_b};
}
注意inventory_term。如果你库存为正(手里有很多币),卖出价会降低,买入价会更低,以鼓励卖出、抑制买入。反之亦然。
步骤3:适配链上交易特性
现在要考虑区块链的特殊性。先看延迟:
double MarketMaker::adjust_price_with_latency(double S_t, double sigma, double latency) {
// 用延迟模拟价格的随机变化
double latency_adjustment = utils::normal_dist(0.0, sigma * std::sqrt(latency));
return S_t + latency_adjustment;
}
这里用的是随机游走模型:波动率越大、延迟越长,订单成交前价格变化越大。
再看gas费:
double MarketMaker::calculate_gas_cost(double gas_price, double trade_size) {
const double GAS_LIMIT_PER_ORDER = 100000; // 每单大致gas消耗
return (gas_price * GAS_LIMIT_PER_ORDER * trade_size) / 1e18; // wei转ETH
}
最后,适配PMM池的价差:
std::pair MarketMaker::adjust_spreads_for_pmm(double S_t, double delta_a, double delta_b, double pool_depth) {
// 简化PMM模型:根据池深调整价差
const double MIN_POOL_DEPTH = 10.0;
double depth_factor = std::max(pool_depth, MIN_POOL_DEPTH) / MIN_POOL_DEPTH;
// 池深越大,价差越小
double spread_reduction = 1.0 / std::sqrt(depth_factor);
double mid_price = (delta_a + delta_b) / 2;
double new_delta_a = mid_price + (delta_a - mid_price) * spread_reduction;
double new_delta_b = mid_price - (mid_price - delta_b) * spread_reduction;
return {new_delta_a, new_delta_b};
}
步骤4:库存管理
为了跟踪和管理库存,创建一个简单的类:
class InventoryManager {
public:
InventoryManager() : inventory_(0.0) {}
void update_inventory(double size, bool is_buy) {
inventory_ += is_buy ? size : -size;
}
double get_inventory() const {
return inventory_;
}
private:
double inventory_;
};
步骤5:整合为完整算法
现在将所有组件整合为一个做市商算法:
void MarketMaker::step(double S_t, double sigma, double k, double latency, double gas_cost, double trade_size) {
// 获取当前库存
double current_inventory = inventory_.get_inventory();
// 根据当前市场和库存计算价差
auto [delta_a, delta_b] = calculate_spreads(S_t, sigma, k, current_inventory);
auto [adjusted_delta_a, adjusted_delta_b] = adjust_spreads_for_onchain(S_t, delta_a, delta_b, latency, sigma, gas_cost, trade_size);
// 生成独立市场价格
double market_price = S_t + utils::normal_dist(0.0, sigma);
// 判断是否成交
bool is_buy = (market_price = adjusted_delta_a);
// 执行交易并更新库存
if (is_buy) {
inventory_.update_inventory(trade_size, true);
std::cout reset();
// 执行动作,获取新状态、奖励和done标志
std::tuple, double, bool> step(const std::array& action);
private:
// 获取当前环境状态
std::vector get_state() const;
MarketMaker& mm_;
double current_inventory_;
double current_profit_;
int current_step_;
int max_steps_;
// 当前市场参数
double mid_price_;
double sigma_;
double latency_;
double pool_depth_;
std::mt19937 rng_;
};
环境状态包括当前价格、库存、波动率、网络延迟和池深。动作为买卖价差和数量。
现在实现奖励函数:
double reward = profit_term - inventory_risk - gas_cost;
其中:
profit_term交易利润inventory_risk大库存惩罚(风险)gas_costgas消耗
最后,训练PPO智能体:
void PPOTrainer::train(int episodes) {
for (int ep = 0; ep states;
std::vector actions;
std::vector rewards;
while (true) {
// 策略网络输出动作
auto action_probs = policy_net_->forward(torch::tensor(state));
auto action = action_probs.multinomial(1);
// 环境执行一步
auto [next_state, reward, done] = env_.step(action);
// 保存转移
states.push_back(torch::tensor(state));
actions.push_back(action);
rewards.push_back(reward);
if (done) break;
state = next_state;
}
// PPO策略更新
update_policy(states, actions, rewards);
}
}
步骤7:测试与可视化
为了测试算法,创建一个简单的仿真:
int main() {
// 任务要求T=300秒
MarketMaker mm(0.1, 300.0);
// 波动率历史数据仿真
std::vector prices = {2000.0};
double S_t = 2000.0;
double trade_size = 1.0;
double initial_sigma = 0.05; // 5%波动率
for (int i = 0; i < 300; ++i) {
std::cout << "Step " << i + 1 << ": ";
// 获取数据(模拟)
auto [mid_price, bid_ask] = mm.get_binance_data("USD+/wETH");
auto [gas_cost, latency] = mm.get_onchain_metrics();
// 随机价格波动,模拟真实市场
S_t = mid_price + utils::normal_dist(0.0, mid_price * 0.01);
// 计算波动率
double sigma = mm.calculate_volatility(prices, 5);
if (sigma < 0.01) sigma = initial_sigma;
// 订单到达率(模拟)
double k = 5.0;
mm.step(S_t, sigma, k, latency, gas_cost, trade_size);
// 更新下一步价格
S_t += utils::normal_dist(0.0, S_t * 0.02);
prices.push_back(S_t);
}
return 0;
}
后续展望
算法已完成,但还有很多优化空间:
- 接入真实API:用真实Binance API和以太坊节点替换模拟
- 改进波动率模型:用GARCH等高级模型
- 扩展PPO:增加更多状态和动作参数
- 优化gas:最小化gas消耗的策略
- 多币种策略:扩展到多交易对
结论
我们构建了一个兼顾链上特性、结合A-S模型与现代RL方法的做市商算法。这种方法能适应市场变化,在控制风险的同时最大化收益。
当然,真实交易中还有许多额外因素需考虑,但本算法为后续开发打下了坚实基础。请记住:算法交易不仅要有数学,更要有充分测试、监控和持续优化。
希望本文能帮助你理解做市商原理,并激励你开发自己的算法。祝交易顺利!
引文
@software{soloviov2025marketmakingavellanedastoikov,
author = {Soloviov, Eugen},
title = {基于Avellaneda-Stoikov模型的加密货币对做市商算法构建指南},
year = {2025},
url = {https://marketmaker.cc/zh/blog/post/market-making-avellaneda-stoikov},
version = {0.1.0},
description = {一步步教你如何用Avellaneda-Stoikov模型和PPO算法为USD+/wETH和USD+/cbbtc等加密货币对构建做市商算法。涵盖链上交易特性、库存管理、强化学习训练等。}
}
MarketMaker.cc Team
量化研究与策略