Skip to content

Fix Kraken WS orderbook updates and add checksum support #626

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 26 additions & 11 deletions src/ExchangeSharp/API/Exchanges/Kraken/ExchangeKrakenAPI.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1142,6 +1142,15 @@ private async Task<List<string>> GetMarketSymbolList(string[] marketSymbols)
return marketSymbolList;
}

/// <summary>
/// Handle Kraken "book" channel message: https://docs.kraken.com/websockets/#message-book
/// Note in the "update payload" case there may be varying number of update blocks for
/// bid/ask updates. The last such block has a checksum. The market symbol is always the last item.
/// </summary>
/// <param name="callback"></param>
/// <param name="maxCount"></param>
/// <param name="marketSymbols"></param>
/// <returns></returns>
protected override async Task<IWebSocket> OnGetDeltaOrderBookWebSocketAsync(
Action<ExchangeOrderBook> callback,
int maxCount = 20,
Expand All @@ -1158,15 +1167,16 @@ params string[] marketSymbols
string message = msg.ToStringFromUTF8();
var book = new ExchangeOrderBook();

// SNAPSHOT payload
if (message.Contains("\"as\"") || message.Contains("\"bs\""))
{
// parse delta update
var delta = JsonConvert.DeserializeObject(message) as JArray;
var snapshot = JsonConvert.DeserializeObject(message) as JArray;

book.MarketSymbol = delta[3].ToString();
book.MarketSymbol = snapshot[3].ToString();

var asks = delta[1]["as"].ToList();
var bids = delta[1]["bs"].ToList();
var asks = snapshot[1]["as"].ToList();
var bids = snapshot[1]["bs"].ToList();

var lastUpdatedTime = DateTime.MinValue;

Expand Down Expand Up @@ -1205,16 +1215,16 @@ params string[] marketSymbols
{
// parse delta update
var delta = JsonConvert.DeserializeObject(message) as JArray;
book.MarketSymbol = delta.Last.ToString();

book.MarketSymbol = delta[3].ToString();
var _a = delta.FirstOrDefault(token => token is JObject && token["a"] != null);
var _b = delta.FirstOrDefault(token => token is JObject && token["b"] != null);

var lastUpdatedTime = DateTime.MinValue;

var updates = delta[1];

if (updates["a"] != null)
if (_a != null)
{
var asks = updates["a"].ToList();
var asks = _a["a"].ToList();

foreach (var ask in asks)
{
Expand All @@ -1230,9 +1240,9 @@ params string[] marketSymbols
}
}

if (updates["b"] != null)
if (_b != null)
{
var bids = updates["b"].ToList();
var bids = _b["b"].ToList();

foreach (var bid in bids)
{
Expand All @@ -1251,6 +1261,11 @@ params string[] marketSymbols
book.LastUpdatedUtc = lastUpdatedTime;
book.SequenceId = lastUpdatedTime.Ticks;

//https://docs.kraken.com/websockets/#book-checksum
//"c" belongs to the last update block
var checksum = _b?["c"] ?? _a?["c"];
book.Checksum = (checksum as JValue)?.ToString();

callback(book);
}

Expand Down
15 changes: 11 additions & 4 deletions src/ExchangeSharp/Model/ExchangeOrderBook.cs
Original file line number Diff line number Diff line change
Expand Up @@ -93,10 +93,17 @@ public sealed class ExchangeOrderBook
public SortedDictionary<decimal, ExchangeOrderPrice> Bids { get; } = new SortedDictionary<decimal, ExchangeOrderPrice>(new DescendingComparer<decimal>());

/// <summary>
/// ToString
/// </summary>
/// <returns>String</returns>
public override string ToString()
/// If provided by the exchange, a checksum value that may be used to check orderbook integrity.
/// Otherwise it will be null.
/// This property is not serialized using the ToBinary and FromBinary methods.
/// </summary>
public string Checksum { get; set; }

/// <summary>
/// ToString
/// </summary>
/// <returns>String</returns>
public override string ToString()
{
return string.Format("Book {0}, Asks: {1} ({2:0.00}), Bids: {3} ({4:0.00})", MarketSymbol,
Asks.Count,
Expand Down