private void RefreshWebSocket()
        {
            this.ws = new WebSocket(this.MakeWebSocketUrl());

            this.ws.OnOpen += (sender, e) => {
                this.Logger.Info("Websocket connected!");
                if (
                    this.provider == QuoteProvider.IEX ||
                    this.provider == QuoteProvider.CRYPTOQUOTE ||
                    this.provider == QuoteProvider.FXCM
                    )

                {
                    this.ready = true;
                    this.RefreshChannels();
                }
            };

            this.ws.OnClose += (sender, e) => {
                this.Logger.Info("Websocket closed!");
                if (!(e.Code == 1001 || e.Code == 1005))
                {
                    this.SelfHeal();
                }
            };

            this.ws.OnError += (sender, e) => {
                this.Logger.Error("Websocket error!", e.Exception);
            };

            this.ws.OnMessage += (sender, e) => {
                IQuote quote = null;
                this.Logger.Info(e.Data);

                JObject reply_message = JObject.Parse(e.Data);
                string  reply_event   = reply_message["event"].ToString();
                if (reply_event == "phx_reply")
                {
                    string payload_status   = reply_message["payload"]["status"].ToString();
                    string payload_response = reply_message["payload"]["response"].ToString();
                    if (payload_status == "error")
                    {
                        Console.WriteLine(payload_response);
                        this.Logger.Error("Websocket error! " + payload_response);
                    }
                }
                else if (this.provider == QuoteProvider.IEX)
                {
                    IexMessage message = JsonConvert.DeserializeObject <IexMessage>(e.Data);
                    if (message.Event == "quote")
                    {
                        quote = message.Payload;
                    }
                }
                else if (this.provider == QuoteProvider.CRYPTOQUOTE)
                {
                    CryptoquoteMessage message = JsonConvert.DeserializeObject <CryptoquoteMessage>(e.Data);
                    if (message.Event == "book_update")
                    {
                        quote = message.Payload.ToObject <CryptoLevel2Message>();
                    }
                    if (message.Event == "ticker")
                    {
                        quote = message.Payload.ToObject <CryptoLevel1Message>();
                    }
                    if (message.Event == "trade")
                    {
                        quote = message.Payload.ToObject <CryptoLevel1Message>();
                    }
                }
                else if (this.provider == QuoteProvider.FXCM)
                {
                    FxcmMessage message = JsonConvert.DeserializeObject <FxcmMessage>(e.Data);
                    if (message.Event == "price_update")
                    {
                        //quote = message.Payload;
                        quote = message.Payload.ToObject <FxcmPrice>();
                    }
                }
                else if (this.provider == QuoteProvider.QUODD)
                {
                    QuoddMessage message = JsonConvert.DeserializeObject <QuoddMessage>(e.Data);
                    if (message.Event == "info")
                    {
                        QuoddInfoData info = message.Data.ToObject <QuoddInfoData>();
                        if (info.Message == "Connected")
                        {
                            this.ready = true;
                            this.RefreshChannels();
                        }
                        else
                        {
                            this.Logger.Info(info.Message);
                        }
                    }
                    else if (message.Event == "quote")
                    {
                        quote = message.Data.ToObject <QuoddBookQuote>();
                    }
                    else if (message.Event == "trade")
                    {
                        quote = message.Data.ToObject <QuoddTradeQuote>();
                    }
                }

                if (quote != null)
                {
                    this.Logger.Debug("Websocket quote received: " + quote);
                    this.queue.Enqueue(quote);
                }
                else
                {
                    this.Logger.Debug("Websocket non-quote message: " + e.Data);
                }
            };

            this.ws.Connect();
        }
        private void RefreshWebSocket()
        {
            this.ws = new WebSocket(this.MakeWebSocketUrl());

            this.ws.OnOpen += (sender, e) => {
                this.Logger.Info("Websocket connected!");
                if (this.provider == QuoteProvider.IEX)
                {
                    this.ready = true;
                    this.RefreshChannels();
                }
            };

            this.ws.OnClose += (sender, e) => {
                this.Logger.Info("Websocket closed!");
                if (!(e.Code == 1001 || e.Code == 1005))
                {
                    this.SelfHeal();
                }
            };

            this.ws.OnError += (sender, e) => {
                this.Logger.Error("Websocket error!", e.Exception);
            };

            this.ws.OnMessage += (sender, e) => {
                IQuote quote = null;
                this.Logger.Info(e.Data);

                if (this.provider == QuoteProvider.IEX)
                {
                    IexMessage message = JsonConvert.DeserializeObject <IexMessage>(e.Data);
                    if (message.Event == "quote")
                    {
                        quote = message.Payload;
                    }
                }
                else if (this.provider == QuoteProvider.QUODD)
                {
                    QuoddMessage message = JsonConvert.DeserializeObject <QuoddMessage>(e.Data);
                    if (message.Event == "info")
                    {
                        QuoddInfoData info = message.Data.ToObject <QuoddInfoData>();
                        if (info.Message == "Connected")
                        {
                            this.ready = true;
                            this.RefreshChannels();
                        }
                        else
                        {
                            this.Logger.Info(info.Message);
                        }
                    }
                    else if (message.Event == "quote")
                    {
                        quote = message.Data.ToObject <QuoddBookQuote>();
                    }
                    else if (message.Event == "trade")
                    {
                        quote = message.Data.ToObject <QuoddTradeQuote>();
                    }
                }

                if (quote != null)
                {
                    this.Logger.Debug("Websocket quote received: " + quote);
                    this.queue.Enqueue(quote);
                }
                else
                {
                    this.Logger.Debug("Websocket non-quote message: " + e.Data);
                }
            };

            this.ws.Connect();
        }