Ejemplo n.º 1
0
        public void DOMMidprice()
        {
            // Arrange
            const decimal BUY_PRICE         = 6004.5m;
            const decimal SELL_PRICE        = 6016.0m;
            const decimal EXPECTED_MIDPRICE = 6010.25m;
            const decimal LOTS = 100m;

            var bids = new List <Tuple <decimal, decimal> >();

            bids.Add(new Tuple <decimal, decimal>(BUY_PRICE - 10m, LOTS));
            bids.Add(new Tuple <decimal, decimal>(BUY_PRICE, LOTS));
            bids.Add(new Tuple <decimal, decimal>(BUY_PRICE - 100m, LOTS));

            var asks = new List <Tuple <decimal, decimal> >();

            asks.Add(new Tuple <decimal, decimal>(SELL_PRICE + 45m, LOTS));
            asks.Add(new Tuple <decimal, decimal>(SELL_PRICE, LOTS));
            asks.Add(new Tuple <decimal, decimal>(SELL_PRICE + 167m, LOTS));
            var dom = new SimpleDOM(bids, asks);
            // Act
            var d = new DOMBalance(Instrument.XBTUSD(), dom, 0.1, 100m);

            // Asert
            Assert.AreEqual(EXPECTED_MIDPRICE, d.MidPrice, $"Incorrect mid-price for spread {BUY_PRICE}..{SELL_PRICE}");
        }
Ejemplo n.º 2
0
        public void FilterOutFarOrders()
        {
            // Arrange
            const decimal EXPECTED_MIDPRICE            = 4510.25m;
            const double  RADIUS_FROM_MIDPRICE_PERCENT = 0.5;                                                                        // 50% from mid price
            const decimal BUY_PRICE          = EXPECTED_MIDPRICE - EXPECTED_MIDPRICE * (decimal)(RADIUS_FROM_MIDPRICE_PERCENT)-0.5m; // 0.5 ticks below lower border
            const decimal SELL_PRICE         = EXPECTED_MIDPRICE + EXPECTED_MIDPRICE * (decimal)(RADIUS_FROM_MIDPRICE_PERCENT)+0.5m; // 0.5 ticks over upper border
            const decimal EXPECTED_LIQUIDITY = 47m;
            const decimal LOTS = 100m;

            var bids = new List <Tuple <decimal, decimal> >();

            bids.Add(new Tuple <decimal, decimal>(BUY_PRICE, LOTS));
            var asks = new List <Tuple <decimal, decimal> >();

            asks.Add(new Tuple <decimal, decimal>(SELL_PRICE, LOTS));
            var dom = new SimpleDOM(bids, asks);
            // Act
            var d = new DOMBalance(Instrument.XBTUSD(), dom, RADIUS_FROM_MIDPRICE_PERCENT, EXPECTED_LIQUIDITY);

            // Asert
            Assert.AreEqual(EXPECTED_MIDPRICE, d.MidPrice, $"Incorrect mid-price for spread {BUY_PRICE}..{SELL_PRICE}");

            // Since all far orders are filtered out, so we need to create buy and sell orders to make liquidity
            Assert.AreEqual(0m, d.SellAmount, "Sell not filtered out");
            Assert.AreEqual(0m, d.BuyAmount, "Buy not filtered out");
            Assert.AreEqual(EXPECTED_LIQUIDITY / 2.0m, d.BuyDisbalance, "Expected to buy");
            Assert.AreEqual(EXPECTED_LIQUIDITY / 2.0m, d.SellDisbalance, "Expected to sell");
        }
Ejemplo n.º 3
0
        public void SingleSellMidprice()
        {
            // Arrange
            const decimal PRICE = 1.2345m;
            const decimal LOTS  = 100m;

            var bids = new List <Tuple <decimal, decimal> >();
            var asks = new List <Tuple <decimal, decimal> >();

            asks.Add(new Tuple <decimal, decimal>(PRICE, LOTS));
            var dom = new SimpleDOM(bids, asks);
            // Act
            var d = new DOMBalance(Instrument.XBTUSD(), dom, 0.1, 100m);

            // Asert
            Assert.AreEqual(PRICE, d.MidPrice, "Incorrect mid-price");
        }
Ejemplo n.º 4
0
        public void OppositeOrderToSingleSell()
        {
            // Arrange
            const decimal PRICE    = 6056.0m;
            const int     LOT_SIZE = 2;
            const decimal REQUIRED_LIQUIDITY_IN_DOM = PRICE * LOT_SIZE * 2; // 2 orders with the same price*vol

            var bids = new List <Tuple <decimal, decimal> >();
            var asks = new List <Tuple <decimal, decimal> >();

            asks.Add(new Tuple <decimal, decimal>(PRICE, LOT_SIZE));
            var dom = new SimpleDOM(bids, asks);
            // Act
            var d = new DOMBalance(Instrument.XBTUSD(), dom, 1, REQUIRED_LIQUIDITY_IN_DOM);

            // Asert
            Assert.AreEqual(PRICE, d.MidPrice, "Incorrect mid-price");
            Assert.AreEqual(0m, d.BuyAmount, "Incorrect buy amount");
            Assert.AreEqual(0m, d.SellDisbalance, "Not expected to sell");

            Assert.AreEqual(PRICE * LOT_SIZE, d.SellAmount, "Incorrect sell amount");
            Assert.AreEqual(PRICE * LOT_SIZE, d.BuyDisbalance, "Expected to buy");
        }
Ejemplo n.º 5
0
        public void SingleLargeSell()
        {
            // Arrange
            const decimal PRICE = 6056.0m;
            const int     LOTS  = 2;
            const decimal REQUIRED_LIQUIDITY_IN_DOM = PRICE * LOTS * 0.8m;

            var bids = new List <Tuple <decimal, decimal> >();
            var asks = new List <Tuple <decimal, decimal> >();

            asks.Add(new Tuple <decimal, decimal>(PRICE, LOTS));
            var dom = new SimpleDOM(bids, asks);
            // Act
            var d = new DOMBalance(Instrument.XBTUSD(), dom, 1, REQUIRED_LIQUIDITY_IN_DOM);

            // Asert
            Assert.AreEqual(PRICE, d.MidPrice, "Incorrect mid-price");
            Assert.AreEqual(0m, d.BuyAmount, "Incorrect buy amount");
            Assert.Less(d.SellDisbalance, 0m, "Sell disbalance shall be negative (need close/eat some sell LMTs)");

            Assert.AreEqual(PRICE * LOTS, d.SellAmount, "Incorrect sell amount");
            Assert.AreEqual(REQUIRED_LIQUIDITY_IN_DOM / 2.0m, d.BuyDisbalance, "Expected to buy");
        }
Ejemplo n.º 6
0
        /// <summary>
        /// Calcs balance and mid-price for the book. Provided bids and asks shall not contain own order.
        /// </summary>
        /// <param name="instr">Instrument</param>
        /// <param name="radiusFromMidpricePercent">Percent around mid-price to filter asks and bids</param>
        /// <param name="requiredLiquidity">Required liquidity to have in DOM within radiusFromMidpricePercent</param>
        public DOMBalance(Instrument instr, SimpleDOM dom, double radiusFromMidpricePercent, decimal requiredLiquidity)
        {
            if (dom == null)
            {
                throw new ArgumentNullException(nameof(dom));
            }

            IList <Tuple <decimal, decimal> > bids = dom.Bids;
            IList <Tuple <decimal, decimal> > asks = dom.Asks;

            if (requiredLiquidity < 0)
            {
                throw new ArgumentOutOfRangeException();
            }
            if (radiusFromMidpricePercent <= 0)
            {
                throw new ArgumentOutOfRangeException();
            }
            if (bids == null || asks == null)
            {
                throw new ArgumentNullException("Please provide empty list instead of null");
            }

            Instrument = instr;

            // BBA
            var     bestBid  = bids.OrderBy(b => b.Item1).LastOrDefault();
            decimal?bidPrice = null;

            if (bestBid != null)
            {
                bidPrice = bestBid.Item1;
            }

            var     bestAsk  = asks.OrderBy(b => b.Item1).FirstOrDefault();
            decimal?askPrice = null;

            if (bestAsk != null)
            {
                askPrice = bestAsk.Item1;
            }

            // Mid price
            if (bidPrice == null && askPrice != null)
            {
                MidPrice = askPrice;
            }
            if (bidPrice != null && askPrice == null)
            {
                MidPrice = bidPrice;
            }
            if (bidPrice != null && askPrice != null)
            {
                MidPrice = (askPrice + bidPrice) / 2.0m;
            }

            if (!MidPrice.HasValue)
            {
                return;
            }

            foreach (var b in bids)
            {
                if (b.Item1 >= MidPrice - MidPrice * (decimal)radiusFromMidpricePercent)
                {
                    BuyAmount += b.Item1 * b.Item2;
                }
            }

            foreach (var a in asks)
            {
                if (a.Item1 <= MidPrice + MidPrice * (decimal)radiusFromMidpricePercent)
                {
                    SellAmount += a.Item1 * a.Item2;
                }
            }

            BuyDisbalance  = requiredLiquidity / 2.0m - BuyAmount;
            SellDisbalance = requiredLiquidity / 2.0m - SellAmount;
        }