Пример #1
0
        /// <summary>
        /// Subscribes tickers for multiple symbols
        /// </summary>
        /// <param name="symbols">Trading pair symbols. Maximum Length: 100 symbols</param>
        /// <param name="onData">The handler for updates</param>
        public async Task <CallResult <UpdateSubscription> > Spot_SubscribeToTickers_Async(IEnumerable <string> symbols, Action <OkexSpotTicker> onData)
        {
            // To List
            var symbolList = symbols.ToList();

            // Check Point
            if (symbolList.Count > 100)
            {
                throw new ArgumentException("Symbols can contain maximum 100 elements");
            }

            for (int i = 0; i < symbolList.Count; i++)
            {
                symbolList[i] = symbolList[i].ValidateSymbol();
            }

            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexSpotTicker> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var tickerList = new List <string>();

            for (int i = 0; i < symbolList.Count; i++)
            {
                tickerList.Add($"spot/ticker:{symbolList[i]}");
            }

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, tickerList);

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }
        /// <summary>
        /// Retrieve advance algo orders (includes iceberg order and twap order). Data will be pushed when first subscribed. Data will be pushed when triggered by events such as placing/canceling order.
        /// </summary>
        /// <param name="instrumentType">Instrument Type</param>
        /// <param name="instrumentId">Instrument ID</param>
        /// <param name="underlying">Underlying</param>
        /// <param name="onData">On Data Handler</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > SubscribeToAdvanceAlgoOrderUpdates_Async(
            OkexInstrumentType instrumentType,
            string instrumentId,
            string underlying,
            Action <OkexAlgoOrder> onData)
        {
            var internalHandler = new Action <DataEvent <OkexSocketUpdateResponse <IEnumerable <OkexAlgoOrder> > > >(data =>
            {
                foreach (var d in data.Data.Data)
                {
                    onData(d);
                }
            });


            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, new OkexSocketRequestArgument
            {
                Channel        = "algo-advance",
                InstrumentId   = instrumentId,
                InstrumentType = instrumentType,
                Underlying     = underlying,
            });

            return(await SubscribeAsync(request, null, true, internalHandler).ConfigureAwait(false));
        }
Пример #3
0
        /// <summary>
        /// Depth-Five: The latest 5 entries of the market depth data is snapshooted and pushed every 100 milliseconds.
        /// Depth-All: After subscription, 400 entries of market depth data of the order book will first be pushed. Subsequently every 100 milliseconds we will snapshot and push entries that have changed during this time.
        /// Depth-TickByTick: The 400 entries of market depth data of the order book that return for the first time after subscription will be pushed; subsequently as long as there's any change of market depth data of the order book, the changes will be pushed tick by tick. Subsequently as long as there's any change of market depth data of the order book, the changes will be pushed tick by tick.
        /// </summary>
        /// <param name="instrument">Trading pair symbol</param>
        /// <param name="depth">Order Book Depth</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Options_SubscribeToOrderBook_Async(string instrument, OkexOrderBookDepth depth, Action <OkexOptionsOrderBook> onData)
        {
            var internalHandler = new Action <OkexOptionsOrderBookUpdate>(data =>
            {
                foreach (var d in data.Data)
                {
                    d.Symbol   = instrument.ToUpper(OkexGlobals.OkexCultureInfo);
                    d.DataType = depth == OkexOrderBookDepth.Depth5 ? OkexOrderBookDataType.DepthTop5 : data.DataType;
                    onData(d);
                }
            });

            var channel = "depth";

            if (depth == OkexOrderBookDepth.Depth5)
            {
                channel = "depth5";
            }
            else if (depth == OkexOrderBookDepth.Depth400)
            {
                channel = "depth";
            }
            else if (depth == OkexOrderBookDepth.TickByTick)
            {
                channel = "depth_l2_tbt";
            }
            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"option/{channel}:{instrument}");

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #4
0
        /// <summary>
        /// Depth-Five: Back to the previous five entries of depth data,This data is snapshot data per 100 milliseconds.For every 100 milliseconds, we will snapshot and push 5 entries of market depth data of the current order book.
        /// Depth-All: After subscription, 400 entries of market depth data of the order book will first be pushed. Subsequently every 100 milliseconds we will snapshot and push entries that have changed during this time.
        /// </summary>
        /// <param name="symbol">Trading pair symbol</param>
        /// <param name="depth">Order Book Depth</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public async Task <CallResult <UpdateSubscription> > Spot_SubscribeToTrades_Async(string symbol, OkexSpotOrderBookDepth depth, Action <OkexSpotOrderBook> onData)
        {
            symbol = symbol.ValidateSymbol();
            symbol = symbol.ToUpper(OkexGlobals.OkexCultureInfo);
            var internalHandler = new Action <OkexSocketOrderBookUpdate>(data =>
            {
                foreach (var d in data.Data)
                {
                    d.Symbol   = symbol;
                    d.DataType = depth == OkexSpotOrderBookDepth.Depth5 ? OkexSpotOrderBookDataType.DepthTop5 : data.DataType;
                    onData(d);
                }
            });

            var channel = "depth";

            if (depth == OkexSpotOrderBookDepth.Depth5)
            {
                channel = "depth5";
            }
            else if (depth == OkexSpotOrderBookDepth.Depth400)
            {
                channel = "depth";
            }
            else if (depth == OkexSpotOrderBookDepth.TickByTick)
            {
                channel = "depth_l2_tbt";
            }
            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"spot/{channel}:{symbol}");

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #5
0
        /// <summary>
        /// Get the status of system maintenance and push when the system maintenance status changes. First subscription: "Push the latest change data"; every time there is a state change, push the changed content
        /// </summary>
        /// <param name="onData">On Data Handler</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > SubscribeToSystemStatus_Async(Action <OkexStatus> onData)
        {
            var internalHandler = new Action <DataEvent <OkexSocketUpdateResponse <IEnumerable <OkexStatus> > > >(data =>
            {
                foreach (var d in data.Data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, "status", string.Empty, string.Empty);

            return(await SubscribeAsync(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #6
0
        /// <summary>
        /// Retrieve detailed pricing information of all OPTION contracts. Data will be pushed at once.
        /// </summary>
        /// <param name="underlying">Underlying</param>
        /// <param name="onData">On Data Handler</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > SubscribeToOptionSummary_Async(string underlying, Action <OkexOptionSummary> onData)
        {
            var internalHandler = new Action <DataEvent <OkexSocketUpdateResponse <IEnumerable <OkexOptionSummary> > > >(data =>
            {
                foreach (var d in data.Data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, "opt-summary", string.Empty, underlying);

            return(await SubscribeAsync(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #7
0
        /// <summary>
        /// Retrieve the open interest. Data will by pushed every 3 seconds.
        /// </summary>
        /// <param name="intrumentId">Instrument ID</param>
        /// <param name="onData">On Data Handler</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > SubscribeToInterests_Async(string intrumentId, Action <OkexOpenInterest> onData)
        {
            var internalHandler = new Action <DataEvent <OkexSocketUpdateResponse <IEnumerable <OkexOpenInterest> > > >(data =>
            {
                foreach (var d in data.Data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, "open-interest", intrumentId);

            return(await SubscribeAsync(request, null, false, internalHandler).ConfigureAwait(false));
        }
        /// <summary>
        /// Get the information of holding positions of a contract. require login
        /// </summary>
        /// <param name="symbol">Instrument Id</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Futures_SubscribeToPositions_Async(string symbol, Action <OkexFuturesPosition> onData)
        {
            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexFuturesPosition> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"futures/position:{symbol}");

            return(await Subscribe(request, null, true, internalHandler).ConfigureAwait(false));
        }
        /// <summary>
        /// This channel is a public index channel that includes the k-lines and tickers for indices. It can be taken reference to for futures and spot trading.
        /// The indices currently available are all USD-denominated. The asset list includes: BTC, LTC, ETH, ETC, XRP, EOS, BTG.
        /// Get the public index ticker data
        /// </summary>
        /// <param name="symbol">The trading pair</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Index_SubscribeToTicker_Async(string symbol, Action <OkexIndexTicker> onData)
        {
            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexIndexTicker> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"index/ticker:{symbol}");

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #10
0
        /// <summary>
        /// Retrieve the estimated delivery/exercise price of FUTURES contracts and OPTION.
        /// Only the estimated delivery/exercise price will be pushed an hour before delivery/exercise, and will be pushed if there is any price change.
        /// </summary>
        /// <param name="instrumentType">Instrument Type</param>
        /// <param name="underlying">Underlying</param>
        /// <param name="onData">On Data Handler</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > SubscribeToEstimatedPrice_Async(OkexInstrumentType instrumentType, string underlying, Action <OkexEstimatedPrice> onData)
        {
            var internalHandler = new Action <DataEvent <OkexSocketUpdateResponse <IEnumerable <OkexEstimatedPrice> > > >(data =>
            {
                foreach (var d in data.Data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, "estimated-price", instrumentType, underlying);

            return(await SubscribeAsync(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #11
0
        /// <summary>
        /// Retrieves the order details of the account. Requires login.
        /// </summary>
        /// <param name="underlying">Underlying Symbol</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Options_SubscribeToOrders_Async(string underlying, Action <OkexOptionsOrder> onData)
        {
            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexOptionsOrder> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"option/order:{underlying}");

            return(await Subscribe(request, null, true, internalHandler).ConfigureAwait(false));
        }
Пример #12
0
        /// <summary>
        /// Get the filled orders data,it will be pushed when there is transaction data.
        /// </summary>
        /// <param name="instrument">Trading pair symbol</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Options_SubscribeToTrades_Async(string instrument, Action <OkexOptionsTrade> onData)
        {
            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexOptionsTrade> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"option/trade:{instrument}");

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #13
0
        /// <summary>
        /// Retrieve account information. Data will be pushed when triggered by events such as placing/canceling order, and will also be pushed in regular interval according to subscription granularity.
        /// </summary>
        /// <param name="onData">On Data Handler</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > SubscribeToAccountUpdates_Async(Action <OkexAccountBalance> onData)
        {
            var internalHandler = new Action <DataEvent <OkexSocketUpdateResponse <IEnumerable <OkexAccountBalance> > > >(data =>
            {
                foreach (var d in data.Data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, "account");

            return(await SubscribeAsync(request, null, true, internalHandler).ConfigureAwait(false));
        }
Пример #14
0
        /// <summary>
        /// Retrieve the user's margin account information (login authentication required).
        /// </summary>
        /// <param name="symbol">Instrument Id</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Margin_SubscribeToBalance_Async(string symbol, Action <OkexMarginBalance> onData)
        {
            symbol = symbol.ValidateSymbol();

            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexMarginBalance> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"spot/margin_account:{symbol}");

            return(await Subscribe(request, null, true, internalHandler).ConfigureAwait(false));
        }
Пример #15
0
        /// <summary>
        /// Get the filled orders data
        /// </summary>
        /// <param name="symbol">Trading pair symbol</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public async Task <CallResult <UpdateSubscription> > Spot_SubscribeToTrades_Async(string symbol, Action <OkexSpotTrade> onData)
        {
            symbol = symbol.ValidateSymbol();

            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexSpotTrade> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"spot/trade:{symbol}");

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #16
0
        /// <summary>
        /// Retrieve market data summary of all contracts of an underlying index for options trading. Does not require login.
        /// It will push multiple messages for multiple contracts, and only one contract per message.
        /// </summary>
        /// <param name="underlying">The underlying index that the contract is based upon, e.g. BTC-USD.</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Options_SubscribeToMarketData_Async(string underlying, Action <OkexOptionsMarketData> onData)
        {
            underlying = underlying.ValidateSymbol();

            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexOptionsMarketData> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"option/summary:{underlying}");

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #17
0
        /// <summary>
        /// Retrieve the candlesticks data of the index. Data will be pushed every 500 ms.
        /// </summary>
        /// <param name="intrumentId">Instrument ID</param>
        /// <param name="period">Period</param>
        /// <param name="onData">On Data Handler</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > SubscribeToIndexCandlesticks_Async(string intrumentId, OkexPeriod period, Action <OkexCandlestick> onData)
        {
            var internalHandler = new Action <DataEvent <OkexSocketUpdateResponse <IEnumerable <OkexCandlestick> > > >(data =>
            {
                foreach (var d in data.Data.Data)
                {
                    d.Instrument = intrumentId;
                    onData(d);
                }
            });

            var jc      = JsonConvert.SerializeObject(period, new PeriodConverter(false));
            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, "index-candle" + jc, intrumentId);

            return(await SubscribeAsync(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #18
0
        public async Task <CallResult <UpdateSubscription> > User_Spot_SubscribeToBalance_Async(string currency, Action <OkexSpotBalance> onData)
        {
            currency = currency.ValidateCurrency();

            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexSpotBalance> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"spot/account:{currency}");

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }
        /// <summary>
        /// Get estimated price,the estimated delivery price will be pushed one hour before the delivery, and it will be pushed if there is a change.
        /// </summary>
        /// <param name="symbol">Trading pair symbol</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Futures_SubscribeToEstimatedPrice_Async(string symbol, Action <OkexFuturesEstimatedPrice> onData)
        {
            symbol = symbol.ValidateSymbol();

            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexFuturesEstimatedPrice> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"futures/estimated_price:{symbol}");

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }
        /// <summary>
        /// Users must login to obtain trading data.
        /// </summary>
        /// <param name="symbol">Instrument Id</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Swap_SubscribeToAlgoOrders_Async(string symbol, Action <OkexSwapAlgoOrder> onData)
        {
            symbol = symbol.ValidateSymbol();

            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexSwapAlgoOrder> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"swap/order_algo:{symbol}");

            return(await Subscribe(request, null, true, internalHandler).ConfigureAwait(false));
        }
Пример #21
0
        /// <summary>
        /// Retrieve order book data.
        /// Use books for 400 depth levels, book5 for 5 depth levels, books50-l2-tbt tick-by-tick 50 depth levels, and books-l2-tbt for tick-by-tick 400 depth levels.
        /// books: 400 depth levels will be pushed in the initial full snapshot. Incremental data will be pushed every 100 ms when there is change in order book.
        /// books5: 5 depth levels will be pushed every time.Data will be pushed every 200 ms when there is change in order book.
        /// books50-l2-tbt: 50 depth levels will be pushed in the initial full snapshot. Incremental data will be pushed tick by tick, i.e.whenever there is change in order book.
        /// books-l2-tbt: 400 depth levels will be pushed in the initial full snapshot. Incremental data will be pushed tick by tick, i.e.whenever there is change in order book.
        /// </summary>
        /// <param name="intrumentId">Instrument ID</param>
        /// <param name="orderBookType">Order Book Type</param>
        /// <param name="onData">On Data Handler</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > SubscribeToOrderBook_Async(string intrumentId, OkexOrderBookType orderBookType, Action <OkexOrderBook> onData)
        {
            var internalHandler = new Action <DataEvent <OkexOrderBookUpdate> >(data =>
            {
                foreach (var d in data.Data.Data)
                {
                    d.Instrument = intrumentId;
                    d.Action     = data.Data.Action;
                    onData(d);
                }
            });

            var jc      = JsonConvert.SerializeObject(orderBookType, new OrderBookTypeConverter(false));
            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, jc, intrumentId);

            return(await SubscribeAsync(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #22
0
        /// <summary>
        /// Retrieve the candlestick charts of option contracts. Does not require login,data is pushed every 500ms.
        /// </summary>
        /// <param name="instrument">Trading contract symbol</param>
        /// <param name="period">The period of a single candlestick</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Options_SubscribeToCandlesticks_Async(string instrument, OkexSpotPeriod period, Action <OkexOptionsCandle> onData)
        {
            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexOptionsCandleContainer> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    d.Timestamp     = DateTime.UtcNow;
                    d.Candle.Symbol = instrument.ToUpper(OkexGlobals.OkexCultureInfo);
                    onData(d.Candle);
                }
            });

            var period_s = JsonConvert.SerializeObject(period, new SpotPeriodConverter(false));
            var request  = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"option/candle{period_s}s:{instrument}");

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }
        /// <summary>
        /// Complete List of Contracts
        /// When a new contract is available for trading after settlement, full contract data of all currency will be pushed in this channel ,no login required.
        /// </summary>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Futures_SubscribeToContracts_Async(Action <OkexFuturesContract> onData)
        {
            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <IEnumerable <OkexFuturesContract> > > >(data =>
            {
                foreach (var d in data.Data)
                {
                    foreach (var dd in d)
                    {
                        onData(dd);
                    }
                }
            });

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, $"futures/instruments");

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }
Пример #24
0
        /// <summary>
        /// Retrieve market data summary of all contracts of an underlying index for options trading. Does not require login.
        /// It will push multiple messages for multiple contracts, and only one contract per message.
        /// </summary>
        /// <param name="underlyings">The underlying symbols Maximum Length: 100 symbols</param>
        /// <param name="onData">The handler for updates</param>
        /// <returns></returns>
        public virtual async Task <CallResult <UpdateSubscription> > Options_SubscribeToMarketData_Async(IEnumerable <string> underlyings, Action <OkexOptionsMarketData> onData)
        {
            // To List
            var symbolList = underlyings.ToList();

            // Check Point
            if (symbolList.Count == 0)
            {
                throw new ArgumentException("Symbols must contain 1 element at least");
            }

            if (symbolList.Count > 100)
            {
                throw new ArgumentException("Symbols can contain maximum 100 elements");
            }

            for (int i = 0; i < symbolList.Count; i++)
            {
                symbolList[i] = symbolList[i].ValidateSymbol();
            }

            var internalHandler = new Action <OkexSocketUpdateResponse <IEnumerable <OkexOptionsMarketData> > >(data =>
            {
                foreach (var d in data.Data)
                {
                    onData(d);
                }
            });

            var tickerList = new List <string>();

            for (int i = 0; i < symbolList.Count; i++)
            {
                tickerList.Add($"option/summary:{symbolList[i]}");
            }

            var request = new OkexSocketRequest(OkexSocketOperation.Subscribe, tickerList);

            return(await Subscribe(request, null, false, internalHandler).ConfigureAwait(false));
        }