public override decimal ClampOrderQuantity(string symbol, decimal outputQuantity)
        {
            symbol = NormalizeSymbol(symbol);
            ExchangeMarket market = GetExchangeMarket(symbol);

            return(market == null ? outputQuantity : CryptoUtility.ClampDecimal(market.MinTradeSize, market.MaxTradeSize, market.QuantityStepSize, outputQuantity));
        }
        public override decimal MinAmount(decimal pairPrice, string symbole)
        {
            ExchangeMarket market      = GetExchangeMarket(symbole);
            decimal        minNotional = market.MinAmountDiv;

            return(minNotional / pairPrice);
        }
        public override int GetRoundPrice(string symbole)
        {
            ExchangeMarket market      = GetExchangeMarket(symbole);
            decimal        outputPrice = ClampOrderPrice(symbole, 9.99999999m);
            int            result      = BitConverter.GetBytes(decimal.GetBits(outputPrice)[3])[2];

            return(result);
        }
        public override int GetRoundAmount(string symbole, decimal outputQuantity)
        {
            ExchangeMarket market = GetExchangeMarket(symbole);

            outputQuantity = ClampOrderQuantity(symbole, outputQuantity);
            int result = BitConverter.GetBytes(decimal.GetBits(outputQuantity)[3])[2];

            return(result);
        }
        public override decimal MinAmountWithRounding(decimal pairPrice, string symbole)
        {
            ExchangeMarket market      = GetExchangeMarket(symbole);
            decimal        minNotional = market.MinAmountDiv;
            decimal        result      = minNotional / pairPrice;

            result = ClampOrderQuantity(symbole, result);

            decimal sum = result * pairPrice;

            while (sum < minNotional)
            {
                result += (decimal)market.QuantityStepSize;
                result  = ClampOrderQuantity(symbole, result);
                sum     = result * pairPrice;
            }

            return(result);
        }
        protected IEnumerable <ExchangeMarket> GetSymbolsMetadata()
        {
            /*
             * {
             * "symbol": "QTUMETH",
             * "status": "TRADING",
             * "baseAsset": "QTUM",
             * "baseAssetPrecision": 8,
             * "quoteAsset": "ETH",
             * "quotePrecision": 8,
             * "orderTypes": [
             *  "LIMIT",
             *  "LIMIT_MAKER",
             *  "MARKET",
             *  "STOP_LOSS_LIMIT",
             *  "TAKE_PROFIT_LIMIT"
             * ],
             * "icebergAllowed": true,
             * "filters": [
             *  {
             *      "filterType": "PRICE_FILTER",
             *      "minPrice": "0.00000100",
             *      "maxPrice": "100000.00000000",
             *      "tickSize": "0.00000100"
             *  },
             *  {
             *      "filterType": "LOT_SIZE",
             *      "minQty": "0.01000000",
             *      "maxQty": "90000000.00000000",
             *      "stepSize": "0.01000000"
             *  },
             *  {
             *      "filterType": "MIN_NOTIONAL",
             *      "minNotional": "0.01000000"
             *  }
             * ]
             * },
             */

            var    markets = new List <ExchangeMarket>();
            JToken obj     = MakeJsonRequest <JToken>("/exchangeInfo");

            CheckError(obj);
            JToken allSymbols = obj["symbols"];

            foreach (JToken symbol in allSymbols)
            {
                var market = new ExchangeMarket
                {
                    MarketName     = symbol["symbol"].ToStringUpperInvariant(),
                    IsActive       = ParseMarketStatus(symbol["status"].ToStringUpperInvariant()),
                    BaseCurrency   = symbol["quoteAsset"].ToStringUpperInvariant(),
                    MarketCurrency = symbol["baseAsset"].ToStringUpperInvariant()
                };

                // "LOT_SIZE"
                JToken filters       = symbol["filters"];
                JToken lotSizeFilter = filters?.FirstOrDefault(x => string.Equals(x["filterType"].ToStringUpperInvariant(), "LOT_SIZE"));
                if (lotSizeFilter != null)
                {
                    market.MaxTradeSize     = lotSizeFilter["maxQty"].ConvertInvariant <decimal>();
                    market.MinTradeSize     = lotSizeFilter["minQty"].ConvertInvariant <decimal>();
                    market.QuantityStepSize = lotSizeFilter["stepSize"].ConvertInvariant <decimal>();
                }

                // PRICE_FILTER
                JToken priceFilter = filters?.FirstOrDefault(x => string.Equals(x["filterType"].ToStringUpperInvariant(), "PRICE_FILTER"));
                if (priceFilter != null)
                {
                    market.MaxPrice = priceFilter["maxPrice"].ConvertInvariant <decimal>();
                    market.MinPrice = priceFilter["minPrice"].ConvertInvariant <decimal>();
                    if (market.MaxPrice == 0 || market.MinPrice == 0)
                    {
                        decimal price = AllTickers[market.MarketName].Last;
                        market.MaxPrice = price * 10;
                        market.MinPrice = price * 0.1m;
                    }
                    market.PriceStepSize = priceFilter["tickSize"].ConvertInvariant <decimal>();
                }

                // MIN_NOTIONAL
                JToken notionalFilter = filters?.FirstOrDefault(x => string.Equals(x["filterType"].ToStringUpperInvariant(), "MIN_NOTIONAL"));
                if (notionalFilter != null)
                {
                    market.MinAmountDiv = notionalFilter["minNotional"].ConvertInvariant <decimal>();
                }
                markets.Add(market);
            }

            return(markets);
        }
        public override decimal ClampOrderPrice(string symbol, decimal outputPrice)
        {
            ExchangeMarket market = GetExchangeMarket(symbol);

            return(market == null ? outputPrice : CryptoUtility.ClampDecimal(market.MinPrice, market.MaxPrice, market.PriceStepSize, outputPrice));
        }