Esempio n. 1
0
        public Task <InternalOrderBookModel> GetInternalAsync(string assetPair)
        {
            InternalOrderBook orderBook = _internalOrderBookService.GetByAssetPair(assetPair);

            if (orderBook == null)
            {
                throw new ValidationApiException(HttpStatusCode.NotFound, "Order book does not exist");
            }

            return(Task.FromResult(Mapper.Map <InternalOrderBookModel>(orderBook)));
        }
Esempio n. 2
0
        private static bool AreEqual(InternalOrderBook a, InternalOrderBook b)
        {
            if (a == null && b == null)
            {
                return(true);
            }

            if (a == null || b == null)
            {
                return(false);
            }

            if (a.AssetPair != b.AssetPair)
            {
                return(false);
            }

            return(AreEqual(a.SellLevels, b.SellLevels) && AreEqual(a.BuyLevels, b.BuyLevels));
        }
        public Task UpdateAsync(string assetPair)
        {
            string exchangeName = _settingsService.GetExchangeName();

            AssetPairModel assetPairSettings = _marketInstrumentService.GetAssetPair(assetPair, exchangeName);

            if (assetPairSettings == null)
            {
                throw new FailedOperationException("Asset pair not found");
            }

            IReadOnlyList <ExternalOrderBook> externalOrderBooks = _externalOrderBookService.GetByAssetPair(assetPair);

            var sellLevels = new Dictionary <decimal, decimal>();

            decimal ask = decimal.MaxValue;

            foreach (ExternalOrderBook externalOrderBook in externalOrderBooks)
            {
                foreach (ExternalOrderBookLevel priceLevel in externalOrderBook.SellLevels)
                {
                    decimal price = priceLevel.Price.TruncateDecimalPlaces(assetPairSettings.PriceAccuracy, true);

                    if (!sellLevels.ContainsKey(price))
                    {
                        sellLevels[price] = 0;
                    }

                    sellLevels[price] += priceLevel.Volume;

                    if (ask > price)
                    {
                        ask = price;
                    }
                }
            }

            var buyLevels = new Dictionary <decimal, decimal>();

            decimal bid = decimal.MinValue;

            foreach (ExternalOrderBook externalOrderBook in externalOrderBooks)
            {
                foreach (ExternalOrderBookLevel priceLevel in externalOrderBook.BuyLevels)
                {
                    decimal price = priceLevel.Price.TruncateDecimalPlaces(assetPairSettings.PriceAccuracy);

                    if (!buyLevels.ContainsKey(price))
                    {
                        buyLevels[price] = 0;
                    }

                    buyLevels[price] += priceLevel.Volume;

                    if (bid < price)
                    {
                        bid = price;
                    }
                }
            }

            if (ask <= bid)
            {
                decimal mid = Math.Round((ask + bid) / 2, assetPairSettings.PriceAccuracy);

                var basisPoint = (decimal)Math.Pow(.1, assetPairSettings.PriceAccuracy);

                ask = mid + basisPoint;

                bid = mid - basisPoint;
            }

            var sellOrderBookLevels = new List <OrderBookLevel>();

            var bestSellLevel = new OrderBookLevel {
                Price = ask
            };

            foreach (var(price, volume) in sellLevels)
            {
                if (price <= ask)
                {
                    bestSellLevel.Volume += volume;
                }
                else
                {
                    sellOrderBookLevels.Add(new OrderBookLevel {
                        Price = price, Volume = volume
                    });
                }
            }

            if (bestSellLevel.Volume > 0)
            {
                sellOrderBookLevels.Add(bestSellLevel);
            }

            var buyOrderBookLevels = new List <OrderBookLevel>();

            var bestBuyLevel = new OrderBookLevel {
                Price = bid
            };

            foreach (var(price, volume) in buyLevels)
            {
                if (price >= bid)
                {
                    bestBuyLevel.Volume += volume;
                }
                else
                {
                    buyOrderBookLevels.Add(new OrderBookLevel {
                        Price = price, Volume = volume
                    });
                }
            }

            if (bestBuyLevel.Volume > 0)
            {
                buyOrderBookLevels.Add(bestBuyLevel);
            }

            var internalOrderBook = new InternalOrderBook
            {
                AssetPair  = assetPairSettings.Name,
                Timestamp  = DateTime.UtcNow,
                SellLevels = sellOrderBookLevels
                             .OrderBy(o => o.Price)
                             .ToList(),
                BuyLevels = buyOrderBookLevels
                            .OrderByDescending(o => o.Price)
                            .ToList()
            };

            _orderBooks.AddOrUpdate(assetPair, internalOrderBook, (key, value) => internalOrderBook);

            return(Task.CompletedTask);
        }
Esempio n. 4
0
        public async Task Create_Order_Book_With_Out_Arbitrage()
        {
            // arrange

            _assetPairs.Add(new AssetPairModel
            {
                Name          = "BTCUSD",
                PriceAccuracy = 3
            });

            _externalOrderBooks.AddRange(new[]
            {
                new ExternalOrderBook
                {
                    Exchange   = "Exchange1",
                    AssetPair  = "BTCUSD",
                    Timestamp  = DateTime.UtcNow,
                    SellLevels = new List <ExternalOrderBookLevel>
                    {
                        new ExternalOrderBookLevel {
                            Price = 3.9626635m, Volume = 3
                        },
                        new ExternalOrderBookLevel {
                            Price = 2.1341931m, Volume = 2
                        },
                        new ExternalOrderBookLevel {
                            Price = 1.8762345m, Volume = 1
                        }
                    },
                    BuyLevels = new List <ExternalOrderBookLevel>
                    {
                        new ExternalOrderBookLevel {
                            Price = 1.5761689m, Volume = 1
                        },
                        new ExternalOrderBookLevel {
                            Price = 1.0341931m, Volume = 2
                        },
                        new ExternalOrderBookLevel {
                            Price = 0.5626635m, Volume = 3
                        }
                    }
                },
                new ExternalOrderBook
                {
                    Exchange   = "Exchange2",
                    AssetPair  = "BTCUSD",
                    Timestamp  = DateTime.UtcNow,
                    SellLevels = new List <ExternalOrderBookLevel>
                    {
                        new ExternalOrderBookLevel {
                            Price = 3.963m, Volume = 3
                        },
                        new ExternalOrderBookLevel {
                            Price = 2.136m, Volume = 2
                        },
                        new ExternalOrderBookLevel {
                            Price = 1.877m, Volume = 1
                        }
                    },
                    BuyLevels = new List <ExternalOrderBookLevel>
                    {
                        new ExternalOrderBookLevel {
                            Price = 1.576m, Volume = 1
                        },
                        new ExternalOrderBookLevel {
                            Price = 1.035m, Volume = 2
                        },
                        new ExternalOrderBookLevel {
                            Price = 0.562m, Volume = 3
                        }
                    }
                }
            });

            var expectedInternalOrderBook = new InternalOrderBook
            {
                AssetPair  = "BTCUSD",
                Timestamp  = DateTime.UtcNow,
                SellLevels = new List <OrderBookLevel>
                {
                    new OrderBookLevel {
                        Price = 3.963m, Volume = 6
                    },
                    new OrderBookLevel {
                        Price = 2.136m, Volume = 2
                    },
                    new OrderBookLevel {
                        Price = 2.135m, Volume = 2
                    },
                    new OrderBookLevel {
                        Price = 1.877m, Volume = 2
                    }
                },
                BuyLevels = new List <OrderBookLevel>
                {
                    new OrderBookLevel {
                        Price = 1.576m, Volume = 2
                    },
                    new OrderBookLevel {
                        Price = 1.034m, Volume = 2
                    },
                    new OrderBookLevel {
                        Price = 1.035m, Volume = 2
                    },
                    new OrderBookLevel {
                        Price = 0.562m, Volume = 6
                    }
                }
            };

            // act

            await _service.UpdateAsync("BTCUSD");

            var actualInternalOrderBook = _service.GetByAssetPair("BTCUSD");

            // assert

            Assert.IsTrue(AreEqual(expectedInternalOrderBook, actualInternalOrderBook));
        }