Пример #1
0
        public async Task <OrderBook> GetOrderBookAsync(OrderBookContext context)
        {
            var api      = ApiProvider.GetApi(context);
            var pairCode = context.Pair.ToTicker(this, "").ToLower();

            var r = await api.GetOrderBookAsync(pairCode).ConfigureAwait(false);

            var orderBook = new OrderBook(Network, context.Pair);

            var date = r.timestamp.ToUtcDateTime();

            var asks = context.MaxRecordsCount.HasValue ? r.asks.Take(context.MaxRecordsCount.Value / 2) : r.asks;
            var bids = context.MaxRecordsCount.HasValue ? r.bids.Take(context.MaxRecordsCount.Value / 2) : r.bids;

            foreach (var i in bids.Select(GetBidAskData))
            {
                orderBook.Add(new OrderBookRecord(OrderType.Bid, new Money(i.Price, context.Pair.Asset2), i.Amount));
            }

            foreach (var i in asks.Select(GetBidAskData))
            {
                orderBook.Add(new OrderBookRecord(OrderType.Ask, new Money(i.Price, context.Pair.Asset2), i.Amount));
            }

            return(orderBook);
        }
Пример #2
0
        public async Task <OrderBook> GetOrderBookAsync(OrderBookContext context)
        {
            var api      = ApiProvider.GetApi(context);
            var pairCode = context.Pair.ToTicker(this, '_');

            var r = context.MaxRecordsCount.HasValue ? await api.GetOrderBookAsync(pairCode, context.MaxRecordsCount.Value / 2).ConfigureAwait(false) : await api.GetOrderBookAsync(pairCode).ConfigureAwait(false);

            if (r.bids == null || r.asks == null)
            {
                throw new NoAssetPairException(context.Pair, this);
            }

            var orderBook = new OrderBook(Network, context.Pair);

            foreach (var i in r.bids)
            {
                orderBook.Add(new OrderBookRecord(OrderType.Bid, new Money(i[0], context.Pair.Asset2), i[1]));
            }

            foreach (var i in r.asks)
            {
                orderBook.Add(new OrderBookRecord(OrderType.Ask, new Money(i[0], context.Pair.Asset2), i[1]));
            }

            return(orderBook);
        }
Пример #3
0
        private async Task <OrderBook> GetOrderBookLocalAsync(IKrakenApi api, AssetPair assetPair, int?maxCount)
        {
            var pair       = assetPair;
            var remotePair = new AssetPair(pair.Asset1.ToRemoteCode(this), pair.Asset2.ToRemoteCode(this));

            var r = await api.GetOrderBookAsync(remotePair.ToTicker(this), maxCount ?? 0).ConfigureAwait(false);

            CheckResponseErrors(r);

            var data      = r.result.FirstOrDefault();
            var orderBook = new OrderBook(Network, assetPair);

            var asks = maxCount.HasValue ? data.Value.asks.Take(maxCount.Value / 2).ToArray() : data.Value.asks;
            var bids = maxCount.HasValue ? data.Value.bids.Take(maxCount.Value / 2).ToArray() : data.Value.bids;

            foreach (var i in bids.Select(GetBidAskData))
            {
                orderBook.Add(OrderType.Bid, i.Price, i.Volume);
            }

            foreach (var i in asks.Select(GetBidAskData))
            {
                orderBook.Add(OrderType.Ask, i.Price, i.Volume);
            }

            return(orderBook);
        }
        public Task HandleExternalOrderBookAsync(
            string source,
            string assetPairId,
            IReadOnlyCollection <Order> buyOrders,
            IReadOnlyCollection <Order> sellOrders)
        {
            if (!_matchExternalOrderBooks)
            {
                return(Task.CompletedTask);
            }

            OrderBook orderBook = _orderBooks.GetOrAdd(assetPairId, new OrderBook(assetPairId, _balancesService));

            orderBook.Remove(o => o.IsExternal);

            foreach (Order order in buyOrders.OrderByDescending(o => o.Price))
            {
                orderBook.Add(order);
            }

            foreach (Order order in sellOrders.OrderBy(o => o.Price))
            {
                orderBook.Add(order);
            }

            return(PublishOrderBookAsync(orderBook));
        }
Пример #5
0
        public async Task <OrderBook> GetOrderBookAsync(OrderBookContext context)
        {
            var api      = ApiProvider.GetApi(context);
            var pairCode = context.Pair.ToTicker(this, '_');

            var r = await api.GetBoardAsync(pairCode).ConfigureAwait(false);

            var bids = context.MaxRecordsCount.HasValue
                ? r.bids.Take(context.MaxRecordsCount.Value / 2)
                : r.bids;

            var asks = context.MaxRecordsCount.HasValue
                ? r.asks.Take(context.MaxRecordsCount.Value / 2)
                : r.asks;

            var orderBook = new OrderBook(Network, context.Pair);

            foreach (var i in bids)
            {
                orderBook.Add(new OrderBookRecord(OrderType.Bid, new Money(i.price, context.Pair.Asset2), i.size));
            }

            foreach (var i in asks)
            {
                orderBook.Add(new OrderBookRecord(OrderType.Ask, new Money(i.price, context.Pair.Asset2), i.size));
            }

            return(orderBook);
        }
Пример #6
0
        public async Task <OrderBook> GetOrderBookAsync(OrderBookContext context)
        {
            CheckOrderRecordsInputNumber(context.MaxRecordsCount);

            var api      = ApiProvider.GetApi(context);
            var pairCode = context.Pair.ToTicker(this, "");

            var r = context.MaxRecordsCount.HasValue
                ? await api.GetOrderBookAsync(pairCode, context.MaxRecordsCount.Value / 2).ConfigureAwait(false)
                : await api.GetOrderBookAsync(pairCode).ConfigureAwait(false);

            var orderBook = new OrderBook(Network, context.Pair);

            foreach (var i in r.bids.Select(GetOrderBookRecordData))
            {
                orderBook.Add(new OrderBookRecord(OrderType.Bid, new Money(i.Price, context.Pair.Asset2), i.Volume));
            }

            foreach (var i in r.asks.Select(GetOrderBookRecordData))
            {
                orderBook.Add(new OrderBookRecord(OrderType.Ask, new Money(i.Price, context.Pair.Asset2), i.Volume));
            }

            return(orderBook);
        }
Пример #7
0
        public void TestTradeCallbacks()
        {
            var order0 = new SimpleOrder(false, 3250, 100);
            var order1 = new SimpleOrder(true, 3250, 800);
            var order2 = new SimpleOrder(false, 3230, 0);
            var order3 = new SimpleOrder(false, 3240, 200);
            var order4 = new SimpleOrder(true, 3250, 600);

            var listener   = new TradeCbListener();
            var order_book = new OrderBook();

            order_book.SetTradeListener(listener);
            // Add order, should be accepted
            order_book.Add(order0);
            Assert.Equal(0, listener.quantities_.Count);
            listener.Reset();
            // Add matching order, should result in a trade
            order_book.Add(order1);
            Assert.Equal(1, listener.quantities_.Count);
            Assert.Equal(1, listener.costs_.Count);
            Assert.Equal((Quantity)100, listener.quantities_[0]);
            Assert.Equal(100 * 3250, listener.costs_[0]);
            listener.Reset();
            // Add invalid order, should be rejected
            order_book.Add(order2);
            Assert.Equal(0, listener.quantities_.Count);
            listener.Reset();
            // Cancel only valid order, should be cancelled
            order_book.Cancel(order1);
            Assert.Equal(0, listener.quantities_.Count);
            listener.Reset();
            // Cancel filled order, should be rejected
            order_book.Cancel(order0);
            Assert.Equal(0, listener.quantities_.Count);
            listener.Reset();
            // Add a new order and replace it, should be replaced
            order_book.Add(order3);
            order_book.Replace(order3, 0, 3250);
            Assert.Equal(0, listener.quantities_.Count);
            listener.Reset();
            // Add matching order, should be accepted, followed by a fill
            order_book.Add(order4);
            Assert.Equal(1, listener.quantities_.Count);
            Assert.Equal(1, listener.costs_.Count);
            listener.Reset();
            // Replace matched order, with too large of a size decrease, replace
            // should be rejected
            order_book.Replace(order3, -500, 0);
            Assert.Equal(0, listener.quantities_.Count);
        }
Пример #8
0
        public void TestOrderCallbacks()
        {
            var order0 = new SimpleOrder(false, 3250, 100);
            var order1 = new SimpleOrder(true, 3250, 800);
            var order2 = new SimpleOrder(false, 3230, 0);
            var order3 = new SimpleOrder(false, 3240, 200);
            var order4 = new SimpleOrder(true, 3250, 600);

            var listener   = new OrderCbListener();
            var order_book = new OrderBook();

            order_book.SetOrderListener(listener);
            // Add order, should be accepted
            order_book.Add(order0);
            Assert.AreEqual(1, listener.accepts_.Count);
            listener.Reset();
            // Add matching order, should be accepted, followed by a fill
            order_book.Add(order1);
            Assert.AreEqual(1, listener.accepts_.Count);
            Assert.AreEqual(1, listener.fills_.Count);
            listener.Reset();
            // Add invalid order, should be rejected
            order_book.Add(order2);
            Assert.AreEqual(1, listener.rejects_.Count);
            listener.Reset();
            // Cancel only valid order, should be cancelled
            order_book.Cancel(order1);
            Assert.AreEqual(1, listener.cancels_.Count);
            listener.Reset();
            // Cancel filled order, should be rejected
            order_book.Cancel(order0);
            Assert.AreEqual(1, listener.cancel_rejects_.Count);
            listener.Reset();
            // Add a new order and replace it, should be replaced
            order_book.Add(order3);
            order_book.Replace(order3, 0, 3250);
            Assert.AreEqual(1, listener.accepts_.Count);
            Assert.AreEqual(1, listener.replaces_.Count);
            listener.Reset();
            // Add matching order, should be accepted, followed by a fill
            order_book.Add(order4);
            Assert.AreEqual(1, listener.accepts_.Count);
            Assert.AreEqual(1, listener.fills_.Count);
            listener.Reset();
            // Replace matched order, with too large of a size decrease, replace
            // should be rejected
            order_book.Replace(order3, -500, 0);
            Assert.AreEqual(0, listener.replaces_.Count);
            Assert.AreEqual(1, listener.replace_rejects_.Count);
        }
Пример #9
0
        internal static bool AddAndVerify(OrderBook orderBook, IOrder order, bool matchExpected, bool completeExpected = false,
                                          OrderConditions conditions = 0)
        {
            var matched = orderBook.Add(order, conditions);

            if (matched == matchExpected)
            {
                if (completeExpected)
                {
                    return(OrderState.Complete == (order as SimpleOrder)?.State);
                }
                else if ((conditions & OrderConditions.ImmediateOrCancel) != 0)
                {
                    return(OrderState.Cancelled == (order as SimpleOrder)?.State);
                }
                else
                {
                    return(OrderState.Accepted == (order as SimpleOrder)?.State);
                }
            }
            else
            {
                return(false);
            }
        }
        public async Task <Guid> CreateOrderAsync(Order order)
        {
            _clientOrdersService.Add(order);

            OrderBook orderBook = _orderBooks.GetOrAdd(order.Pair, new OrderBook(order.Pair, _balancesService));

            orderBook.Add(order);

            await PublishOrderBookAsync(orderBook);

            return(order.Id);
        }
        public void ClientHasInsufficientFunds()
        {
            var balancesService = new Mock <IBalancesService>();

            balancesService.Setup(x => x.UserHasEnoughBalanceForOrder(It.IsAny <Order>())).Returns(false);

            var ob = new OrderBook(Pair, balancesService.Object);

            var sell = Order.CreateLimit(ClientId1, TradeType.Sell, Pair, 100, 60);

            Assert.Throws <InsufficientBalanceException>(() => ob.Add(sell));
            Assert.Equal(OrderStatus.Rejected, sell.OrderStatus);
        }
    static void Main(string[] args)
    {
        //create order book
        OrderBook orderBook = new OrderBook();

        //start pumping orders
        //that will be concurrently processed by sweeper thread
        for (int ctr = 0; ctr <= 10; ctr++)
        {
            orderBook.Add(new Order());
        }
        Console.ReadLine();
    }
Пример #13
0
        public async Task <OrderBook> GetOrderBookAsync(OrderBookContext context)
        {
            var api = ApiProvider.GetApi(context);

            var pairCode = context.Pair.ToTicker(this, "");

            var r = context.MaxRecordsCount.HasValue
                ? await api.GetOrderBookAsync(pairCode, context.MaxRecordsCount.Value).ConfigureAwait(false)
                : await api.GetOrderBookAsync(pairCode, 0).ConfigureAwait(false);

            var buyAction  = "buy";
            var sellAction = "sell";

            var buys = context.MaxRecordsCount.HasValue
                ? r.Where(x => x.side.ToLower().Equals(buyAction)).OrderBy(x => x.id)
                       .Take(context.MaxRecordsCount.Value / 2).ToList()
                : r.Where(x => x.side.ToLower().Equals(buyAction)).OrderBy(x => x.id).ToList();

            var sells = context.MaxRecordsCount.HasValue
                ? r.Where(x => x.side.ToLower().Equals(sellAction)).OrderBy(x => x.id)
                        .Take(context.MaxRecordsCount.Value / 2).ToList()
                : r.Where(x => x.side.ToLower().Equals(sellAction)).OrderBy(x => x.id).ToList();

            var orderBook = new OrderBook(Network, context.Pair);

            foreach (var i in buys)
            {
                orderBook.Add(new OrderBookRecord(OrderType.Bid, new Money(i.price, context.Pair.Asset2), i.size));
            }

            foreach (var i in sells)
            {
                orderBook.Add(new OrderBookRecord(OrderType.Ask, new Money(i.price, context.Pair.Asset2), i.size));
            }

            return(orderBook);
        }
Пример #14
0
        /// <summary>Determine the exchange rate based on volume</summary>
        private static OrderBook MergeRates(OrderBook rates, OrderBook offers, Unit <decimal> balance, bool invert)        // Worker thread context
        {
            // 'rates' is a table of volumes in the current coin currency (i.e. the current
            // coin in the loop) along with the accumulated exchange rate for each volume.
            // 'orders' is a table of 'Base' currency volumes and the offer prices for
            // converting those volumes to 'Quote' currency.
            // If 'invert' is true, the 'orders' table is the offers for converting Quote
            // currency to Base currency, however the volumes and prices are still in Base
            // and Quote respectively.
            var new_coin = invert ? offers.Base : offers.Quote;
            var ret      = new OrderBook(new_coin, new_coin, rates.TradeType);

            // Volume accumulators for the 'rates' and 'orders' order books.
            var R_vol = 0m._(rates.Base.Symbol);
            var O_vol = 0m._(rates.Base.Symbol);

            // The maximum volume available to trade is the minimum of the 'rates' and 'orders'
            // volumes, hence this loop ends when the last order in either set is reached.
            for (int r = 0, o = 0; r != rates.Count && o != offers.Count;)
            {
                var rate = rates[r];
                var offr = offers[o];

                // Get the offer price and volume to convert to the current coin currency
                var price  = invert ? 1m / offr.PriceQ2B : offr.PriceQ2B;
                var volume = invert ? offr.PriceQ2B * offr.AmountBase : offr.AmountBase;

                // Get the volume available to be traded at 'price'
                var vol0 = rate.AmountBase < volume ? rate.AmountBase : volume;

                // Convert this volume to the new currency using 'price'
                var vol1 = vol0 * price;

                // Record the volume and the combined rate
                ret.Add(new Offer(rate.PriceQ2B * price, vol1), validate: false);

                // Move to the next order in the set with the lowest accumulative volume.
                // If the same accumulative volume is in both sets, move to the next order in both sets.
                // Need to be careful with overflow, because special case values use decimal.MaxValue.
                // Only advance to the next order if the accumulative volume is less than MaxValue.
                var adv_R =
                    (R_vol < decimal.MaxValue - rate.AmountBase) &&                     // if 'R_vol + rate.AmountBase' does not overflow
                    (R_vol - O_vol <= volume - rate.AmountBase);                        // and 'R_vol + rate.AmountBase' <= 'O_vol + volume'
                var adv_O =
                    (O_vol < decimal.MaxValue - volume) &&                              // if 'O_vol + volume' does not overflow
                    (R_vol - O_vol >= volume - rate.AmountBase);                        // and 'R_vol + rate.AmountBase' >= 'O_vol + volume'
                if (adv_R)
                {
                    ++r; R_vol += rate.AmountBase;
                }
                if (adv_O)
                {
                    ++o; O_vol += volume;
                }
                if (!adv_R && !adv_O)
                {
                    break;
                }

                // Don't bother calculating for volumes that exceed the current balance
                if (rates.Count > 5 && R_vol > balance)
                {
                    break;
                }
            }

            return(ret);
        }