Solana 回测

在真实发生过的链上测试你的策略。

通过你现有的 Yellowstone gRPC 客户端回放 Solana 主网过去 24 小时的数据。相同协议、相同顺序,100μs 精度,按次回放计费。

为什么需要历史回放

主网是唯一诚实的回测。

Devnet 没有 MEV,没有拥塞,没有真实对手。自建模拟器在新程序碰到新边界场景的那一刻起,就开始偏离验证节点的实际行为。

sillage.sh 保留 24 小时的主网数据 —— 每一次账户写入、每一笔交易、每一个区块 —— 并通过你的实盘 bot 已经在使用的同一协议重新传送给你。真实发生过的链,按需提供,按其原本的时序回放。

工作方式

从实时订阅出发的三个步骤。

  1. 01
    将客户端指向 sillage 的端点。

    相同的 Yellowstone gRPC、相同的 SubscribeRequest、相同的过滤器。sillage.sh 作为服务端讲这套协议。

  2. 02
    传入过去 24 小时内的起始 slot。

    数据流从该位置开始,按真实墙钟速度回放,slot 内部顺序保留至 100 微秒精度。

  3. 03
    无需消耗流式订阅即可迭代。

    按次回放计费。你的调参循环需要重跑多少次昨天的窗口都行。

无缝接入

yellowstone-grpc-client,无需改动。

唯一变化的是端点和起始 slot。你的 SubscribeRequest、过滤器与消息处理逻辑保持不变。

回测回放
let mut client = GeyserGrpcClient::build_from_shared(
    "https://replay.sillage.sh",
)?
    .x_token(Some(api_key))?
    .connect()
    .await?;

let req = SubscribeRequest {
    // any slot within the last 24 hours
    from_slot: Some(312_847_201),
    transactions: hashmap! {
        "swaps".into() => SubscribeRequestFilterTransactions {
            account_include: vec![JUPITER_V6.into()],
            ..Default::default()
        },
    },
    ..Default::default()
};

let (_, mut stream) =
    client.subscribe_with_request(Some(req)).await?;

while let Some(msg) = stream.next().await {
    handle(msg?);
}
常见问题

注册之前大家常问的问题。

怎么拿到一个端点?

加入等待列表。前 100 名成员解锁免费 24 小时回放;其余用户将在每批开放时陆续拿到端点。

我需要改客户端代码吗?

不需要。sillage.sh 作为服务端讲 Yellowstone gRPC 协议。把你现有的客户端指向新端点,传入一个起始 slot —— 你的 SubscribeRequest、过滤器与消息处理逻辑都照常工作。

回放的精度如何?

每条消息都携带实时捕获时的时间戳,精度保留到 100 微秒。Slot 内部顺序、传播延迟以及真实网络时间的纹理,都会按其原本的样子回放出来。

为什么是 24 小时窗口?

从当前链顶端向前推,持续滚动。我们服务的工作负载 —— 回测、索引器回填、重组校验 —— 都活在这个窗口里。超出 24 小时,回放就难以为自己付出的成本买单了。

这和我自建 RPC 有什么不同?

RPC 给你的是按需查询;它不会给你一条可重播的、按时间排序的数据流,把昨天发生的每一次账户写入还原出来。sillage.sh 可以,而且走的就是你 bot 已经接好的那个协议。

这和实时 Yellowstone 服务商怎么比?

Helius、Triton、QuickNode 都把链上数据向前 stream 得非常好。但没有一家通过同一协议提供 24 小时的历史回放并按次计费。这正是 sillage.sh 的反向定位。

在真实链上回测。

在我们正式开放前,先拿到一个端点。