Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/321.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/visual-studio-code/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# GDAX/Coinbase API Level3 orderbook-跳过消息_C#_Websocket_Coinbase Api_Gdax Api_Websocket Sharp - Fatal编程技术网

C# GDAX/Coinbase API Level3 orderbook-跳过消息

C# GDAX/Coinbase API Level3 orderbook-跳过消息,c#,websocket,coinbase-api,gdax-api,websocket-sharp,C#,Websocket,Coinbase Api,Gdax Api,Websocket Sharp,我正在使用gdaxapi尝试创建完整的LEVEL3订单的副本 我用WebSocketSharp实现了一个非常简单的实现,我基本上就是这样做的 private readonly WebSocket _webSocket = new WebSocket("wss://ws-feed.gdax.com"); _webSocket.OnMessage += WebSocket_OnMessage; _webSocket.Connect(); _webSocket.Send(JsonConvert.Se

我正在使用gdaxapi尝试创建完整的LEVEL3订单的副本

我用WebSocketSharp实现了一个非常简单的实现,我基本上就是这样做的

private readonly WebSocket _webSocket = new WebSocket("wss://ws-feed.gdax.com");

_webSocket.OnMessage += WebSocket_OnMessage;
_webSocket.Connect();
_webSocket.Send(JsonConvert.SerializeObject(new BeginSubscriptionMessage()));

private void WebSocket_OnMessage(object sender, MessageEventArgs e)
{
    var message = JsonConvert.DeserializeObject<BaseMessage>(e.Data);
    switch (message.Type)
    {   
        case "match": //A trade occurred between two orders. 
            MatchMessage matchMessage = JsonConvert.DeserializeObject<MatchMessage>(e.Data);
            _receivedMatchQueue.Enqueue(matchMessage);
            break;
        case "received": //A valid order has been received and is now active. This message is emitted for every single valid order as soon as the matching engine receives it whether it fills immediately or not.
            ReceivedMessage receivedMessage = JsonConvert.DeserializeObject<ReceivedMessage>(e.Data);
            _receivedMessageQueue.Enqueue(receivedMessage);
            break;
        case "open": //The order is now open on the order book. This message will only be sent for orders which are not fully filled immediately. remaining_size will indicate how much of the order is unfilled and going on the book.
            OpenMessage openMessage = JsonConvert.DeserializeObject<OpenMessage>(e.Data);
            _receivedOpenQueue.Enqueue(openMessage);
            break;
        case "done": //The order is no longer on the order book. Sent for all orders for which there was a received message. This message can result from an order being canceled or filled. 
            DoneMessage doneMessage = JsonConvert.DeserializeObject<DoneMessage>(e.Data);
            _receivedDoneQueue.Enqueue(doneMessage);
            break;
        case "change": //Existing order has been changed
            ChangeMessage changeMessage = JsonConvert.DeserializeObject<ChangeMessage>(e.Data);
            _receivedChangeQueue.Enqueue(changeMessage);
            break;
        case "activate": //Stop order placed
            //Console.WriteLine("Stop Order Placed");
            //ActivateMessage activateMessage = JsonConvert.DeserializeObject<ActivateMessage>(e.Data);

            break;
        case "subscriptions":
            break;
        case "ticker":
            TickerMessage tickerMessage = JsonConvert.DeserializeObject<TickerMessage>(e.Data);
            _receivedTickerQueue.Enqueue(tickerMessage);
            break;
        case "l2update":

            break;
    }
}
我试着在Azure上测试这个,只是为了确保这不是我终端的带宽限制,并且结果基本相似

因此,如果消息被删除,如何使用“完整”websocket流构建完整的“实时”订单簿?我可以安全地忽略它们吗?还是我只是清除了孤立的值


任何做过类似工作的人的任何建议都将不胜感激。

最有可能的消息不会被删除,您只是对这些序列号代表的“序列”有错误的印象

如api文件所述

大多数提要消息都包含序列号。序列号是 为每种产品增加整数值,每增加一条新消息 比前一个序列号正好是一个序列号

因此,每个频道对每个产品都有单独的序列号(如
ETH-USD
),而不是每种消息类型(如“打开”或“接收”)。假设您订阅了“完整”渠道,用于产品
ETH-USD
ETH-EUR
。那么您应该期望这样的序列:

receive `ETH-EUR` X
open `ETH-EUR` X + 1
receive `ETH-USD` Y
done `ETH-EUR` X + 2
open `ETH-USD` Y + 1
对于完整频道,消息类型为:已接收、打开、完成、匹配、更改、激活(请注意,股票代码消息属于不同的频道,因此有单独的顺序)。因此,为了确保不跳过任何消息,您需要跟踪所有这些消息类型,并确保您收到的最后一个序列号比每个产品的新序列号正好少1个(如果您订阅了多个产品)

证明代码:

class Program {
    private static readonly WebSocket _webSocket = new WebSocket("wss://ws-feed.gdax.com");
    private static long _lastSequence = 0;
    private static readonly HashSet<string> _expectedTypes = new HashSet<string>(
        new[] { "received", "open", "done", "match", "change", "activate" });

    static void Main(string[] args) {
        var subMsg = "{\"type\": \"subscribe\",\"product_ids\": [\"ETH-USD\"],\"channels\": [\"full\"]}";
        _webSocket.OnMessage += WebSocket_OnMessage;
        _webSocket.Connect();
        _webSocket.Send(subMsg);
        Console.ReadKey();
    }        

    private static void WebSocket_OnMessage(object sender, MessageEventArgs e) {
        var message = JsonConvert.DeserializeObject<BaseMessage>(e.Data);
        if (_expectedTypes.Contains(message.Type)) {
            lock (typeof(Program)) {
                if (_lastSequence == 0)
                    _lastSequence = message.Sequence;
                else {
                    if (message.Sequence > _lastSequence + 1) {
                        Debugger.Break(); // never hits, so nothing is dropped
                    }
                    _lastSequence = message.Sequence;
                }
            }
        }
    }
}

public class BaseMessage {
    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("product_id")]
    public string ProductId { get; set; }

    [JsonProperty("sequence")]
    public long Sequence { get; set; }
}
类程序{
私有静态只读WebSocket _WebSocket=新WebSocket(“wss://ws-feed.gdax.com");
私有静态长_lastSequence=0;
私有静态只读哈希集_expectedTypes=新哈希集(
新[]{“已接收”、“打开”、“完成”、“匹配”、“更改”、“激活”});
静态void Main(字符串[]参数){
var subMsg=“{\'type\':\'subscribe\',\'product\'uids\':[\'ETH-USD\'],\'channels\':[\'full\']}”;
_webSocket.OnMessage+=webSocket_OnMessage;
_Connect();
_webSocket.Send(subMsg);
Console.ReadKey();
}        
私有静态void WebSocket_OnMessage(对象发送者,MessageEventArgs e){
var message=JsonConvert.DeserializeObject(如数据);
if(_expectedTypes.Contains(message.Type)){
锁(类型(程序)){
如果(_lastSequence==0)
_lastSequence=message.Sequence;
否则{
如果(message.Sequence>\u lastSequence+1){
Debugger.Break();//从不命中,因此不会删除任何内容
}
_lastSequence=message.Sequence;
}
}
}
}
}
公共类基消息{
[JsonProperty(“类型”)]
公共字符串类型{get;set;}
[JsonProperty(“产品id”)]
公共字符串ProductId{get;set;}
[JsonProperty(“序列”)]
公共长序列{get;set;}
}

非常感谢您,您完全正确。我在概念上误解了消息序列是如何工作的,并假设它是“每个订阅频道”(即股票代码、匹配等),而事实显然并非如此。让我大吃一惊的是,有时消息会“无序”,所以我没有立即得到我看到的序列之间的关联。
class Program {
    private static readonly WebSocket _webSocket = new WebSocket("wss://ws-feed.gdax.com");
    private static long _lastSequence = 0;
    private static readonly HashSet<string> _expectedTypes = new HashSet<string>(
        new[] { "received", "open", "done", "match", "change", "activate" });

    static void Main(string[] args) {
        var subMsg = "{\"type\": \"subscribe\",\"product_ids\": [\"ETH-USD\"],\"channels\": [\"full\"]}";
        _webSocket.OnMessage += WebSocket_OnMessage;
        _webSocket.Connect();
        _webSocket.Send(subMsg);
        Console.ReadKey();
    }        

    private static void WebSocket_OnMessage(object sender, MessageEventArgs e) {
        var message = JsonConvert.DeserializeObject<BaseMessage>(e.Data);
        if (_expectedTypes.Contains(message.Type)) {
            lock (typeof(Program)) {
                if (_lastSequence == 0)
                    _lastSequence = message.Sequence;
                else {
                    if (message.Sequence > _lastSequence + 1) {
                        Debugger.Break(); // never hits, so nothing is dropped
                    }
                    _lastSequence = message.Sequence;
                }
            }
        }
    }
}

public class BaseMessage {
    [JsonProperty("type")]
    public string Type { get; set; }

    [JsonProperty("product_id")]
    public string ProductId { get; set; }

    [JsonProperty("sequence")]
    public long Sequence { get; set; }
}