#trading #kraken #async #request-response #tokio #api-bindings #crypto

kraken-async-rs

为Kraken Pro API提供的异步REST和WSS客户端

7个版本 (4个破坏性版本)

0.4.1 2024年7月31日
0.4.0 2024年7月29日
0.3.0 2024年7月20日
0.2.0 2024年7月1日
0.0.1 2024年3月19日

#988 in 神奇豆子

Download history 4/week @ 2024-04-23 128/week @ 2024-04-30 26/week @ 2024-05-07 1/week @ 2024-05-14 4/week @ 2024-05-21 183/week @ 2024-05-28 13/week @ 2024-06-04 3/week @ 2024-06-11 1/week @ 2024-06-18 114/week @ 2024-06-25 84/week @ 2024-07-02 106/week @ 2024-07-16 97/week @ 2024-07-23 198/week @ 2024-07-30

每月401次下载

MIT许可证

350KB
8K SLoC

Kraken-Async-Rs

badge License: MIT codecov

对Kraken Pro交易API(v1和v2 WebSocket)的完整[^3]封装,使用异步Rust编写。

在未查阅Kraken APIWebSocket文档的情况下,无法使用Kraken-Async-Rs。接下来,应参考新的API文档:Kraken REST APIKraken Websockets V1Kraken Websockets V2

由于这些细节和相互依赖[^1]不在本库的控制范围内,且可能会发生变化,因此并未在库中记录或强制执行。

示例:调用公开端点

公开端点调用非常简单,只需创建一个客户端对象并等待请求。由于不需要API密钥,使用StaticSecretsProvider提供了一个空的、静态的集合,其值为空的&str。有关导入的完整示例,请参阅完整示例

#[tokio::main]
async fn main() {
    // credentials aren't needed for public endpoints
    let secrets_provider: Arc<Mutex<Box<dyn SecretsProvider>>> = Box::new(Arc::new(Mutex::new(StaticSecretsProvider::new("", ""))));
    let nonce_provider: Arc<Mutex<Box<dyn NonceProvider>>> =
        Arc::new(Mutex::new(Box::new(IncreasingNonceProvider::new())));
    let mut client = CoreKrakenClient::new(secrets_provider, nonce_provider);

    let request = TradableAssetPairsRequest::builder()
        .pair(Pairs::new(vec!["BTCUSD".to_string()]))
        .build();

    let open_orders_response = client.get_tradable_asset_pairs(&request).await;

    // Note that Kraken will return assets in their own naming scheme, e.g. a request for
    // "BTCUSD" will return as "XXBTZUSD"
    // For a reasonable understanding of their mappings, see: https://gist.github.com/brendano257/975a395d73a6d7bb53e53d292534d6af
    if let Ok(ResultErrorResponse {
                  result: Some(tradable_assets),
                  ..
              }) = open_orders_response
    {
        for (asset, details) in tradable_assets {
            println!("{asset}: {details:?}")
        }
    }
}

示例:调用私有端点

私有端点调用需要有效的凭证,凭证可以通过任何方式静态提供,或者通过一个 EnvSecretsProvider 提供,它会自动加载项目目录中的 .env 文件,并从本地环境中检索指定的键。有关导入的完整示例,请参阅 此处

#[tokio::main]
async fn main() {
    // note that this will fail if you don't have your key and secret set to these env vars
    // eg `export KRAKEN_KEY="YOUR-API-KEY"`, ...
    let secrets_provider: Arc<Mutex<Box<dyn SecretsProvider>>> = Box::new(Arc::new(Mutex::new(StaticSecretsProvider::new("", ""))));
    let nonce_provider: Arc<Mutex<Box<dyn NonceProvider>>> =
        Arc::new(Mutex::new(Box::new(IncreasingNonceProvider::new())));
    let mut client = CoreKrakenClient::new(secrets_provider, nonce_provider);

    let request = OpenOrdersRequest::builder().build();

    let open_orders_response = client.get_open_orders(&request).await;

    if let Ok(ResultErrorResponse {
                  result: Some(open_orders),
                  ..
              }) = open_orders_response
    {
        for (order_id, order) in open_orders.open {
            println!("{order_id}: {order:?}")
        }
    }
}

示例:监听 Websockets(V2)

公共 Websockets 不需要认证,因此只需创建一个 v2::KrakenWSSClient,连接,并发送任何订阅方法,然后等待返回的 KrakenMessageStream.next() 方法。

您还可以访问带有日志和导入的 完整示例

#[tokio::main]
async fn main() {
    let mut client = KrakenWSSClient::new();
    let mut kraken_stream = client.connect::<WssMessage>().await.unwrap();

    let ohlc_params = OhlcSubscription::new(vec!["ETH/USD".into()], 60);
    let subscription = Message::new_subscription(ohlc_params, 0);

    let result = kraken_stream.send(&subscription).await;
    assert!(result.is_ok());

    while let Ok(Some(message)) = timeout(Duration::from_secs(10), kraken_stream.next()).await {
        if let Ok(response) = message {
            println!("{:?}", response);
        } else {
            println!("Message failed: {:?}", message);
        }
    }
}

示例:监听 Websockets(V1 - 已弃用)

Kraken 发布了具有简化数据类型、新功能以及更多标准化文档的 V2 版本 API。如果可能,应使用 V2 API,因为 V1 端点将得到维护但不会得到改进。

公共 Websockets 不需要认证,因此只需创建一个 KrakenWSSClient,连接,并发送任何订阅方法,然后等待返回的 KrakenMessageStream.next() 方法。

您还可以访问带有日志和导入的 完整示例

#[tokio::main]
async fn main() {
    let subscriptions = [
        // many of these have additional options that could be set
        Subscription::new_trades_subscription(),
        Subscription::new_book_subscription(Some(10)), // use a depth of 10 for simplicity
        Subscription::new_ticker_subscription(),
        Subscription::new_ohlc_subscription(None),
        Subscription::new_spread_subscription(),
    ];

    let mut client = KrakenWSSClient::new();
    let mut kraken_stream: KrakenMessageStream<PublicMessage> = client.connect().await.unwrap();

    for subscription in subscriptions {
        // for more valid pairs for WSS requests, consult the `ws_name` field of `get_tradable_asset_pairs`
        let subscribe_message =
            SubscribeMessage::new(0, Some(vec!["XBT/USD".into()]), subscription);
        kraken_stream.subscribe(&subscribe_message).await.expect("failed to subscribe");
    }

    while let Some(message) = kraken_stream.next().await {
        println!("{:?}", message.unwrap());
    }
}

请求详情

具有超过 1 或 2 个参数的请求通常会给一个结构体,而不是有多个参数的方法。通过使用标记字段为必填的 simple-builder 包,builder 实现强制执行必填参数,确保它们必须在 .builder() 调用中提供。任何可选参数都可以使用流畅的 API 添加。

例如,深度(订单簿)端点需要一个对,但可以可选地接受一个 count 参数,用于返回每侧的出价/要价数量。然后构建器表现得如下

let request = OrderbookRequest::builder("ETHUSD".to_string())
        .count(500)
        .build();

响应详情

尽可能遵守 Kraken 的响应格式,除非某些情况会对可用性造成严重限制。反序列化使用 serde,并保留大多数数据类型不变,除了将字符串解析为 rust_decimal::Decimal,以及使用许多值有明确文档的枚举。大多数 i64 String/RFC3339 和 f64 时间戳保持不变。目标是提供一个优秀的基库,供他人构建,而不会通过解析所有内容来限制下游使用并降低整体性能。如果您正在开发通用交易算法,您应该编写一个可以在这种解析之上进行操作的通用抽象。

如果您不同意或对解析、格式化或任何其他问题或受阻用例有意见,请提供您的问题的清晰示例!

安全

  • 使用 secrecy 包防止在请求和响应对象中意外记录 WebSocket 令牌。
  • 默认情况下,功能 debug-inbounddebug-outbound 是关闭的,当启用时 将记录令牌,因为它们将传入和传出消息作为字符串记录,这些字符串不容易被删除。

其他细节

  • 参数和响应值通常从 Kraken API 字段重命名为符合 Rust 的命名约定或提高可读性[^2]

贡献

这是一个独立开发的大型项目,尽管我尽了最大努力,但无疑还是遗漏了一些东西。请提供任何错误、可用性问题或改进建议的清晰示例!

[^1]:例如,AddOrder 端点需要 "Good-'til-Date" 订单同时指定 endtm 值。类似的情况有很多,并且 由这个库强制执行。

[^2]:例如,包括 refid -> ref_idendtm -> end_timeofs -> order_flags(或 offset...),vol_exec -> executed_volumeqty -> quantity 等等。

[^3]:在完成本库初始版本的后期,添加了一些关于 NFT 交易的 20+ 个端点。我正在考虑添加它,但没有实际用途。如果你有用途或想要贡献,请告知。

依赖项

~11–23MB
~366K SLoC