コード例 #1
0
        public void UpdateTrades(BittrexMarketInfo info)
        {
            Timer.Reset();
            Timer.Stop();
            string address = string.Format("https://bittrex.com/api/v1.1/public/getmarkethistory?market={0}", Uri.EscapeDataString(info.MarketName));
            string text    = GetDownloadString(info, address);

            if (string.IsNullOrEmpty(text))
            {
                return;
            }
            JObject res = (JObject)JsonConvert.DeserializeObject(text);

            foreach (JProperty prop in res.Children())
            {
                if (prop.Name == "success")
                {
                    if (prop.Value.Value <bool>() == false)
                    {
                        break;
                    }
                }
                if (prop.Name == "message")
                {
                    continue;
                }
                if (prop.Name == "result")
                {
                    lock (info) {
                        JArray trades = (JArray)prop.Value;
                        UpdateList.Clear();
                        int lastId = info.TradeHistory.Count > 0 ? info.TradeHistory.First().Id : -1;
                        foreach (JObject obj in trades)
                        {
                            int id = obj.Value <int>("Id");
                            if (id == lastId)
                            {
                                info.TradeHistory.InsertRange(0, UpdateList);
                                break;
                            }
                            TradeHistoryItem item = new TradeHistoryItem();
                            item.Id     = id;
                            item.Time   = obj.Value <DateTime>("TimeStamp");
                            item.Amount = obj.Value <double>("Quantity");
                            item.Rate   = obj.Value <double>("Price");
                            item.Total  = obj.Value <double>("Total");
                            item.Type   = obj.Value <string>("OrderType") == "BUY" ? TradeType.Buy : TradeType.Sell;
                            item.Fill   = obj.Value <string>("FillType") == "FILL" ? TradeFillType.Fill : TradeFillType.PartialFill;
                            TickerUpdateHelper.UpdateHistoryForTradeItem(item, info);
                            UpdateList.Add(item);
                        }
                    }
                    Timer.Stop();
                    Console.WriteLine(info.Time.ToString("hh:mm:ss.fff") + " trade update. process time = " + Timer.ElapsedMilliseconds);
                    info.RaiseTradeHistoryAdd();
                }
            }
        }
コード例 #2
0
 public FullHistoryTradeOffer(TradeHistoryItem historyItem, List <AssetDescription> assetDescriptions)
 {
     TradeId       = historyItem.TradeId;
     SteamIdOther  = new SteamID(ulong.Parse(historyItem.SteamIdOther));
     TimeInit      = CommonUtils.ParseSteamUnixDate(int.Parse(historyItem.TimeInit));
     TimeEscrowEnd = historyItem.TimeEscrowEnd;
     Status        = historyItem.Status;
     MyItems       = GetFullHistoryTradeItemsList(historyItem.AssetsGiven, historyItem.CurrencyGiven,
                                                  assetDescriptions);
     HisItems = GetFullHistoryTradeItemsList(historyItem.AssetsReceived, historyItem.CurrencyReceived,
                                             assetDescriptions);
 }
コード例 #3
0
 public static ICandle CreateCandle(this TradeHistoryItem trade, string assetPairId, CandlePriceType priceType, CandleTimeInterval interval, decimal volumeMultiplier = 1.0M)
 {
     return(Candle.Create(
                assetPairId,
                priceType,
                interval,
                trade.DateTime.TruncateTo(interval),
                (double)trade.Price,
                (double)trade.Price,
                (double)trade.Price,
                (double)trade.Price,
                Convert.ToDouble((trade.IsStraight ? trade.Volume : trade.OppositeVolume) * volumeMultiplier),
                Convert.ToDouble((trade.IsStraight ? trade.OppositeVolume : trade.Volume) * volumeMultiplier),
                0, // Last Trade Price is enforced to be = 0
                trade.DateTime
                ));
 }
            private async Task ProcessTrade(TradeHistoryItem trade, decimal volumeMultiplier)
            {
                var dataWritingTasks = new List <Task>();

                foreach (var interval in Candles.Constants.DbStoredIntervals)
                {
                    if (_activeCandles.TryGetValue(interval, out var activeCandle))
                    {
                        if (trade.BelongsTo(activeCandle))
                        {
                            _activeCandles[interval] = activeCandle.ExtendBy(trade, volumeMultiplier);
                        }
                        else
                        {
                            _persistenceCandleQueue[interval].Add(activeCandle);

                            _activeCandles[interval] = trade.CreateCandle(_assetPairId,
                                                                          CandlePriceType.Trades, interval, volumeMultiplier);
                        }
                    }
                    else
                    {
                        _activeCandles[interval] = trade.CreateCandle(_assetPairId,
                                                                      CandlePriceType.Trades, interval, volumeMultiplier);
                        continue;
                    }

                    if (_persistenceCandleQueue[interval].Count < _persistenceQueueMaxSize)
                    {
                        continue;
                    }

                    dataWritingTasks.Add(_historyRepo.ReplaceCandlesAsync(_persistenceCandleQueue[interval]));

                    _healthService[_assetPairId].SummarySavedCandles +=
                        _persistenceCandleQueue[interval].Count;

                    _persistenceCandleQueue[interval] = new List <ICandle>(_persistenceQueueMaxSize);
                }

                await Task.WhenAll(dataWritingTasks);

                _healthService.Health.PersistenceQueueSize = PersistenceQueueSize;
            }
        public async Task <IReadOnlyCollection <TradeHistoryItem> > GetNextBatchAsync()
        {
            // If we got the last batch in the previous iteration, there is no reason to execute one more query
            // with empty result. Just return.
            if (_gotTheLastBatch)
            {
                return(Array.Empty <TradeHistoryItem>());
            }

            try
            {
                var result = new List <TradeHistoryItem>();

                // Renew the connection on every call.
                using (var sqlConnection = new SqlConnection(_sqlConnString))
                {
                    sqlConnection.Open();

                    if (sqlConnection.State != ConnectionState.Open)
                    {
                        throw new InvalidOperationException("Can't fetch from DB while connection is not opened.");
                    }

                    _log.Info(nameof(GetNextBatchAsync),
                              $"Trying to fetch next {_sqlQueryBatchSize} rows...",
                              $"Starting offset = {StartingRowOffset}, asset pair ID = {AssetPairId}");

                    using (var sqlCommand = BuildCurrentQueryCommand(sqlConnection))
                    {
                        sqlCommand.CommandTimeout = (int)_sqlTimeout.TotalSeconds;
                        using (var reader = await sqlCommand.ExecuteReaderAsync())
                        {
                            while (await reader.ReadAsync())
                            {
                                var trade = new TradeHistoryItem
                                {
                                    Id         = reader.GetInt64(0),
                                    AssetToken = reader.GetString(1),
                                    Direction  =
                                        (TradeDirection)Enum.Parse(typeof(TradeDirection), reader.GetString(2)),
                                    Volume          = reader.GetDecimal(3),
                                    Price           = reader.GetDecimal(4),
                                    DateTime        = reader.GetDateTime(5),
                                    OppositeVolume  = reader.GetDecimal(6),
                                    OrderId         = Guid.Parse(reader.GetString(7)),
                                    OppositeOrderId = Guid.Parse(reader.GetString(8)),
                                    TradeId         = reader.GetString(9),
                                    IsStraight      =
                                        reader.GetString(1) == SearchToken // If the trade is straight or reverse.
                                };

                                // We must ignore trades with negative prices and\or volumes (if any).
                                if (trade.Price > 0 &&
                                    trade.Volume > 0 &&
                                    trade.OppositeVolume > 0)
                                {
                                    result.Add(trade);
                                }
                                else
                                {
                                    _healthNotifier.Notify("Got a trade with non-posotive price or volume(s) values.", trade);
                                }
                            }
                        }
                    }

                    sqlConnection.Close();
                }

                if (result.Count > 0)
                {
                    // Now we need to remove the last several trades which have the same date and time (accuracy - to seconds).
                    // This will guarantee that we did not peek up some orders of the same trade on this iteration, and others
                    // on the next. On the next iteration we will read them again for the next batch. No temporary buffer, for
                    // it can't save any observable value of time. NOTE: if we have got less records than _sqlQueryBatchSize,
                    // this means that we obtained the last (or the single) data pack, and there is no reason to delete "tail"
                    // trades.

                    if (result.Count == _sqlQueryBatchSize)
                    {
                        var lastDateTime      = result.Last().DateTime.TruncateTo(CandleTimeInterval.Sec);
                        var resultWithoutTail = result.TakeWhile(t => t.DateTime < lastDateTime).ToList();

                        if (!resultWithoutTail.Any())
                        {
                            throw new InvalidOperationException($"Got an SQL data batch of {result.Count} trade records with the same timestamp {lastDateTime:O}. " +
                                                                $"Migration for asset pair {AssetPairId} will be terminated. Row offset was {StartingRowOffset} before the incident.");
                        }

                        result = resultWithoutTail;
                    }
                    else
                    {
                        _gotTheLastBatch = true;  // If we have got smaller amount of records than _sqlQueryBatchSize, this only means we have the last batch now.
                    }
                    _log.Info(nameof(GetNextBatchAsync),
                              $"Fetched {result.Count} rows successfully. First date is {result.First().DateTime:O}, last date is {result.Last().DateTime:O}",
                              $"Starting offset = {StartingRowOffset}, asset pair ID = {AssetPairId}");

                    StartingRowOffset += result.Count;
                }
                else
                {
                    _log.Info(nameof(GetNextBatchAsync),
                              "No data to fetch.",
                              $"Starting offset = {StartingRowOffset}, asset pair ID = {AssetPairId}");
                }

                return(result);
            }
            catch (Exception ex)
            {
                _log.Error(nameof(GetNextBatchAsync), ex);
                // We can just report about the error and return an empty list - this will be interpreted as "no data".
                return(Array.Empty <TradeHistoryItem>());
            }
        }
コード例 #6
0
        public bool UpdateTradesStatistic(ExmoTicker ticker, int count)
        {
            string text    = string.Empty;
            string address = string.Format("https://api.exmo.me/v1/trades/?pair={0}", ticker.MarketName);

            try {
                text = GetDownloadString(address);
                if (text == null)
                {
                    return(false);
                }
            }
            catch (Exception) {
                return(false);
            }

            Dictionary <string, object> res = null;

            lock (JsonParser) {
                res = (Dictionary <string, object>)JsonParser.Parse(text);
            }
            List <object> trades = (List <object>)res[ticker.MarketName];

            if (trades.Count == 0)
            {
                ticker.TradeStatistic.Add(new TradeStatisticsItem()
                {
                    Time = DateTime.Now
                });
                if (ticker.TradeStatistic.Count > 5000)
                {
                    for (int i = 0; i < 100; i++)
                    {
                        ticker.TradeStatistic.RemoveAt(0);
                    }
                }
                return(true);
            }

            TradeStatisticsItem st = new TradeStatisticsItem();

            st.MinBuyPrice  = decimal.MaxValue;
            st.MinSellPrice = decimal.MaxValue;
            st.Time         = DateTime.Now;

            foreach (Dictionary <string, object> obj in trades)
            {
                TradeHistoryItem item   = new TradeHistoryItem();
                decimal          amount = Convert.ToDecimal(obj["amount"]);
                decimal          price  = Convert.ToDecimal(obj["price"]);
                bool             isBuy  = obj["type"].ToString().Length == 3;
                if (isBuy)
                {
                    st.BuyAmount  += amount;
                    st.MinBuyPrice = Math.Min(st.MinBuyPrice, price);
                    st.MaxBuyPrice = Math.Max(st.MaxBuyPrice, price);
                    st.BuyVolume  += amount * price;
                }
                else
                {
                    st.SellAmount  += amount;
                    st.MinSellPrice = Math.Min(st.MinSellPrice, price);
                    st.MaxSellPrice = Math.Max(st.MaxSellPrice, price);
                    st.SellVolume  += amount * price;
                }
            }
            if (st.MinSellPrice == decimal.MaxValue)
            {
                st.MinSellPrice = 0;
            }
            if (st.MinBuyPrice == decimal.MaxValue)
            {
                st.MinBuyPrice = 0;
            }
            ticker.LastTradeId            = Convert.ToInt64(((Dictionary <string, object>)trades.First())["trade_id"]);
            ticker.LastTradeStatisticTime = DateTime.Now;
            ticker.TradeStatistic.Add(st);
            if (ticker.TradeStatistic.Count > 5000)
            {
                for (int i = 0; i < 100; i++)
                {
                    ticker.TradeStatistic.RemoveAt(0);
                }
            }
            return(true);
        }
コード例 #7
0
        public bool UpdateTradesStatistic(HitBtcTicker ticker, int count)
        {
            string text    = string.Empty;
            string address = string.Format("http://api.hitbtc.com//api/1/public/{0}/trades?from={1}&by=trade_id&sort=desc&start_index=0&max_results={2}&side=true", ticker.MarketName, ticker.LastTradeId, count);

            try {
                text = GetDownloadString(address);
                if (text == null)
                {
                    return(false);
                }
            }
            catch (Exception) {
                return(false);
            }

            Dictionary <string, object> res = null;

            lock (JsonParser) {
                res = (Dictionary <string, object>)JsonParser.Parse(text);
            }
            List <object> trades = (List <object>)res["trades"];

            if (trades.Count == 0)
            {
                ticker.TradeStatistic.Add(new TradeStatisticsItem()
                {
                    Time = DateTime.Now
                });
                if (ticker.TradeStatistic.Count > 5000)
                {
                    for (int i = 0; i < 100; i++)
                    {
                        ticker.TradeStatistic.RemoveAt(0);
                    }
                }
                return(true);
            }

            TradeStatisticsItem st = new TradeStatisticsItem();

            st.MinBuyPrice  = decimal.MaxValue;
            st.MinSellPrice = decimal.MaxValue;
            st.Time         = DateTime.Now;

            foreach (List <object> obj in trades)
            {
                TradeHistoryItem item   = new TradeHistoryItem();
                decimal          amount = Convert.ToDecimal(obj[1]);
                decimal          price  = Convert.ToDecimal(obj[2]);
                bool             isBuy  = obj[4].ToString().Length == 3;
                if (isBuy)
                {
                    st.BuyAmount  += amount;
                    st.MinBuyPrice = Math.Min(st.MinBuyPrice, price);
                    st.MaxBuyPrice = Math.Max(st.MaxBuyPrice, price);
                    st.BuyVolume  += amount * price;
                }
                else
                {
                    st.SellAmount  += amount;
                    st.MinSellPrice = Math.Min(st.MinSellPrice, price);
                    st.MaxSellPrice = Math.Max(st.MaxSellPrice, price);
                    st.SellVolume  += amount * price;
                }
            }
            if (st.MinSellPrice == decimal.MaxValue)
            {
                st.MinSellPrice = 0;
            }
            if (st.MinBuyPrice == decimal.MaxValue)
            {
                st.MinBuyPrice = 0;
            }
            ticker.LastTradeId            = Convert.ToInt64(((List <object>)trades.First())[0]);
            ticker.LastTradeStatisticTime = DateTime.Now;
            ticker.TradeStatistic.Add(st);
            if (ticker.TradeStatistic.Count > 5000)
            {
                for (int i = 0; i < 100; i++)
                {
                    ticker.TradeStatistic.RemoveAt(0);
                }
            }
            return(true);
        }
コード例 #8
0
 /// <summary>
 /// Detects if the given trade item lays in time borders of the given candle.
 /// </summary>
 public static bool BelongsTo(this TradeHistoryItem trade, ICandle candle)
 {
     return(trade.DateTime.TruncateTo(candle.TimeInterval) == candle.Timestamp);
 }
コード例 #9
0
        /// <summary>
        /// Extends a candle by a trade, if trade's DateTime corresponds to candle's TimeStamp (i.e., the trade belongs to the same time period).
        /// </summary>
        public static ICandle ExtendBy(this ICandle self, TradeHistoryItem trade, decimal volumeMultiplier = 1.0M)
        {
            var tradeCandle = trade.CreateCandle(self.AssetPairId, self.PriceType, self.TimeInterval, volumeMultiplier);

            return(self.ExtendBy(tradeCandle));
        }
コード例 #10
0
        public override bool UpdateTrades(TickerBase ticker)
        {
            string address = string.Format("https://yobit.net/api/3/trades/{0}",
                                           Uri.EscapeDataString(ticker.CurrencyPair));
            string text = ((TickerBase)ticker).DownloadString(address);

            if (string.IsNullOrEmpty(text))
            {
                return(false);
            }

            JObject obj2   = (JObject)JsonConvert.DeserializeObject(text);
            JArray  trades = (JArray)obj2.Value <JArray>(ticker.CurrencyPair);

            if (trades.Count == 0)
            {
                return(true);
            }

            int  lastTradeId    = trades.First().Value <int>("tid");
            long lastGotTradeId = ticker.TradeHistory.Count > 0 ? ticker.TradeHistory.First().Id : 0;

            if (lastGotTradeId == lastTradeId)
            {
                ticker.TradeStatistic.Add(new TradeStatisticsItem()
                {
                    Time = DateTime.UtcNow
                });
                if (ticker.TradeStatistic.Count > 5000)
                {
                    for (int i = 0; i < 100; i++)
                    {
                        ticker.TradeStatistic.RemoveAt(0);
                    }
                }
                return(true);
            }
            TradeStatisticsItem st = new TradeStatisticsItem();

            st.MinBuyPrice  = double.MaxValue;
            st.MinSellPrice = double.MaxValue;
            st.Time         = DateTime.UtcNow;

            int index = 0;

            foreach (JObject obj in trades)
            {
                DateTime time    = new DateTime(1970, 1, 1).AddSeconds(obj.Value <long>("timestamp"));
                int      tradeId = obj.Value <int>("tid");
                if (lastGotTradeId == tradeId)
                {
                    break;
                }

                TradeHistoryItem item = new TradeHistoryItem();

                bool isBuy = obj.Value <string>("type") == "bid";
                item.AmountString = obj.Value <string>("amount");
                item.Time         = time;
                item.Type         = isBuy ? TradeType.Buy : TradeType.Sell;
                item.RateString   = obj.Value <string>("price");
                item.Id           = tradeId;
                double price  = item.Rate;
                double amount = item.Amount;
                item.Total = price * amount;
                if (isBuy)
                {
                    st.BuyAmount  += amount;
                    st.MinBuyPrice = Math.Min(st.MinBuyPrice, price);
                    st.MaxBuyPrice = Math.Max(st.MaxBuyPrice, price);
                    st.BuyVolume  += amount * price;
                }
                else
                {
                    st.SellAmount  += amount;
                    st.MinSellPrice = Math.Min(st.MinSellPrice, price);
                    st.MaxSellPrice = Math.Max(st.MaxSellPrice, price);
                    st.SellVolume  += amount * price;
                }
                ticker.TradeHistory.Insert(index, item);
                index++;
            }
            if (st.MinSellPrice == double.MaxValue)
            {
                st.MinSellPrice = 0;
            }
            if (st.MinBuyPrice == double.MaxValue)
            {
                st.MinBuyPrice = 0;
            }
            ticker.LastTradeStatisticTime = DateTime.UtcNow;
            ticker.TradeStatistic.Add(st);
            if (ticker.TradeStatistic.Count > 5000)
            {
                for (int i = 0; i < 100; i++)
                {
                    ticker.TradeStatistic.RemoveAt(0);
                }
            }
            return(true);
        }