Kraken:WebSocket 与 Futures REST 客户端中的四项可靠性修复 | eSeGeCe 博客

Kraken:WebSocket 与 Futures REST 客户端中的四项可靠性修复

· 组件

2026.9 版本中修复了四个独立的 Kraken 缺陷,其中没有一个是仅凭读一遍代码就能发现的那种。每一个都只在特定条件下才会显现:连接时用了错误的端点、请求体从未真正离开本机、重新连接的时机早了几百毫秒。这四处问题现已全部修复,也都值得了解一下,因为每一种失败表现看起来都完全像是另外一回事。

现货客户端在连接 v2 端点时却在使用 v1 协议

TsgcWSAPI_Kraken 构建和解析的是 v1 协议格式:eventpairsubscriptionsubscriptionStatussystemStatus。这套格式的存在是有原因的,该组件上的每一个订阅调用和每一个事件处理程序都是针对它编写的。然而它所连接的端点,默认指向的却是 Kraken 的 v2 WebSocket,而后者使用的是完全不同的格式:methodparamschanneltype。连接本身可以正常建立,不会报错。只是它从未产生过任何一次订阅确认或状态事件,因为服务器返回的数据格式,客户端根本无法解析。

Kraken.Version 现在默认值为 1,组件会据此选择匹配的 v1 端点:

uses
  sgcWebSocket, sgcWebSocket_APIs;

var
  oKraken: TsgcWSAPI_Kraken;
begin
  oKraken := TsgcWSAPI_Kraken.Create(nil);
  oKraken.Client := oClient;
  // Version defaults to 1, matching the event/pair/subscription
  // schema this component already builds and parses.
  oKraken.Kraken.Version := 1;
  oClient.Active := True;
  oKraken.SubscribeTicker('XBT/USD');
end;

如果你的应用之前恰好依赖了旧的、悄悄出错的默认值,那也就意味着它其实从未真正接收到过 v1 事件,因此并不存在什么正常运作中的行为需要保留。如果显式设置 Kraken.Version := 2,仍然会连接到 v2 端点,并启用 RawMessages,在 OnKrakenDataOnMessage 中处理负载,供那些确实是有意针对该格式开发的用户使用。

Futures 订单以 GET 方式发送,请求体被丢弃

这一处问题更隐蔽,也更严重。Kraken Futures REST 客户端上的每一个私有请求,无论是发送订单、编辑订单、取消订单,还是转账、提现,都是以 HTTP GET 方式发出的。已签名的请求体本身构建正确,计算无误,格式化完毕,本已准备就绪,却在最后被丢弃了,因为 GET 请求根本没有地方放置请求体。Kraken 收到的是一个不带任何参数的 GET 请求,要么拒绝,要么直接忽略。这些调用没有一个是真正生效的。

uses
  sgcHTTP_API_Kraken;

var
  oKraken: TsgcHTTP_API_Kraken_Futures_Rest;
  oOrder: TsgcHTTPKrakenFuturesOrder;
begin
  oKraken := TsgcHTTP_API_Kraken_Futures_Rest.Create(nil);
  oKraken.KrakenOptions.ApiKey := 'your_api_key';
  oKraken.KrakenOptions.ApiSecret := 'your_api_secret';

  oOrder := TsgcHTTPKrakenFuturesOrder.Create;
  try
    oOrder.OrderType := kotfLMT;
    oOrder.Symbol := 'PF_XBTUSD';
    oOrder.Side := kosfBuy;
    oOrder.Size := 1;
    oOrder.LimitPrice := 30000;
    // SendOrder now posts through DoHTTP_POST_PRIVATE, body included.
    ShowMessage(oKraken.SendOrder(oOrder));
  finally
    oOrder.Free;
  end;
end;

SendOrderEditOrderByOrderIdEditOrderByCliOrderIdCancelOrderByOrderIdCancelOrderByCliOrderIdTransfer 以及 WithdrawalToSpotWallet 现在全部改走私有 POST 路径,已签名的请求体也会真正附加到请求中。

重新连接后私有订阅丢失

WatchDog 完成重新连接,日志显示这是一次干净利落的重连,可从那一刻起,你的订单、余额和成交频道就这样消失了。没有任何报错,也没有任何日志记录。重连看起来完全成功,因为连接本身确实是成功的,只是断线前发出的那些私有订阅,之后从未被重放过。这个问题在 Kraken 现货和 Kraken Futures 上同样存在,同一批修复中还涉及了其他几个交易所客户端。现在它已被纳入标准的重新订阅重放流程,也就是重连后用来恢复公共市场数据订阅的那条同一路径。

Futures 在会话完成认证前就已重新订阅

一个与此密切相关、且仅出现在 Kraken Futures 上的缺陷:重新连接后,活跃订阅的重放有可能在认证握手真正完成之前就已经开始执行。订阅请求被发往一个 Kraken 尚未完成认证的会话,因此其中的私有订阅遭到拒绝,而客户端同样没有任何迹象能说明原因。现在,重放会先等待认证完成,然后才会重新订阅。

升级说明

这四项修复都可以直接替换使用,不涉及任何 API 迁移。唯一需要留意的行为变化是 Kraken.Version 的默认值,从此前那个实际上不起作用的值改为了 1;如果你的代码已经显式设置了 Version := 2,那么对你来说什么都不会改变。

有疑问、反馈,或需要迁移方面的帮助?联系我们 — 回复你的正是编写这些代码的人。