コード例 #1
0
        protected override async Task OnGetHistoricalTradesAsync(Func <IEnumerable <ExchangeTrade>, bool> callback, string symbol, DateTime?startDate = null, DateTime?endDate = null)
        {
            List <ExchangeTrade> allTrades = new List <ExchangeTrade>();
            var trades = await MakeRequestOkexAsync(symbol, "/trades.do?symbol=$SYMBOL$");

            foreach (JToken trade in trades.Item1)
            {
                // [ { "date": "1367130137", "date_ms": "1367130137000", "price": 787.71, "amount": 0.003, "tid": "230433", "type": "sell" } ]
                allTrades.Add(new ExchangeTrade
                {
                    Amount    = trade["amount"].ConvertInvariant <decimal>(),
                    Price     = trade["price"].ConvertInvariant <decimal>(),
                    Timestamp = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(trade["date_ms"].ConvertInvariant <long>()),
                    Id        = trade["tid"].ConvertInvariant <long>(),
                    IsBuy     = trade["type"].ToStringInvariant() == "buy"
                });
            }
            callback(allTrades);
        }
コード例 #2
0
        private ExchangeOrderResult ParseOrder(JToken result)
        {
            decimal amount       = result["original_amount"].ConvertInvariant <decimal>();
            decimal amountFilled = result["executed_amount"].ConvertInvariant <decimal>();

            return(new ExchangeOrderResult
            {
                Amount = amount,
                AmountFilled = amountFilled,
                Price = result["price"].ConvertInvariant <decimal>(),
                AveragePrice = result["avg_execution_price"].ConvertInvariant <decimal>(),
                Message = string.Empty,
                OrderId = result["id"].ToStringInvariant(),
                Result = (amountFilled == amount ? ExchangeAPIOrderResult.Filled : (amountFilled == 0 ? ExchangeAPIOrderResult.Pending : ExchangeAPIOrderResult.FilledPartially)),
                OrderDate = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(result["timestampms"].ConvertInvariant <double>()),
                Symbol = result["symbol"].ToStringInvariant(),
                IsBuy = result["side"].ToStringInvariant() == "buy"
            });
        }
コード例 #3
0
        private IEnumerable <ExchangeTrade> ParseTradesWebSocket(JToken token)
        {
            var trades = new List <ExchangeTrade>();

            foreach (var t in token)
            {
                var trade = new ExchangeTrade()
                {
                    Amount = t["amount"].ConvertInvariant <decimal>(),
                    // System.OverflowException: Value was either too large or too small for an Int64.
                    // Id = x["id"].ConvertInvariant<long>(),
                    IsBuy     = t["direction"].ToStringLowerInvariant().EqualsWithOption("buy"),
                    Price     = t["price"].ConvertInvariant <decimal>(),
                    Timestamp = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(t["ts"].ConvertInvariant <long>())
                };
                trades.Add(trade);
            }

            return(trades);
        }
コード例 #4
0
        private ExchangeOrderResult ParseOrder(JToken token)
        {
            ExchangeOrderResult result = new ExchangeOrderResult()
            {
                OrderId      = token["id"].ToStringInvariant(),
                Symbol       = token["symbol"].ToStringInvariant(),
                Amount       = token["amount"].ConvertInvariant <decimal>(),
                AmountFilled = token["field-amount"].ConvertInvariant <decimal>(),
                Price        = token["price"].ConvertInvariant <decimal>(),
                OrderDate    = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(token["created-at"].ConvertInvariant <long>()),
                IsBuy        = token["type"].ToStringInvariant().StartsWith("buy"),
                Result       = ParseState(token["state"].ToStringInvariant()),
            };

            if (result.Price == 0 && result.AmountFilled != 0m)
            {
                var amountCash = token["field-cash-amount"].ConvertInvariant <decimal>();
                result.Price = amountCash / result.AmountFilled;
            }

            return(result);
        }
コード例 #5
0
        private ExchangeTicker ParseTickerV2(string symbol, JToken ticker)
        {
            // {"buy":"0.00001273","change":"-0.00000009","changePercentage":"-0.70%","close":"0.00001273","createdDate":1527355333053,"currencyId":535,"dayHigh":"0.00001410","dayLow":"0.00001174","high":"0.00001410","inflows":"19.52673814","last":"0.00001273","low":"0.00001174","marketFrom":635,"name":{},"open":"0.00001282","outflows":"52.53715678","productId":535,"sell":"0.00001284","symbol":"you_btc","volume":"5643177.15601228"}

            decimal last = ticker["last"].ConvertInvariant <decimal>();
            decimal vol  = ticker["volume"].ConvertInvariant <decimal>();

            return(new ExchangeTicker
            {
                Ask = ticker["sell"].ConvertInvariant <decimal>(),
                Bid = ticker["buy"].ConvertInvariant <decimal>(),
                Last = last,
                Volume = new ExchangeVolume
                {
                    BaseVolume = vol,
                    BaseSymbol = symbol,
                    ConvertedVolume = vol * last,
                    ConvertedSymbol = symbol,
                    Timestamp = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(ticker["createdDate"].ConvertInvariant <long>())
                }
            });
        }
コード例 #6
0
        protected override async Task <ExchangeTicker> OnGetTickerAsync(string symbol)
        {
            /*
             * {{
             * "status": "ok",
             * "ch": "market.naseth.detail.merged",
             * "ts": 1525136582460,
             * "tick": {
             *  "amount": 1614089.3164448638,
             *  "open": 0.014552,
             *  "close": 0.013308,
             *  "high": 0.015145,
             *  "id": 6442118070,
             *  "count": 74643,
             *  "low": 0.013297,
             *  "version": 6442118070,
             *  "ask": [
             *    0.013324,
             *    0.0016
             *  ],
             *  "vol": 22839.223396720725,
             *  "bid": [
             *    0.013297,
             *    3192.2322
             *  ]
             * }
             * }}
             */
            symbol = NormalizeSymbol(symbol);
            JToken obj = await MakeJsonRequestAsync <JToken>("/market/detail/merged?symbol=" + symbol);

            var tick = obj["tick"];
            var ts   = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(obj["ts"].ConvertInvariant <double>());

            return(ParseTicker(symbol, ts, tick));
        }
コード例 #7
0
        protected override async Task OnGetHistoricalTradesAsync(Func <IEnumerable <ExchangeTrade>, bool> callback, string symbol, DateTime?startDate = null, DateTime?endDate = null)
        {
            /* [ {
            *  "a": 26129,         // Aggregate tradeId
            *       "p": "0.01633102",  // Price
            *       "q": "4.70443515",  // Quantity
            *       "f": 27781,         // First tradeId
            *       "l": 27781,         // Last tradeId
            *       "T": 1498793709153, // Timestamp
            *       "m": true,          // Was the buyer the maker?
            *       "M": true           // Was the trade the best price match?
            *  } ] */

            HistoricalTradeHelperState state = new HistoricalTradeHelperState(this)
            {
                Callback      = callback,
                EndDate       = endDate,
                ParseFunction = (JToken token) =>
                {
                    DateTime timestamp = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(token["T"].ConvertInvariant <long>());
                    return(new ExchangeTrade
                    {
                        Amount = token["q"].ConvertInvariant <decimal>(),
                        Price = token["p"].ConvertInvariant <decimal>(),
                        Timestamp = timestamp,
                        Id = token["a"].ConvertInvariant <long>(),
                        IsBuy = token["m"].ConvertInvariant <bool>()
                    });
                },
                StartDate         = startDate,
                Symbol            = symbol,
                TimestampFunction = (DateTime dt) => ((long)CryptoUtility.UnixTimestampFromDateTimeMilliseconds(dt)).ToStringInvariant(),
                Url = "/aggTrades?symbol=[symbol]&startTime={0}&endTime={1}",
            };
            await state.ProcessHistoricalTrades();
        }
コード例 #8
0
        private ExchangeOrderResult ParseOrder(JToken token)
        {
            /*
             * {
             * "result": true,
             * "orders": [
             * {
             * "amount": 0.1,
             * "avg_price": 0,
             * "create_date": 1418008467000,
             * "deal_amount": 0,
             * "order_id": 10000591,
             * "orders_id": 10000591,
             * "price": 500,
             * "status": 0,
             * "symbol": "btc_usd",
             * "type": "sell"
             * },
             *
             *
             */
            ExchangeOrderResult result = new ExchangeOrderResult
            {
                Amount       = token["amount"].ConvertInvariant <decimal>(),
                AmountFilled = token["deal_amount"].ConvertInvariant <decimal>(),
                Price        = token["price"].ConvertInvariant <decimal>(),
                AveragePrice = token["avg_price"].ConvertInvariant <decimal>(),
                IsBuy        = token["type"].ToStringInvariant().StartsWith("buy"),
                OrderDate    = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(token["create_date"].ConvertInvariant <long>()),
                OrderId      = token["order_id"].ToStringInvariant(),
                Symbol       = token["symbol"].ToStringInvariant(),
                Result       = ParseOrderStatus(token["status"].ConvertInvariant <int>()),
            };

            return(result);
        }
コード例 #9
0
        private ExchangeOrderResult ParseClientOrder(JToken token)
        {
            //  "data": [{"id": 4910,"currencyPair": "BTC/USD","goodUntilTime": 0,"type": "MARKET_SELL","orderStatus": "EXECUTED","issueTime": 1409920636701,"price": null,"quantity": 2.85714285,"remainingQuantity": 0,"commission": null,"commissionRate": 0.005, "lastModificationTime": 1409920636701 }, .. ]
            ExchangeOrderResult order = new ExchangeOrderResult()
            {
                OrderId   = token["id"].ToStringInvariant(),
                Symbol    = token["currencyPair"].ToStringInvariant(),
                OrderDate = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(token["issueTime"].ConvertInvariant <long>()),
                IsBuy     = token["type"].ToStringInvariant().Contains("BUY"),
                Price     = token["price"].ConvertInvariant <decimal>(),
                Amount    = token["quantity"].ConvertInvariant <decimal>(),
                Fees      = token["commission"].ConvertInvariant <decimal>(),
            };

            order.AmountFilled = order.Amount - token["remainingQuantity"].ConvertInvariant <decimal>();
            switch (token["status"].ToStringInvariant())
            {
            case "CANCELLED": order.Result = ExchangeAPIOrderResult.Canceled; break;
            }



            return(order);
        }
コード例 #10
0
        protected override IWebSocket OnGetTickersWebSocket(Action <IReadOnlyCollection <KeyValuePair <string, ExchangeTicker> > > callback)
        {
            if (callback == null)
            {
                return(null);
            }
            Symbols    = OnGetSymbolsMetadataAsync().GetAwaiter().GetResult();
            symbolDict = Symbols.GroupBy(p => (p.MarketCurrency + p.BaseCurrency).ToLowerInvariant()).ToDictionary(k => k.Key, k => k.FirstOrDefault());
            return(ConnectWebSocket(string.Empty, (msg, _socket) =>
            {
                //消息返回事件

                /*
                 * {"id":"id1","status":"ok","subbed":"market.btcusdt.trade.detail","ts":1527574853489}
                 *
                 *
                 * {{
                 * "ch": "market.btcusdt.trade.detail",
                 * "ts": 1527574905759,
                 * "tick": {
                 * "id": 8232977476,
                 * "ts": 1527574905623,
                 * "data": [
                 * {
                 * "amount": 0.3066,
                 * "ts": 1527574905623,
                 * "id": 82329774765058180723,
                 * "price": 7101.81,
                 * "direction": "buy"
                 * }
                 * ]
                 * }
                 * }}
                 */

                try
                {
                    var freshTickers = new Dictionary <string, ExchangeTicker>(StringComparer.OrdinalIgnoreCase);
                    var str = msg.UTF8StringFromGzip();
                    JToken token = JToken.Parse(str);

                    if (token["status"] != null)
                    {
                        return;
                    }
                    else if (token["ping"] != null)
                    {
                        _socket.SendMessage(str.Replace("ping", "pong"));
                        return;
                    }

                    var ch = token["ch"].ToStringInvariant();
                    var sArray = ch.Split('.');
                    var symbol = sArray[1];

                    var tickData = token["tick"];
                    var id = tickData["id"].ConvertInvariant <long>();

                    var ticks = tickData["data"];
                    string marketName = token["ch"].ToStringInvariant().Split('.')[1];
                    if (!symbolDict.ContainsKey(marketName))
                    {
                        return;
                    }
                    foreach (JToken tick in ticks)
                    {
                        DateTime timestamp = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(tick["ts"].ConvertInvariant <long>());
                        decimal last = tick["price"].ConvertInvariant <decimal>();
                        decimal volume = tick["amount"].ConvertInvariant <decimal>();

                        var t = new ExchangeTicker
                        {
                            Last = last,
                            Volume = new ExchangeVolume
                            {
                                ConvertedVolume = volume,
                                ConvertedSymbol = symbolDict[marketName].BaseCurrency,
                                BaseSymbol = symbolDict[marketName].MarketCurrency,
                                Timestamp = timestamp
                            }
                        };
                        freshTickers[marketName] = t;
                    }
                    callback(freshTickers);
                }
                catch
                {
                }
            }, (_socket) =>
            {
                var symbols = GetSymbols().ToArray();

                foreach (string symbol in symbols)
                {
                    string normalizedSymbol = NormalizeSymbol(symbol);
                    long id = Interlocked.Increment(ref webSocketId);
                    string channel = $"market.{normalizedSymbol}.trade.detail";
                    string msg = $"{{\"sub\":\"{channel}\",\"id\":\"id{id}\"}}";
                    _socket.SendMessage(msg);
                }
            }));
        }
コード例 #11
0
        private ExchangeOrderResult ParseOrder(JToken token)
        {
            /*
             * "symbol": "IOTABTC",
             * "orderId": 1,
             * "clientOrderId": "12345",
             * "transactTime": 1510629334993,
             * "price": "1.00000000",
             * "origQty": "1.00000000",
             * "executedQty": "0.00000000",
             * "status": "NEW",
             * "timeInForce": "GTC",
             * "type": "LIMIT",
             * "side": "SELL",
             * "fills": [
             *    {
             *      "price": "4000.00000000",
             *      "qty": "1.00000000",
             *      "commission": "4.00000000",
             *      "commissionAsset": "USDT"
             *    },
             *    {
             *      "price": "3999.00000000",
             *      "qty": "5.00000000",
             *      "commission": "19.99500000",
             *      "commissionAsset": "USDT"
             *    },
             *    {
             *      "price": "3998.00000000",
             *      "qty": "2.00000000",
             *      "commission": "7.99600000",
             *      "commissionAsset": "USDT"
             *    },
             *    {
             *      "price": "3997.00000000",
             *      "qty": "1.00000000",
             *      "commission": "3.99700000",
             *      "commissionAsset": "USDT"
             *    },
             *    {
             *      "price": "3995.00000000",
             *      "qty": "1.00000000",
             *      "commission": "3.99500000",
             *      "commissionAsset": "USDT"
             *    }
             *  ]
             */
            ExchangeOrderResult result = new ExchangeOrderResult
            {
                Amount       = token["origQty"].ConvertInvariant <decimal>(),
                AmountFilled = token["executedQty"].ConvertInvariant <decimal>(),
                Price        = token["price"].ConvertInvariant <decimal>(),
                IsBuy        = token["side"].ToStringInvariant() == "BUY",
                OrderDate    = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(token["time"].ConvertInvariant <long>(token["transactTime"].ConvertInvariant <long>())),
                OrderId      = token["orderId"].ToStringInvariant(),
                Symbol       = token["symbol"].ToStringInvariant()
            };

            switch (token["status"].ToStringInvariant())
            {
            case "NEW":
                result.Result = ExchangeAPIOrderResult.Pending;
                break;

            case "PARTIALLY_FILLED":
                result.Result = ExchangeAPIOrderResult.FilledPartially;
                break;

            case "FILLED":
                result.Result = ExchangeAPIOrderResult.Filled;
                break;

            case "CANCELED":
            case "PENDING_CANCEL":
            case "EXPIRED":
            case "REJECTED":
                result.Result = ExchangeAPIOrderResult.Canceled;
                break;

            default:
                result.Result = ExchangeAPIOrderResult.Error;
                break;
            }

            ParseAveragePriceAndFeesFromFills(result, token["fills"]);

            return(result);
        }
コード例 #12
0
        protected override IWebSocket OnGetTickersWebSocket(Action <IReadOnlyCollection <KeyValuePair <string, ExchangeTicker> > > callback)
        {
            if (callback == null)
            {
                return(null);
            }
            return(ConnectWebSocket(string.Empty, (msg, _socket) =>
            {
                /*
                 # Request
                 # {'event':'addChannel','channel':'ok_sub_spot_bch_btc_ticker'}
                 # Response
                 # [
                 # {
                 # "channel": "ok_sub_spot_bch_btc_ticker",
                 # "data": {
                 # "high": "10000",
                 # "vol": "185.03743858",
                 # "last": "111",
                 # "low": "0.00000001",
                 # "buy": "115",
                 # "change": "101",
                 # "sell": "115",
                 # "dayLow": "0.00000001",
                 # "dayHigh": "10000",
                 # "timestamp": 1500444626000
                 # }
                 # }
                 # ]
                 */
                try
                {
                    var freshTickers = new Dictionary <string, ExchangeTicker>(StringComparer.OrdinalIgnoreCase);
                    JToken token = JToken.Parse(msg.UTF8String());
                    token = token[0];
                    var channel = token["channel"].ToStringInvariant();
                    if (channel.EqualsWithOption("addChannel"))
                    {
                        return;
                    }

                    var sArray = channel.Split('_');
                    var marketName = sArray[3] + "_" + sArray[4];

                    var tickData = token["data"];
                    DateTime timestamp = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(tickData["timestamp"].ConvertInvariant <long>());
                    decimal last = tickData["last"].ConvertInvariant <decimal>();
                    decimal volume = tickData["vol"].ConvertInvariant <decimal>();

                    var t = new ExchangeTicker
                    {
                        Last = last,
                        Volume = new ExchangeVolume
                        {
                            ConvertedVolume = volume,
                            ConvertedSymbol = sArray[4].ToUpperInvariant(),
                            BaseSymbol = sArray[3].ToUpperInvariant(),
                            Timestamp = timestamp
                        }
                    };
                    freshTickers[marketName] = t;
                    callback(freshTickers);
                }
                catch
                {
                }
            }, (_socket) =>
            {
                var symbols = GetSymbols().ToArray();
                foreach (string symbol in symbols)
                {
                    string normalizedSymbol = NormalizeSymbol(symbol);
                    string channel = $"ok_sub_spot_{normalizedSymbol}_ticker";
                    string msg = $"{{\'event\':\'addChannel\',\'channel\':\'{channel}\'}}";
                    _socket.SendMessage(msg);
                }
            }));
        }
コード例 #13
0
 /// <summary>
 /// Get a string for this trade
 /// </summary>
 /// <returns>String</returns>
 public override string ToString()
 {
     return(CryptoUtility.UnixTimeStampToDateTimeMilliseconds(Ticks).ToLocalTime() + ": " + Amount + " at " + Price);
 }
コード例 #14
0
        protected override async Task OnGetHistoricalTradesAsync(Func <IEnumerable <ExchangeTrade>, bool> callback, string symbol, DateTime?startDate = null, DateTime?endDate = null)
        {
            const int maxCount = 100;

            symbol = NormalizeSymbol(symbol);
            string baseUrl = "/trades/t" + symbol + "/hist?sort=" + (startDate == null ? "-1" : "1") + "&limit=" + maxCount;
            string url;
            List <ExchangeTrade> trades = new List <ExchangeTrade>();

            decimal[][] tradeChunk;
            while (true)
            {
                url = baseUrl;
                if (startDate != null)
                {
                    url += "&start=" + (long)CryptoUtility.UnixTimestampFromDateTimeMilliseconds(startDate.Value);
                }
                tradeChunk = await MakeJsonRequestAsync <decimal[][]>(url);

                if (tradeChunk == null || tradeChunk.Length == 0)
                {
                    break;
                }
                if (startDate != null)
                {
                    startDate = CryptoUtility.UnixTimeStampToDateTimeMilliseconds((double)tradeChunk[tradeChunk.Length - 1][1]);
                }
                foreach (decimal[] tradeChunkPiece in tradeChunk)
                {
                    trades.Add(new ExchangeTrade {
                        Amount = Math.Abs(tradeChunkPiece[2]), IsBuy = tradeChunkPiece[2] > 0m, Price = tradeChunkPiece[3], Timestamp = CryptoUtility.UnixTimeStampToDateTimeMilliseconds((double)tradeChunkPiece[1]), Id = (long)tradeChunkPiece[0]
                    });
                }
                trades.Sort((t1, t2) => t1.Timestamp.CompareTo(t2.Timestamp));
                if (!callback(trades))
                {
                    break;
                }
                trades.Clear();
                if (tradeChunk.Length < maxCount || startDate == null)
                {
                    break;
                }
                await Task.Delay(5000);
            }
        }
コード例 #15
0
        protected override IWebSocket OnGetTickersWebSocket(Action <IReadOnlyCollection <KeyValuePair <string, ExchangeTicker> > > callback)
        {
            if (callback == null)
            {
                return(null);
            }

            void innerCallback(string json)
            {
                #region sample json

                /*
                 * {
                 *  Nonce : int,
                 *  Deltas :
                 *  [
                 *      {
                 *          MarketName     : string,
                 *          High           : decimal,
                 *          Low            : decimal,
                 *          Volume         : decimal,
                 *          Last           : decimal,
                 *          BaseVolume     : decimal,
                 *          TimeStamp      : date,
                 *          Bid            : decimal,
                 *          Ask            : decimal,
                 *          OpenBuyOrders  : int,
                 *          OpenSellOrders : int,
                 *          PrevDay        : decimal,
                 *          Created        : date
                 *      }
                 *  ]
                 * }
                 */
                #endregion

                var    freshTickers = new Dictionary <string, ExchangeTicker>(StringComparer.OrdinalIgnoreCase);
                JToken token        = JToken.Parse(json);
                token = token["D"];
                foreach (JToken ticker in token)
                {
                    string   marketName = ticker["M"].ToStringInvariant();
                    decimal  last       = ticker["l"].ConvertInvariant <decimal>();
                    decimal  ask        = ticker["A"].ConvertInvariant <decimal>();
                    decimal  bid        = ticker["B"].ConvertInvariant <decimal>();
                    decimal  volume     = ticker["V"].ConvertInvariant <decimal>();
                    decimal  baseVolume = ticker["m"].ConvertInvariant <decimal>();
                    DateTime timestamp  = CryptoUtility.UnixTimeStampToDateTimeMilliseconds(ticker["T"].ConvertInvariant <long>());
                    var      t          = new ExchangeTicker
                    {
                        Ask    = ask,
                        Bid    = bid,
                        Last   = last,
                        Volume = new ExchangeVolume
                        {
                            ConvertedVolume = volume,
                            ConvertedSymbol = marketName.Split('-')[0],
                            BaseVolume      = baseVolume,
                            BaseSymbol      = marketName.Split('-')[1],
                            Timestamp       = timestamp
                        }
                    };
                    freshTickers[marketName] = t;
                }
                callback(freshTickers);
            }

            var client = SocketManager;
            return(client.SubscribeToSummaryDeltas(innerCallback));
        }