예제 #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="cco"></param>
        /// <returns></returns>
        private async ValueTask <bool> mergeCompleteOrder(SCompleteOrders cco)
        {
            var _result = false;

            if (__gmconfig.UsePublishTrade == true)
            {
                await publishTrading(cco);
            }

            if (cco.symbol != null)
            {
                SOrderBooks _qob;
                if (__qOrderBooks.TryGetValue(cco.symbol, out _qob) == true)
                {
                    _qob.stream = cco.stream;

                    if (cco.result != null)
                    {
                        var _settings = GetSettings(cco.symbol);
                        _result = await updateCompleteOrder(_qob, cco, _settings);
                    }
                }
            }

            return(_result);
        }
예제 #2
0
        private async ValueTask publishTrading(SCompleteOrders sco)
        {
            await Task.Delay(0);

            var _json_data = JsonConvert.SerializeObject(sco);

            __trading.Write(this, GMConfig.DealerName, _json_data);
        }
예제 #3
0
        /// <summary>
        /// Fetch array of recent trades data
        /// </summary>
        /// <param name="base_name">The type of trading base-currency of which information you want to query for.</param>
        /// <param name="quote_name">The type of trading quote-currency of which information you want to query for.</param>
        /// <param name="limits">maximum number of items (optional): default 20</param>
        /// <returns></returns>
        public async ValueTask <SCompleteOrders> GetCompleteOrders(string base_name, string quote_name, int limits = 20)
        {
            var _result = new SCompleteOrders
            {
                symbol = $"{quote_name}-{base_name}"
            };

            var _params = new Dictionary <string, object>();
            {
                _params.Add("market", _result.symbol);
                _params.Add("count", limits);
            }

            var _response = await publicClient.CallApiGet2Async($"/trades/ticks", _params);

            if (_response != null)
            {
#if RAWJSON
                _result.rawJson = _response.Content;
#endif
                if (_response.IsSuccessful == true)
                {
                    var _trades = publicClient.DeserializeObject <List <UACompleteOrderItem> >(_response.Content);
                    {
                        _result.sequentialId = _trades.Max(t => t.sequential_id);
                        _result.result       = _trades.Select(t =>
                        {
                            return(new SCompleteOrderItem
                            {
                                timestamp = t.timestamp,
                                sideType = t.sideType,
                                price = t.price,
                                quantity = t.quantity
                            });
                        })
                                               .ToList();
                    }

                    _result.SetSuccess();
                }
                else
                {
                    var _message = publicClient.GetResponseMessage(_response);
                    _result.SetFailure(_message.message);
                }
            }

            return(_result);
        }
예제 #4
0
        private async ValueTask <bool> updateCompleteOrder(SOrderBooks qob, SCompleteOrders cco, Settings settings)
        {
            var _nob = new SOrderBooks
            {
                exchange     = cco.exchange,
                stream       = "difftrade",
                symbol       = cco.symbol,
                action       = cco.action,
                sequentialId = cco.sequentialId,

                result = new SOrderBook
                {
                    timestamp = cco.result.Max(o => o.timestamp),
                    askSumQty = 0,
                    bidSumQty = 0
                }
            };

            lock (__qOrderBooks)
            {
                settings.before_trade_ask_size = qob.result.asks.Sum(o => o.quantity);
                settings.before_trade_bid_size = qob.result.bids.Sum(o => o.quantity);

                foreach (var _t in cco.result.OrderBy(t => t.timestamp))
                {
                    if (settings.last_trade_id >= _t.timestamp)
                    {
                        continue;
                    }

                    settings.last_trade_id = _t.timestamp;

                    var _ask = qob.result.asks.Where(o => o.price == _t.price).SingleOrDefault();
                    if (_ask != null)
                    {
                        if (_ask.quantity <= _t.quantity)
                        {
                            _nob.result.asks.Add(new SOrderBookItem
                            {
                                action   = "delete",
                                id       = _ask.id,
                                price    = _ask.price,
                                quantity = _ask.quantity,
                                amount   = _ask.price * _ask.quantity,
                                count    = 1
                            });

                            _nob.result.askSumQty -= _ask.quantity;

                            _ask.quantity = 0;
                            _ask.amount   = 0;
                        }
                        else
                        {
                            _ask.quantity -= _t.quantity;
                            _ask.amount    = _ask.price * _ask.quantity;

                            _nob.result.asks.Add(new SOrderBookItem
                            {
                                action   = "update",
                                id       = _ask.id,
                                price    = _ask.price,
                                quantity = _ask.quantity,
                                amount   = _ask.price * _ask.quantity,
                                count    = 1
                            });

                            _nob.result.askSumQty += _ask.quantity;
                        }
                    }

                    var _bid = qob.result.bids.Where(o => o.price == _t.price).SingleOrDefault();
                    if (_bid != null)
                    {
                        if (_bid.quantity <= _t.quantity)
                        {
                            _nob.result.bids.Add(new SOrderBookItem
                            {
                                action   = "delete",
                                id       = _bid.id,
                                price    = _bid.price,
                                quantity = _bid.quantity,
                                amount   = _bid.price * _bid.quantity,
                                count    = 1
                            });

                            _nob.result.bidSumQty -= _bid.quantity;

                            _bid.quantity = 0;
                            _bid.amount   = 0;
                        }
                        else
                        {
                            _bid.quantity -= _t.quantity;
                            _bid.amount    = _bid.price * _bid.quantity;

                            _nob.result.bids.Add(new SOrderBookItem
                            {
                                action   = "update",
                                id       = _bid.id,
                                price    = _bid.price,
                                quantity = _bid.quantity,
                                amount   = _bid.price * _bid.quantity,
                                count    = 1
                            });

                            _nob.result.bidSumQty += _bid.quantity;
                        }
                    }

                    //cleanOrderbook(qob, _nob, _t.price);
                }

                qob.sequentialId = _nob.sequentialId;

                qob.result.asks.RemoveAll(o => o.quantity == 0);
                qob.result.bids.RemoveAll(o => o.quantity == 0);
            }

            _nob.result.asks.RemoveAll(o => o.quantity == 0);
            _nob.result.bids.RemoveAll(o => o.quantity == 0);

            if (_nob.result.asks.Count + _nob.result.bids.Count > 0)
            {
                await publishOrderbook(_nob);

                settings.orderbook_count = 0;
                settings.trades_flag     = true;
            }

            return(true);
        }
예제 #5
0
        public async ValueTask Start(CancellationToken cancelToken)
        {
            BTLogger.SNG.WriteO(this, $"processing service start...");

            var _processing = Task.Run(async() =>
            {
                var _last_polling_trade = 0L;

                while (true)
                {
                    try
                    {
                        await Task.Delay(0);

                        var _message = (QMessage)null;
                        if (ReceiveQ.TryDequeue(out _message) == false)
                        {
                            var _cancelled = cancelToken.WaitHandle.WaitOne(0);
                            if (_cancelled == true)
                            {
                                break;
                            }

                            await Task.Delay(10);
                            continue;
                        }

                        if (_message.command == "WS")
                        {
                            if (_message.stream == "trade")
                            {
                                var _w_trade = JsonConvert.DeserializeObject <UWCompleteOrderItem>(_message.payload ?? "");

                                var _s_trade = new SCompleteOrders
                                {
                                    exchange     = _message.exchange,
                                    symbol       = _message.symbol,
                                    stream       = _message.stream,
                                    action       = _message.action,
                                    sequentialId = _w_trade.timestamp,

                                    result = new List <SCompleteOrderItem>
                                    {
                                        new SCompleteOrderItem
                                        {
                                            timestamp = _w_trade.timestamp,
                                            sideType  = _w_trade.sideType,
                                            price     = _w_trade.price,
                                            quantity  = _w_trade.quantity
                                        }
                                    }
                                };

                                if (_s_trade.result.Count() > 0)
                                {
                                    _last_polling_trade = _s_trade.sequentialId;
                                    await mergeCompleteOrder(_s_trade);
                                }
                            }
                            else if (_message.stream == "orderbook")
                            {
                                var _w_orderbook = JsonConvert.DeserializeObject <UWOrderBook>(_message.payload ?? "");

                                var _s_orderbooks = new SOrderBooks
                                {
                                    exchange     = _message.exchange,
                                    symbol       = _message.symbol,
                                    stream       = _message.stream,
                                    action       = _message.action,
                                    sequentialId = _w_orderbook.timestamp,

                                    result = new SOrderBook
                                    {
                                        timestamp = _w_orderbook.timestamp,

                                        askSumQty = _w_orderbook.askSumQty,
                                        bidSumQty = _w_orderbook.bidSumQty,

                                        asks = _w_orderbook.asks,
                                        bids = _w_orderbook.bids
                                    }
                                };

                                await mergeOrderbook(_s_orderbooks);
                            }
                        }
                        else if (_message.command == "AP")
                        {
                            if (_message.stream == "trade")
                            {
                                var _a_trades = JsonConvert.DeserializeObject <List <UACompleteOrderItem> >(_message.payload ?? "");

                                var _s_trade = new SCompleteOrders
                                {
                                    exchange     = _message.exchange,
                                    symbol       = _message.symbol,
                                    stream       = _message.stream,
                                    action       = _message.action,
                                    sequentialId = _a_trades.Max(t => t.timestamp),

                                    result = _a_trades.Where(t => t.timestamp > _last_polling_trade).Select(t =>
                                    {
                                        return(new SCompleteOrderItem
                                        {
                                            timestamp = t.timestamp,
                                            sideType = t.sideType,
                                            price = t.price,
                                            quantity = t.quantity
                                        });
                                    })
                                             .ToList()
                                };

                                if (_s_trade.result.Count() > 0)
                                {
                                    _last_polling_trade = _s_trade.sequentialId;
                                    await mergeCompleteOrder(_s_trade);
                                }
                            }
                            else if (_message.stream == "orderbook")
                            {
                                var _a_orderbooks = JsonConvert.DeserializeObject <List <UAOrderBook> >(_message.payload ?? "");

                                var _timestamp = _a_orderbooks.Max(o => o.timestamp);
                                var _asks      = _a_orderbooks[0].asks;
                                var _bids      = _a_orderbooks[0].bids;

                                var _s_orderbooks = new SOrderBooks
                                {
                                    exchange     = _message.exchange,
                                    symbol       = _message.symbol,
                                    stream       = _message.stream,
                                    action       = _message.action,
                                    sequentialId = _a_orderbooks.Max(t => t.timestamp),

                                    result = new SOrderBook
                                    {
                                        timestamp = _timestamp,

                                        askSumQty = _asks.Sum(o => o.quantity),
                                        bidSumQty = _bids.Sum(o => o.quantity),

                                        asks = _asks,
                                        bids = _bids
                                    }
                                };

                                await mergeOrderbook(_s_orderbooks);
                            }
                            else if (_message.stream == "ticker")
                            {
                                var _a_ticker_data = JsonConvert.DeserializeObject <List <UAOrderBook> >(_message.payload ?? "");

                                await publishTicker(new STickers
                                {
                                    exchange     = _message.exchange,
                                    symbol       = _message.symbol,
                                    stream       = _message.stream,
                                    action       = _message.action,
                                    sequentialId = _message.sequentialId,

                                    timestamp    = _a_ticker_data.Max(o => o.timestamp),
                                    totalAskSize = _a_ticker_data.Sum(o => o.askSumQty),
                                    totalBidSize = _a_ticker_data.Sum(o => o.bidSumQty),

                                    result = _a_ticker_data.Select(o =>
                                    {
                                        var _ask = o.asks.OrderBy(a => a.price).First();
                                        var _bid = o.bids.OrderBy(a => a.price).Last();

                                        return(new STickerItem
                                        {
                                            askPrice = _ask.price,
                                            askSize = _ask.quantity,
                                            bidPrice = _bid.price,
                                            bidSize = _bid.quantity
                                        });
                                    })
                                             .ToList()
                                });
                            }
                        }
                        else if (_message.command == "SS")
                        {
                            await snapshotOrderbook(_message.symbol);
                        }
#if DEBUG
                        else
                        {
                            BTLogger.SNG.WriteO(this, _message.payload);
                        }
#endif
                        if (cancelToken.IsCancellationRequested == true)
                        {
                            break;
                        }
                    }
                    catch (TaskCanceledException)
                    {
                    }
                    catch (Exception ex)
                    {
                        BTLogger.SNG.WriteX(this, ex.ToString());
                    }
                }
            },
                                       cancelToken
                                       );

            await Task.WhenAll(_processing);

            BTLogger.SNG.WriteO(this, $"processing service stop...");
        }
예제 #6
0
        public async ValueTask Start(CancellationToken cancelToken)
        {
            BMLogger.SNG.WriteO(this, $"processing service start...");

            var _processing = Task.Run(async() =>
            {
                var _last_polling_trade = 0L;

                while (true)
                {
                    try
                    {
                        await Task.Delay(0);

                        var _message = (QMessage)null;
                        if (ReceiveQ.TryDequeue(out _message) == false)
                        {
                            var _cancelled = cancelToken.WaitHandle.WaitOne(0);
                            if (_cancelled == true)
                            {
                                break;
                            }

                            await Task.Delay(10);
                            continue;
                        }

                        if (_message.command == "WS")
                        {
                            if (_message.stream == "order")
                            {
                                var _w_orders = JsonConvert.DeserializeObject <List <BMyOrderItem> >(_message.payload ?? "");

                                var _s_order = new SMyOrders
                                {
                                    exchange     = _message.exchange,
                                    stream       = _message.stream,
                                    symbol       = _message.symbol,
                                    action       = _message.action,
                                    sequentialId = _w_orders.Max(t => t.timestamp),

                                    result = _w_orders.Select(o =>
                                    {
                                        return(new SMyOrderItem
                                        {
                                            orderId = o.orderId ?? "",
                                            symbol = o.symbol ?? "",
                                            sideType = o.sideType,

                                            timestamp = o.timestamp,

                                            makerType = MakerType.Maker,
                                            orderStatus = o.orderStatus,
                                            orderType = o.orderType,

                                            quantity = o.quantity,
                                            price = o.price,
                                            amount = o.amount,
                                            filled = o.filled,
                                            remaining = o.remaining,

                                            workingIndicator = o.workingIndicator,
                                            avgPx = o.avgPx.HasValue ? o.avgPx.Value : 0,
                                            fee = o.fee,
                                            cost = o.cost,

                                            count = o.count
                                        });
                                    })
                                             .ToList <ISMyOrderItem>()
                                };

                                await mergeMyOrder(_s_order);
                            }
                            else if (_message.stream == "trade")
                            {
                                var _w_trades = JsonConvert.DeserializeObject <List <BCompleteOrderItem> >(_message.payload ?? "");

                                var _s_trade = new SCompleteOrders
                                {
                                    exchange     = _message.exchange,
                                    stream       = _message.stream,
                                    symbol       = _message.symbol,
                                    action       = _message.action,
                                    sequentialId = _w_trades.Max(t => t.timestamp),

                                    result = _w_trades.Select(t =>
                                    {
                                        return(new SCompleteOrderItem
                                        {
                                            timestamp = t.timestamp,
                                            sideType = t.sideType,
                                            price = t.price,
                                            quantity = t.quantity
                                        });
                                    })
                                             .ToList()
                                };

                                if (_s_trade.result.Count() > 0)
                                {
                                    _last_polling_trade = _s_trade.sequentialId;
                                    await mergeCompleteOrder(_s_trade);
                                }
                            }
                            else if (_message.stream == "orderbook")
                            {
                                var _w_orderbooks = JsonConvert.DeserializeObject <List <BOrderBookItem> >(_message.payload ?? "");

                                var _timestamp = CUnixTime.NowMilli;
                                var _asks      = _w_orderbooks.Where(o => o.sideType == SideType.Ask);
                                var _bids      = _w_orderbooks.Where(o => o.sideType == SideType.Bid);

                                var _s_orderbooks = new SOrderBooks
                                {
                                    exchange     = _message.exchange,
                                    symbol       = _message.symbol,
                                    stream       = _message.stream,
                                    action       = _message.action,
                                    sequentialId = _timestamp,

                                    result = new SOrderBook
                                    {
                                        timestamp = _timestamp,
                                        askSumQty = _asks.Sum(o => o.quantity),
                                        bidSumQty = _bids.Sum(o => o.quantity),

                                        asks = _asks.Select(o =>
                                        {
                                            return(new SOrderBookItem
                                            {
                                                quantity = o.quantity,
                                                price = o.price,
                                                amount = o.quantity * o.price,
                                                id = o.id,
                                                count = 1
                                            });
                                        }).ToList(),
                                        bids = _bids.Select(o =>
                                        {
                                            return(new SOrderBookItem
                                            {
                                                quantity = o.quantity,
                                                price = o.price,
                                                amount = o.quantity * o.price,
                                                id = o.id,
                                                count = 1
                                            });
                                        }).ToList()
                                    }
                                };

                                await mergeOrderbook(_s_orderbooks);
                            }
                        }
                        else if (_message.command == "AP")
                        {
                            if (_message.stream == "order")
                            {
                                var _w_orders = JsonConvert.DeserializeObject <List <BMyOrderItem> >(_message.payload ?? "");

                                var _s_order = new SMyOrders
                                {
                                    exchange     = _message.exchange,
                                    stream       = _message.stream,
                                    symbol       = _message.symbol,
                                    action       = _message.action,
                                    sequentialId = _w_orders.Max(t => t.timestamp),

                                    result = _w_orders.Select(o =>
                                    {
                                        return(new SMyOrderItem
                                        {
                                            orderId = o.orderId ?? "",
                                            symbol = o.symbol ?? "",
                                            sideType = o.sideType,

                                            timestamp = o.timestamp,

                                            makerType = o.makerType,
                                            orderStatus = o.orderStatus,
                                            orderType = o.orderType,

                                            quantity = o.quantity,
                                            price = o.price,
                                            amount = o.amount,
                                            filled = o.filled,
                                            remaining = o.remaining,

                                            workingIndicator = o.workingIndicator,
                                            avgPx = o.avgPx.HasValue ? o.avgPx.Value : 0,
                                            fee = o.fee,
                                            cost = o.cost,

                                            count = o.count
                                        });
                                    })
                                             .ToList <ISMyOrderItem>()
                                };

                                await mergeMyOrder(_s_order);
                            }
                            else if (_message.stream == "trade")
                            {
                                var _a_trades = JsonConvert.DeserializeObject <List <BCompleteOrderItem> >(_message.payload ?? "");

                                var _s_trade = new SCompleteOrders
                                {
                                    exchange     = _message.exchange,
                                    symbol       = _message.symbol,
                                    stream       = _message.stream,
                                    action       = _message.action,
                                    sequentialId = _a_trades.Max(t => t.timestamp),

                                    result = _a_trades.Where(t => t.timestamp > _last_polling_trade).Select(t =>
                                    {
                                        return(new SCompleteOrderItem
                                        {
                                            timestamp = t.timestamp,
                                            sideType = t.sideType,
                                            price = t.price,
                                            quantity = t.quantity
                                        });
                                    })
                                             .ToList()
                                };

                                if (_s_trade.result.Count() > 0)
                                {
                                    _last_polling_trade = _s_trade.sequentialId;
                                    await mergeCompleteOrder(_s_trade);
                                }
                            }
                            else if (_message.stream == "orderbook")
                            {
                                var _a_orderbooks = JsonConvert.DeserializeObject <List <BOrderBookItem> >(_message.payload ?? "");

                                var _timestamp = CUnixTime.NowMilli;
                                var _asks      = _a_orderbooks.Where(o => o.sideType == SideType.Ask);
                                var _bids      = _a_orderbooks.Where(o => o.sideType == SideType.Bid);

                                var _s_orderbooks = new SOrderBooks
                                {
                                    exchange     = _message.exchange,
                                    symbol       = _message.symbol,
                                    stream       = _message.stream,
                                    action       = _message.action,
                                    sequentialId = _timestamp,

                                    result = new SOrderBook
                                    {
                                        timestamp = _timestamp,
                                        askSumQty = _asks.Sum(o => o.quantity),
                                        bidSumQty = _bids.Sum(o => o.quantity),

                                        asks = _asks.Select(o =>
                                        {
                                            return(new SOrderBookItem
                                            {
                                                quantity = o.quantity,
                                                price = o.price,
                                                amount = o.quantity * o.price,
                                                id = o.id,
                                                count = 1
                                            });
                                        }).ToList(),
                                        bids = _bids.Select(o =>
                                        {
                                            return(new SOrderBookItem
                                            {
                                                quantity = o.quantity,
                                                price = o.price,
                                                amount = o.quantity * o.price,
                                                id = o.id,
                                                count = 1
                                            });
                                        }).ToList()
                                    }
                                };

                                await mergeOrderbook(_s_orderbooks);
                            }
                        }
                        else if (_message.command == "SS")
                        {
                            await snapshotOrderbook(_message.exchange);
                        }
#if DEBUG
                        else
                        {
                            BMLogger.SNG.WriteO(this, _message.payload);
                        }
#endif
                        if (cancelToken.IsCancellationRequested == true)
                        {
                            break;
                        }
                    }
                    catch (TaskCanceledException)
                    {
                    }
                    catch (Exception ex)
                    {
                        BMLogger.SNG.WriteX(this, ex.ToString());
                    }
                }
            },
                                       cancelToken
                                       );

            await Task.WhenAll(_processing);

            BMLogger.SNG.WriteO(this, $"processing service stop...");
        }
예제 #7
0
        public async ValueTask Start(CancellationTokenSource cancelTokenSource)
        {
            DRLogger.SNG.WriteO(this, $"processing service start...");

            var _processing = Task.Run(async() =>
            {
                var _last_polling_trade = 0L;
                var _orderbook_size     = 25;

                while (true)
                {
                    try
                    {
                        await Task.Delay(0);

                        var _message = (QMessage)null;
                        if (ReceiveQ.TryDequeue(out _message) == false)
                        {
                            var _cancelled = cancelTokenSource.Token.WaitHandle.WaitOne(0);
                            if (_cancelled == true)
                            {
                                break;
                            }

                            await Task.Delay(10);
                            continue;
                        }

                        if (_message.command == "WS")
                        {
                            if (_message.stream == "trade")
                            {
                                var _w_trades = JsonConvert.DeserializeObject <List <DCompleteOrderItem> >(_message.payload ?? "");

                                var _s_trades = new SCompleteOrders
                                {
                                    exchange = _message.exchange,   // deribit
                                    stream   = _message.stream,     // trade
                                    symbol   = _message.symbol,     // BTC-PERPETUAL
                                    action   = _message.action,     // pushing

                                    sequentialId = _w_trades.Max(t => t.timestamp),

                                    result = _w_trades.Select(t =>
                                    {
                                        return(new SCompleteOrderItem
                                        {
                                            timestamp = t.timestamp,
                                            sideType = t.sideType,
                                            price = t.price,
                                            quantity = t.quantity
                                        });
                                    })
                                             .ToList()
                                };

                                if (_s_trades.result.Count() > 0)
                                {
                                    _last_polling_trade = _s_trades.sequentialId;
                                    await mergeTrades(_s_trades);
                                }
                            }
                            else if (_message.stream == "orderbook")
                            {
                                var _w_orderbooks = JsonConvert.DeserializeObject <DWsOrderBook>(_message.payload ?? "");
                                if (_w_orderbooks.asks.Count() > 0 || _w_orderbooks.bids.Count() > 0)
                                {
                                    var _timestamp = _w_orderbooks.timestamp;

                                    var _s_orderbooks = new SOrderBooks
                                    {
                                        exchange = _message.exchange,       // deribit
                                        symbol   = _message.symbol,         // BTC-PERPETUAL
                                        stream   = _message.stream,         // orderbook
                                        action   = _w_orderbooks.type,      // snapshot, change

                                        sequentialId = _timestamp,

                                        result = new SOrderBook
                                        {
                                            timestamp = _timestamp,

                                            askSumQty = 0,
                                            bidSumQty = 0,

                                            asks = new List <SOrderBookItem>(),
                                            bids = new List <SOrderBookItem>()
                                        }
                                    };

                                    foreach (var _a in _w_orderbooks.asks.OrderBy(a => a[1]).Take(_orderbook_size))
                                    {
                                        _s_orderbooks.result.asks.Add(new SOrderBookItem
                                        {
                                            action   = _a[0].ToString(),
                                            quantity = Convert.ToDecimal(_a[2]),
                                            price    = Convert.ToDecimal(_a[1]),
                                            amount   = 0,
                                            id       = 0,
                                            count    = 1
                                        });
                                    }

                                    foreach (var _b in _w_orderbooks.bids.OrderByDescending(b => b[1]).Take(_orderbook_size))
                                    {
                                        _s_orderbooks.result.bids.Add(new SOrderBookItem
                                        {
                                            action   = _b[0].ToString(),
                                            quantity = Convert.ToDecimal(_b[2]),
                                            price    = Convert.ToDecimal(_b[1]),
                                            amount   = 0,
                                            id       = 0,
                                            count    = 1
                                        });
                                    }

                                    await mergeOrderbooks(_s_orderbooks);
                                }
                            }
                        }
                        else if (_message.command == "AP")
                        {
                            if (_message.stream == "trade")
                            {
                                var _a_trades = JsonConvert.DeserializeObject <DRResults <DCompleteOrders> >(_message.payload ?? "");
                                if (_a_trades.result.trades.Count > 0)
                                {
                                    var _s_trades = new SCompleteOrders
                                    {
                                        exchange = _message.exchange,   // deribit
                                        symbol   = _message.symbol,     // BTC-PERPETUAL
                                        stream   = _message.stream,     // trade
                                        action   = _message.action,     // polling

                                        sequentialId = _a_trades.result.trades.Max(t => t.timestamp),

                                        result = _a_trades.result.trades.Where(t => t.timestamp > _last_polling_trade).Select(t =>
                                        {
                                            return(new SCompleteOrderItem
                                            {
                                                timestamp = t.timestamp,
                                                sideType = t.sideType,
                                                price = t.price,
                                                quantity = t.quantity
                                            });
                                        })
                                                 .ToList()
                                    };

                                    if (_s_trades.result.Count() > 0)
                                    {
                                        _last_polling_trade = _s_trades.sequentialId;
                                        await mergeTrades(_s_trades);
                                    }
                                }
                            }
                            else if (_message.stream == "orderbook")
                            {
                                var _a_orderbooks = JsonConvert.DeserializeObject <DRResults <DOrderBook> >(_message.payload ?? "");
                                if (_a_orderbooks.result.asks.Count > 0 || _a_orderbooks.result.bids.Count > 0)
                                {
                                    var _timestamp = _a_orderbooks.result.timestamp;

                                    var _s_orderbooks = new SOrderBooks
                                    {
                                        exchange = _message.exchange,   // deribit
                                        symbol   = _message.symbol,     // BTC-PERPETUAL
                                        stream   = _message.stream,     // orderbook
                                        action   = _message.action,     // polling

                                        sequentialId = _timestamp,

                                        result = new SOrderBook
                                        {
                                            timestamp = _timestamp,

                                            askSumQty = 0,
                                            bidSumQty = 0,

                                            asks = _a_orderbooks.result.asks.Select(o =>
                                            {
                                                return(new SOrderBookItem
                                                {
                                                    quantity = o.quantity,
                                                    price = o.price,
                                                    amount = 0,
                                                    id = 0,
                                                    count = 1
                                                });
                                            })
                                                   .ToList(),

                                            bids = _a_orderbooks.result.bids.Select(o =>
                                            {
                                                return(new SOrderBookItem
                                                {
                                                    quantity = o.quantity,
                                                    price = o.price,
                                                    amount = 0,
                                                    id = 0,
                                                    count = 1
                                                });
                                            })
                                                   .ToList()
                                        }
                                    };

                                    await mergeOrderbooks(_s_orderbooks);
                                }
                            }
                        }
                        else if (_message.command == "SS")
                        {
                            await snapshotOrderbook(_message.exchange);
                        }
#if DEBUG
                        else
                        {
                            DRLogger.SNG.WriteO(this, _message.payload);
                        }
#endif
                        if (cancelTokenSource.Token.IsCancellationRequested == true)
                        {
                            break;
                        }
                    }
                    catch (TaskCanceledException)
                    {
                    }
                    catch (Exception ex)
                    {
                        DRLogger.SNG.WriteX(this, ex.ToString());
                    }
                }
            },
                                       cancelTokenSource.Token
                                       );

            await Task.WhenAll(_processing);

            DRLogger.SNG.WriteO(this, $"processing service stop...");
        }