public async Task <DepthModel> GetDepth(string tradingPair)
        {
            using (var client = GetClient())
            {
                using (var response = await client.GetAsync($"/api/v1/depth?symbol={tradingPair}"))
                {
                    if (!response.IsSuccessStatusCode)
                    {
                        throw new Exception($"Response code: {response.StatusCode}, body: {response.Content.ReadAsStringAsync().Result}");
                    }

                    var depthModel = new DepthModel
                    {
                        Bids = new List <PriceRateModel>(),
                        Asks = new List <PriceRateModel>()
                    };
                    var responseContent = await response.Content.ReadAsStringAsync();

                    var obj      = (JObject)JsonConvert.DeserializeObject(responseContent);
                    var bidArray = obj["bids"].ToArray();
                    foreach (var bid in bidArray)
                    {
                        var bidPriceAndRate = bid.ToArray();
                        depthModel.Bids.Add(new PriceRateModel
                        {
                            Price    = (decimal)bidPriceAndRate[0],
                            Quantity = (decimal)bidPriceAndRate[1]
                        });
                    }
                    var askArray = obj["asks"].ToArray();
                    foreach (var ask in askArray)
                    {
                        var askPriceAndRate = ask.ToArray();
                        depthModel.Asks.Add(new PriceRateModel
                        {
                            Price    = (decimal)askPriceAndRate[0],
                            Quantity = (decimal)askPriceAndRate[1]
                        });
                    }
                    return(depthModel);
                }
            }
        }
        private decimal CheckProfitPrecentageAsync(DepthModel depth, decimal closePrice)
        {
            //var bidsWall = depth.Bids.First(f => f.Quantity == depth.Bids.Max(b => b.Quantity));
            var asksWall = depth.Asks.First(f => f.Quantity == depth.Asks.Max(b => b.Quantity));

            var bidsSum = depth.Bids.Sum(s => s.Quantity);
            var asksSum = depth.Asks.Sum(s => s.Quantity);

            var profitEstimation = (asksWall.Price / closePrice - 1) * 100;

            Console.WriteLine($"Profit estimation: {Math.Round(profitEstimation, 4)}%");
            if (profitEstimation > _options.ProfitEstimationRate &&
                bidsSum > asksSum)
            {
                return(Math.Round(profitEstimation, 4));
            }

            return(-1);
        }
Example #3
0
        /// <summary>
        /// Parses the data from source to datapoints.
        /// </summary>
        /// <param name="data">The data.</param>
        /// <param name="ticker">Associated ticker</param>
        /// <returns></returns>
        public DataPointImpl[] ParseData(string data, string ticker = "")
        {
            //Initial items
            DepthModel     depthupdate     = null;
            TradeModel     treadeupdate    = null;
            OrderBookModel orderbookupdate = null;
            var            toreturn        = new List <DataPointImpl>();

            data = data.Replace(",[]", "");

            //Convert models
            if (data.Contains("depthUpdate"))
            {
                depthupdate = JSON.Deserialize <DepthModel>(data);
            }
            else if (data.Contains("aggTrade"))
            {
                treadeupdate = JSON.Deserialize <TradeModel>(data);
            }
            else if (data.Contains("lastUpdateId"))
            {
                //Check if this contains additional data
                if (data.Contains("|"))
                {
                    var splitted = data.Split('|');
                    ticker = splitted[0];
                    data   = splitted[1];
                }

                //Parse data
                orderbookupdate = JSON.Deserialize <OrderBookModel>(data);
            }

            //Full update order book
            if (orderbookupdate != null && !string.IsNullOrWhiteSpace(ticker))
            {
                //Check data
                if (!_orderbook.TryGetValue(ticker, out var orderbook))
                {
                    //Set order book instance
                    orderbook          = new OrderBook(ticker);
                    _orderbook[ticker] = orderbook;
                }

                //Helper function
                void UpdateBook(bool isBid, PriceModel x) =>
                orderbook.AddQuote(isBid, x.DoubleValue, x.DoubleSize);

                //Clear and refresh
                orderbook.Clear();
                orderbookupdate.Asks.ForEach(u => UpdateBook(false, u));
                orderbookupdate.Bids.ForEach(u => UpdateBook(true, u));
            }
            //Update order book
            else if (depthupdate != null)
            {
                //Check data
                if (!_orderbook.TryGetValue(ticker, out var orderbook))
                {
                    //Set order book instance
                    orderbook          = new OrderBook(ticker);
                    _orderbook[ticker] = orderbook;
                }

                //DateTime occured
                DateTime occuredutc = Time.FromUnixTime(depthupdate.EventTime, true);

                //Check for quote updates in the order book (size == 0 = remove from order book)
                bool update = depthupdate.AskPricesModel.Count(x => orderbook.AddQuote(false, x.DoubleValue, x.DoubleSize)) > 0;
                update = depthupdate.BidPricesModel.Count(x => orderbook.AddQuote(true, x.DoubleValue, x.DoubleSize)) > 0 | update;

                //Check for full quote update
                if (update)
                {
                    toreturn.Add(new Tick(GetQuantlerTicker(depthupdate.Symbol), DataSource)
                    {
                        AskSize  = Convert.ToDecimal(orderbook.AskSize),
                        AskPrice = Convert.ToDecimal(orderbook.BestAsk),
                        BidPrice = Convert.ToDecimal(orderbook.BestBid),
                        BidSize  = Convert.ToDecimal(orderbook.BidSize),
                        Depth    = 0,
                        Occured  = occuredutc,
                        TimeZone = TimeZone.Utc
                    });
                }
            }
            //Send trade
            else if (treadeupdate != null)
            {
                //DateTime occured
                DateTime occuredutc = Time.FromUnixTime(treadeupdate.EventTime, true);

                toreturn.Add(new Tick(GetQuantlerTicker(treadeupdate.Symbol), DataSource)
                {
                    TradePrice = decimal.Parse(treadeupdate.Price, NumberStyles.Any, new CultureInfo("en-US")),
                    Size       = decimal.Parse(treadeupdate.Quantity, NumberStyles.Any, new CultureInfo("en-US")),
                    Occured    = occuredutc,
                    TimeZone   = TimeZone.Utc
                });
            }

            //Return what we have
            return(toreturn.ToArray());
        }
        public async Task <TrendDirection> CheckTrendAsync(string tradingPair, CandleModel currentCandle)
        {
            var shortEmaValue  = _shortEmaIndicator.GetIndicatorValue(currentCandle).IndicatorValue;
            var longEmaValue   = _longEmaIndicator.GetIndicatorValue(currentCandle).IndicatorValue;
            var macdValue      = Math.Round(shortEmaValue - longEmaValue, 4);
            var signalEmaValue = Math.Round(_signalEmaIndicator.GetIndicatorValue(macdValue).IndicatorValue, 4);
            var histogramValue = Math.Round(macdValue - signalEmaValue, 4);

            var ichimokuCloudValue = _ichimokuCloudIndicator.GetIndicatorValue(currentCandle);

            var ssa = ichimokuCloudValue.IchimokuCloud?.SenkouSpanAValue;
            var ssb = ichimokuCloudValue.IchimokuCloud?.SenkouSpanBValue;

            DepthModel depth = null;

            if (ichimokuCloudValue.IchimokuCloud != null)
            {
                depth = await _exchangeProvider.GetDepth(tradingPair);
            }

            var bid      = depth?.Bids.First(f => f.Quantity == depth.Bids.Max(b => b.Quantity));
            var ask      = depth?.Asks.First(f => f.Quantity == depth.Asks.Max(b => b.Quantity));
            var bidPrice = bid?.Price ?? Math.Round(currentCandle.ClosePrice, 4);
            var askPrice = ask?.Price ?? Math.Round(currentCandle.ClosePrice, 4);

            var bidPercentage = Math.Round((currentCandle.ClosePrice / bidPrice) * (decimal)100.0 - (decimal)100.0, 2);
            var askPercentage = Math.Round((currentCandle.ClosePrice / askPrice) * (decimal)100.0 - (decimal)100.0, 2);

            Console.WriteLine($"DateTs: {currentCandle.StartDateTime:s}; " +
                              $"MACD Value: {macdValue}; " +
                              $"SSA/SSB: {ssa}/{ssb}; " +
                              $"Bids price/qty/%: {bid}/{bidPercentage}%; " +
                              $"Asks price/qty/%: {ask}/{askPercentage}%; " +
                              $"Close price: {Math.Round(currentCandle.ClosePrice, 4)};");

            _volumenQueue.Enqueue(currentCandle.Volume);

            if (!_lastMacd.HasValue || _lastMacd == 0)
            {
                _lastMacd       = macdValue;
                _lastClosePrice = currentCandle.ClosePrice;
                _macdDirection  = macdValue < 0 ? MacdDirection.LessThanZero : MacdDirection.GreaterThanZero;
                return(await Task.FromResult(TrendDirection.None));
            }

            if (_lastMacd < 0 && macdValue >= 0)
            {
                if (_macdSwitch)
                {
                    _maxMacd = 0;
                }
                else
                {
                    _macdSwitch = true;
                }
            }

            if (_lastMacd > 0 && macdValue <= 0)
            {
                if (_macdSwitch)
                {
                    _minMacd = 0;
                }
                else
                {
                    _macdSwitch = true;
                }
            }

            if (macdValue < 0 && macdValue < _minMacd)
            {
                _minMacd           = macdValue;
                _minMacdClosePrice = currentCandle.ClosePrice;
            }

            if (macdValue > 0 && macdValue > _maxMacd)
            {
                _maxMacd           = macdValue;
                _maxMacdClosePrice = currentCandle.ClosePrice;
            }

            // wait 0.5 hour
            if (_candleCount <= 30)
            {
                _candleCount++;
                if (macdValue < 0 && macdValue < _minWarmupMacd)
                {
                    _minWarmupMacd = macdValue;
                }
                Console.WriteLine($"Min warmup Macd: {_minWarmupMacd}");
                return(await Task.FromResult(TrendDirection.None));
            }

            if (_lastTrend == TrendDirection.Short)
            {
                if (macdValue > 0 && _stopTrading)
                {
                    _stopTrading = false;
                }

                if (macdValue < 0 && macdValue < _lastMacd)
                {
                    _maxOrMinMacd = macdValue;
                }

                //var diffPreviousMacd = _maxOrMinMacd - macdValue;
                if (_stopTrading == false &&
                    macdValue < _options.BuyThreshold &&
                    currentCandle.ClosePrice > ssa &&
                    currentCandle.ClosePrice > ssb &&
                    currentCandle.CandleType == CandleType.Green
                    //&& diffPreviousMacd < -(decimal)0.2
                    && macdValue > _lastMacd &&
                    currentCandle.ClosePrice > _lastClosePrice)
                {
                    _lastMacd       = macdValue;
                    _lastClosePrice = currentCandle.ClosePrice;

                    _profitEstimationRate = CheckProfitPrecentageAsync(depth, currentCandle.ClosePrice);
                    if (_profitEstimationRate < 0)
                    {
                        return(await Task.FromResult(TrendDirection.None));
                    }

                    _lastTrend    = TrendDirection.Long;
                    _maxOrMinMacd = 0;
                    _lastBuyPrice = currentCandle.ClosePrice;
                }
                else
                {
                    _lastMacd       = macdValue;
                    _lastClosePrice = currentCandle.ClosePrice;
                    return(await Task.FromResult(TrendDirection.None));
                }
            }
            else if (_lastTrend == TrendDirection.Long)
            {
                if (macdValue > 0 && macdValue > _lastMacd)
                {
                    _maxOrMinMacd = macdValue;
                }

                if (macdValue < 0)
                {
                    _maxOrMinMacd = 0;
                }

                var stopPercentage   = 1 - _profitEstimationRate / (decimal)100.0;                  //1 - (_macdRate - (decimal)0.4) / 100; //(decimal) 0.97;
                var profitPercentage = 1 + (_profitEstimationRate + (decimal)0.4) / (decimal)100.0; //1 + (_macdRate + (decimal)0.4) / 100; //(decimal) 1.038;
                //var diffPreviousMacd = _maxOrMinMacd - macdValue;
                if (_lastMacd > macdValue
                    //&& diffPreviousMacd > (decimal)1.0
                    && currentCandle.ClosePrice > _lastBuyPrice * profitPercentage ||
                    currentCandle.ClosePrice < _lastBuyPrice * stopPercentage)
                {
                    Console.WriteLine($"Stop percentage: {stopPercentage}; Profit percentage: {profitPercentage}");
                    _lastTrend      = TrendDirection.Short;
                    _maxOrMinMacd   = 0;
                    _stopTrading    = true;
                    _lastMacd       = macdValue;
                    _lastClosePrice = currentCandle.ClosePrice;
                }
                else
                {
                    _lastMacd       = macdValue;
                    _lastClosePrice = currentCandle.ClosePrice;
                    return(await Task.FromResult(TrendDirection.None));
                }
            }

            return(await Task.FromResult(_lastTrend));
        }
Example #5
0
 public void Init(DepthModel model)
 {
     ChangeDepthPanel(model.depth);
 }