示例#1
0
        private void createNewArbitrage(Game game,
                                        GameSiteRatio homeRatio,
                                        GameSiteRatio drawRatio,
                                        GameSiteRatio awayRatio,
                                        double probability)
        {
            Arbitrage arbitrage = new Arbitrage();

            arbitrage.GameId = game.Id;

            arbitrage.HomeRatio       = homeRatio.HomeRatio;
            arbitrage.HomeRatioSiteId = homeRatio.SiteId;
            arbitrage.DrawRatio       = drawRatio.DrawRatio;
            arbitrage.DrawRatioSiteId = drawRatio.SiteId;
            arbitrage.AwayRatio       = awayRatio.AwayRatio;
            arbitrage.AwayRatioSiteId = awayRatio.SiteId;

            arbitrage.HomeBetPercent = calcBetPercent(homeRatio.HomeRatio, probability);
            arbitrage.DrawBetPercent = calcBetPercent(drawRatio.DrawRatio, probability);
            arbitrage.AwayBetPercent = calcBetPercent(awayRatio.AwayRatio, probability);
            arbitrage.ProfitPercent  = (1 / probability) - 1;

            arbitrage.IsActive = true;
            arbitrage.FindTime = DateTime.Now;

            activeArbitrages.Add(game.Id, arbitrage);
            arbitrageDBManager.Add(arbitrage); // Add to DB
        }
        public void ArbitrageVolume_NoArbitrage_TheSameOrderBook_Test()
        {
            const string exchangeName = "FE";
            var          assetPair    = new AssetPair("BTC", "USD", 8, 8);
            var          timestamp    = DateTime.UtcNow;

            var asks = new List <VolumePrice>
            {
                new VolumePrice(9000, 10),
                new VolumePrice(8999.95m, 7),
                new VolumePrice(8900.12345677m, 3)
            };
            var bids = new List <VolumePrice>
            {
                new VolumePrice(8825, 9),
                new VolumePrice(8823, 5)
            };

            var orderBook1 = new OrderBook(exchangeName, assetPair, bids, asks, timestamp);
            var orderBook2 = new OrderBook(exchangeName, assetPair, bids, asks, timestamp);

            var volume = Arbitrage.GetArbitrageVolumePnL(orderBook1.Bids, orderBook2.Asks);

            Assert.Null(volume);
        }
        public void ArbitrageVolumePnL_Simple1_Test()
        {
            const string exchangeName = "FE";
            var          assetPair    = new AssetPair("BTC", "USD", 8, 8);
            var          timestamp    = DateTime.UtcNow;

            var asks = new List <VolumePrice>
            {
                new VolumePrice(9000, 10),
                new VolumePrice(8999.95m, 7),      // <-
                new VolumePrice(8900.12345677m, 3) // <-
            };

            var bids = new List <VolumePrice>
            {
                new VolumePrice(9000, 9), // <-
                new VolumePrice(8900, 5)
            };

            var bidsOrderBook = new OrderBook(exchangeName, assetPair, bids, new List <VolumePrice>(), timestamp);
            var asksOrderBook = new OrderBook(exchangeName, assetPair, new List <VolumePrice>(), asks, timestamp);

            var volumePnL = Arbitrage.GetArbitrageVolumePnL(bidsOrderBook.Bids, asksOrderBook.Asks);

            Assert.Equal(9, volumePnL?.Volume);
            Assert.Equal(299.92962969m, volumePnL?.PnL);
        }
        public void ArbitrageVolumePnL_Complex1_Test()
        {
            // https://docs.google.com/spreadsheets/d/1plnbQSS-WP6ykTv8wIi_hbAhk_aSz_tllXFIE3jhFpU/edit#gid=0

            const string source    = "FE";
            var          timestamp = DateTime.UtcNow;

            var bids = new List <LimitOrder>
            {
                new LimitOrder("", "", 900, 5),   // <-
                new LimitOrder("", "", 750, 100), // <-
                new LimitOrder("", "", 550, 1)    // <-
            };
            var asks = new List <LimitOrder>
            {
                new LimitOrder("", "", 1000, 10),
                new LimitOrder("", "", 950, 10),
                new LimitOrder("", "", 850, 10), // <-
                new LimitOrder("", "", 800, 10), // <-
                new LimitOrder("", "", 700, 10), // <-
                new LimitOrder("", "", 650, 10), // <-
                new LimitOrder("", "", 600, 10), // <-
                new LimitOrder("", "", 550, 1),  // <-
                new LimitOrder("", "", 500, 10)  // <-
            };

            var bidsOrderBook = new OrderBook(source, _btcusd, bids, new List <LimitOrder>(), timestamp);
            var asksOrderBook = new OrderBook(source, _btcusd, new List <LimitOrder>(), asks, timestamp);

            var volumePnL = Arbitrage.GetArbitrageVolumeAndPnL(bidsOrderBook.Bids, asksOrderBook.Asks);

            Assert.Equal(41, volumePnL?.Volume);
            Assert.Equal(6450, volumePnL?.PnL);
        }
示例#5
0
        public async Task <IHttpActionResult> PutArbitrage(int id, Arbitrage arbitrage)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            if (id != arbitrage.Id)
            {
                return(BadRequest());
            }

            db.Entry(arbitrage).State = EntityState.Modified;

            try
            {
                await db.SaveChangesAsync();
            }
            catch (DbUpdateConcurrencyException)
            {
                if (!ArbitrageExists(id))
                {
                    return(NotFound());
                }
                else
                {
                    throw;
                }
            }

            return(StatusCode(HttpStatusCode.NoContent));
        }
        public void ArbitrageVolumePnL_Simple1_Test()
        {
            const string source    = "FE";
            var          timestamp = DateTime.UtcNow;

            var bids = new List <LimitOrder>
            {
                new LimitOrder("", "", 9000, 9), // <-
                new LimitOrder("", "", 8900, 5)
            };
            var asks = new List <LimitOrder>
            {
                new LimitOrder("", "", 9000, 10),
                new LimitOrder("", "", 8999.95m, 7),      // <-
                new LimitOrder("", "", 8900.12345677m, 3) // <-
            };

            var bidsOrderBook = new OrderBook(source, _btcusd, bids, new List <LimitOrder>(), timestamp);
            var asksOrderBook = new OrderBook(source, _btcusd, new List <LimitOrder>(), asks, timestamp);

            var volumePnL = Arbitrage.GetArbitrageVolumeAndPnL(bidsOrderBook.Bids, asksOrderBook.Asks);

            Assert.Equal(9, volumePnL?.Volume);
            Assert.Equal(299.92962969m, volumePnL?.PnL);
        }
        public void ArbitrageVolumePnL_Simple2_Test()
        {
            var eurgbpOB = new OrderBook("FE", _eurgbp,
                                         new List <LimitOrder> (), // bids
                                         new List <LimitOrder>     // asks
            {
                new LimitOrder(0.90477m, 757921.29m)
            },
                                         DateTime.Now);

            var eurusdOB = new OrderBook("FE", _eurusd,
                                         new List <LimitOrder> // bids
            {
                new LimitOrder(1.16211m, 1923.11m),
                new LimitOrder(0.58117m, 100)
            },
                                         new List <LimitOrder>(), // asks
                                         DateTime.Now);

            var gbpusdOB = new OrderBook("FE", _gbpusd,
                                         new List <LimitOrder>(), // bids
                                         new List <LimitOrder>    // asks
            {
                new LimitOrder(1.28167m, 2909.98m),               // 0.78023, 3729.63406 (reciprocal)
                new LimitOrder(1.29906m, 50000m)                  // 0.76978, 64953.0 (reciprocal)
            },
                                         DateTime.Now);

            var eurgbpSynth = SynthOrderBook.FromOrderBooks(eurusdOB, gbpusdOB, _eurgbp);

            var volumePnL = Arbitrage.GetArbitrageVolumeAndPnL(eurgbpSynth.Bids, eurgbpOB.Asks);

            Assert.NotNull(volumePnL?.Volume);
            Assert.NotNull(volumePnL?.PnL);
        }
示例#8
0
        private void deactivateArbitrage(Arbitrage arbitrage)
        {
            arbitrage.IsActive   = false;
            arbitrage.ExpireTime = DateTime.Now;

            arbitrageDBManager.Update(arbitrage);
        }
        public void ShouldIterateArbitrageCase1()
        {
            MockSistem mockSistem = new MockSistem();

            Arbitrage arbitrage = new Arbitrage(mockSistem);

            arbitrage.IterateSymbols();
        }
示例#10
0
 public void Add(Arbitrage arbitrage)
 {
     _lastArbitrageDict[arbitrage.ObservationId] = arbitrage; //Get a null excption? 2018-2-13
     using (var context = _coinContextService.GetContext())
     {
         context.Add(arbitrage);
         context.SaveChanges();
     }
 }
示例#11
0
        internal void CheckDoubleArbitrage(int ArbBidTag, int ArbAskTag)
        {
            int       counter = 0;
            Arbitrage a1 = null, a2 = null;

            foreach (var item in dictSPairs)
            {
                if (item.Value.m_firstBidSecondAskArbitrage != null && item.Value.m_firstBidSecondAskArbitrage.BankBidGAsk == ArbBidTag)
                {
                    //continue if itself
                    if (ArbAskTag == item.Value.m_firstBidSecondAskArbitrage.BankAskLBid)
                    {
                        a1 = item.Value.m_firstBidSecondAskArbitrage;
                        continue;
                    }
                    counter++;
                    a2 = item.Value.m_firstBidSecondAskArbitrage;
                }
            }
            if (counter == 1 && a1 != null && a2 != null)
            {
                //run trade for
                DoubleArbitrage1B2A da = new DoubleArbitrage1B2A();
                da.Symbol          = m_symbol;
                da.FirstArbitrage  = a1;
                da.SecondArbitrage = a2;
                TradeDoubleArbitrage.Instance.TradeBegin(da);
            }

            counter = 0;
            a1      = null;
            a2      = null;

            foreach (var item in dictSPairs)
            {
                if (item.Value.m_firstBidSecondAskArbitrage != null && item.Value.m_firstBidSecondAskArbitrage.BankAskLBid == ArbAskTag)
                {
                    //continue if itself
                    if (ArbBidTag == item.Value.m_firstBidSecondAskArbitrage.BankBidGAsk)
                    {
                        a1 = item.Value.m_firstBidSecondAskArbitrage;
                        continue;
                    }
                    counter++;
                    a2 = item.Value.m_firstBidSecondAskArbitrage;
                }
            }
            if (counter == 1 && a1 != null && a2 != null)
            {
                //run trade for
                DoubleArbitrage2B1A da = new DoubleArbitrage2B1A();
                da.Symbol          = m_symbol;
                da.FirstArbitrage  = a1;
                da.SecondArbitrage = a2;
                TradeDoubleArbitrage.Instance.TradeBegin(da);
            }
        }
        public void ShouldIterateArbitrageCase2()
        {
            Parameters.IsVadeSpot = true;
            Parameters.IsVade0819 = true;

            MockSistem mockSistem = new MockSistem();

            Arbitrage arbitrage = new Arbitrage(mockSistem);

            arbitrage.IterateSymbols();
        }
示例#13
0
        public async Task <IHttpActionResult> GetArbitrage(int id)
        {
            Arbitrage arbitrage = await db.Arbitrages.FindAsync(id);

            if (arbitrage == null)
            {
                return(NotFound());
            }

            return(Ok(arbitrage));
        }
示例#14
0
        public void Buy(BuyOptions options)
        {
            lock (syncRoot)
            {
                PauseTasks();
                try
                {
                    IRule       rule       = signalsService.Rules.Entries.FirstOrDefault(r => r.Name == options.Metadata.SignalRule);
                    RuleAction  ruleAction = rule?.Action ?? RuleAction.Default;
                    IPairConfig pairConfig = GetPairConfig(options.Pair);

                    bool arbitragePair = pairConfig.ArbitrageEnabled && pairConfig.ArbitrageSignalRules.Contains(options.Metadata.SignalRule);
                    if (arbitragePair)
                    {
                        Arbitrage arbitrage = Exchange.GetArbitrage(options.Pair, Config.Market, pairConfig.ArbitrageMarkets, pairConfig.ArbitrageType);
                        if (arbitrage.IsAssigned)
                        {
                            Arbitrage(new ArbitrageOptions(options.Pair, arbitrage, options.Metadata));
                        }
                    }
                    else
                    {
                        ITradingPair swappedPair = Account.GetTradingPairs().OrderBy(p => p.CurrentMargin).FirstOrDefault(tradingPair =>
                        {
                            IPairConfig tradingPairConfig = GetPairConfig(tradingPair.Pair);
                            return(tradingPairConfig.SellEnabled && tradingPairConfig.SwapEnabled && tradingPairConfig.SwapSignalRules != null &&
                                   tradingPairConfig.SwapSignalRules.Contains(options.Metadata.SignalRule) &&
                                   tradingPairConfig.SwapTimeout < (DateTimeOffset.Now - tradingPair.OrderDates.DefaultIfEmpty().Max()).TotalSeconds);
                        });

                        if (swappedPair != null)
                        {
                            Swap(new SwapOptions(swappedPair.Pair, options.Pair, options.Metadata));
                        }
                        else if (ruleAction == RuleAction.Default)
                        {
                            if (CanBuy(options, out string message))
                            {
                                tradingTimedTask.InitiateBuy(options);
                            }
                            else
                            {
                                loggingService.Debug(message);
                            }
                        }
                    }
                }
                finally
                {
                    ContinueTasks();
                }
            }
        }
        public void ArbitrageVolume_NoArbitrage_EmptyOrderBooks_Test()
        {
            const string source    = "FE";
            var          timestamp = DateTime.UtcNow;

            var orderBook1 = new OrderBook(source, _btcusd, new List <LimitOrder>(), new List <LimitOrder>(), timestamp);
            var orderBook2 = new OrderBook(source, _btcusd, new List <LimitOrder>(), new List <LimitOrder>(), timestamp);

            var volume = Arbitrage.GetArbitrageVolumeAndPnL(orderBook1.Bids, orderBook2.Asks);

            Assert.Null(volume);
        }
示例#16
0
        public async Task <IHttpActionResult> PostArbitrage(Arbitrage arbitrage)
        {
            if (!ModelState.IsValid)
            {
                return(BadRequest(ModelState));
            }

            db.Arbitrages.Add(arbitrage);
            await db.SaveChangesAsync();

            return(CreatedAtRoute("DefaultApi", new { id = arbitrage.Id }, arbitrage));
        }
        public void ArbitrageVolume_NoArbitrage_EmptyOrderBooks_Test()
        {
            const string exchangeName = "FE";
            var          assetPair    = new AssetPair("BTC", "USD", 8, 8);
            var          timestamp    = DateTime.UtcNow;

            var orderBook1 = new OrderBook(exchangeName, assetPair, new List <VolumePrice>(), new List <VolumePrice>(), timestamp);
            var orderBook2 = new OrderBook(exchangeName, assetPair, new List <VolumePrice>(), new List <VolumePrice>(), timestamp);

            var volume = Arbitrage.GetArbitrageVolumePnL(orderBook1.Bids, orderBook2.Asks);

            Assert.Null(volume);
        }
        public void ShouldIterateArbitrageCase5()
        {
            Parameters.IsVade0919 = true;
            Parameters.IsVade1019 = true;
            Parameters.IsVade1219 = true;
            Parameters.IsSending  = true;
            Parameters.Delay      = 12;

            MockSistem mockSistem = new MockSistem();

            Arbitrage arbitrage = new Arbitrage(mockSistem);

            arbitrage.IterateSymbols();
        }
示例#19
0
        public async Task <IHttpActionResult> DeleteArbitrage(int id)
        {
            Arbitrage arbitrage = await db.Arbitrages.FindAsync(id);

            if (arbitrage == null)
            {
                return(NotFound());
            }

            db.Arbitrages.Remove(arbitrage);
            await db.SaveChangesAsync();

            return(Ok(arbitrage));
        }
 public void AddAndGet()
 {
     using (var context = GetContext())
     {
         var arbitrage = new Arbitrage();
         arbitrage.Id            = Guid.NewGuid();
         arbitrage.ObservationId = Guid.NewGuid();
         var coinContextService = new CoinContextService();
         var service            = new ArbitrageService(coinContextService, context);
         service.Add(arbitrage);
         var lastOne = service.GetLastOne(arbitrage.ObservationId);
         Assert.Equal(arbitrage, lastOne);
         Assert.Equal(arbitrage.Id, lastOne.Id);
     }
 }
        public void ShouldIterateArbitrageCase3()
        {
            Parameters.IsVade0819         = true;
            Parameters.IsVade0919         = true;
            Parameters.IsVade1019         = true;
            Parameters.IsArbitrageForward = true;
            Parameters.ForwardThreshold   = -50;
            Parameters.IsSending          = true;

            MockSistem mockSistem = new MockSistem();

            Arbitrage arbitrage = new Arbitrage(mockSistem);

            arbitrage.IterateSymbols();
        }
        public void ShouldIterateArbitrageCase4()
        {
            Parameters.IsVade0919          = true;
            Parameters.IsVade1019          = true;
            Parameters.IsVade1219          = true;
            Parameters.IsSending           = true;
            Parameters.IsArbitrageBackward = true;
            Parameters.BackwardThreshold   = -50;
            Parameters.TrackThreshold      = 10000;
            Parameters.Delay = 15;

            MockSistem mockSistem = new MockSistem();

            Arbitrage arbitrage = new Arbitrage(mockSistem);

            arbitrage.IterateSymbols();
        }
        public void ArbitrageVolumePnL_Complex2_Test()
        {
            // https://docs.google.com/spreadsheets/d/1plnbQSS-WP6ykTv8wIi_hbAhk_aSz_tllXFIE3jhFpU/edit#gid=2011486790
            const string exchangeName = "FE";
            var          assetPair    = new AssetPair("BTC", "USD", 8, 8);
            var          timestamp    = DateTime.UtcNow;

            var asks = new List <VolumePrice>
            {
                new VolumePrice(2.9m, 10),
                new VolumePrice(2.8m, 10),
                new VolumePrice(2.7m, 10),
                new VolumePrice(2.6m, 10),
                new VolumePrice(2.4m, 10),
                new VolumePrice(2.3m, 10),
                new VolumePrice(2.2m, 10),
                new VolumePrice(2.0m, 10),
                new VolumePrice(1.9m, 10),
                new VolumePrice(1.8m, 10),
                new VolumePrice(1.7m, 10),
                new VolumePrice(1.3m, 10),
                new VolumePrice(1.2m, 10),
                new VolumePrice(1.1m, 10),
            };

            var bids = new List <VolumePrice>
            {
                new VolumePrice(3.2m, 1),
                new VolumePrice(3.1m, 1),
                new VolumePrice(3m, 1),
                new VolumePrice(2.5m, 1),
                new VolumePrice(2.1m, 100),
                new VolumePrice(1.6m, 5),
                new VolumePrice(1.5m, 5),
                new VolumePrice(1.4m, 5)
            };

            var bidsOrderBook = new OrderBook(exchangeName, assetPair, bids, new List <VolumePrice>(), timestamp);
            var asksOrderBook = new OrderBook(exchangeName, assetPair, new List <VolumePrice>(), asks, timestamp);

            var volumePnL = Arbitrage.GetArbitrageVolumePnL(bidsOrderBook.Bids, asksOrderBook.Asks);

            Assert.Equal(70, volumePnL?.Volume);
            Assert.Equal(40.4m, volumePnL?.PnL);
        }
示例#24
0
文件: Program.cs 项目: hombrevrc/FDK
        static void Main(string[] args)
        {
            Arbitrage        coldArb     = null;
            List <Arbitrage> warmArbList = new List <Arbitrage>();

            for (int i = 0; i < 10000; i++)
            {
                Arbitrage newArb = new Arbitrage(DateTime.Now, 1, 2, "dfas");
                for (int j = 0; j < 10; j++)
                {
                    newArb.ArbitrageDetails.Add(new ArbitrageDetail(DateTime.Now));
                }
                warmArbList.Add(newArb);
                coldArb = newArb;
            }

            using (Model.ArbitrageContext arbContext = new Model.ArbitrageContext())
            {
                arbContext.Arbitrages.Add(coldArb);
                arbContext.SaveChanges();
            }

            Stopwatch sw = new Stopwatch();

            using (Model.ArbitrageContext arbContext = new Model.ArbitrageContext())
            {
                arbContext.Configuration.AutoDetectChangesEnabled = false;
                //arbContext.Configuration.ValidateOnSaveEnabled = false;

                sw.Start();

                foreach (var item in warmArbList)
                {
                    arbContext.Arbitrages.Add(item);
                }
                sw.Stop();
                Console.WriteLine("Time of adding 10000 elements : " + sw.ElapsedMilliseconds + " ms");

                sw.Reset();
                sw.Start();
                arbContext.SaveChanges();
                sw.Stop();
                Console.WriteLine("Time of saving 10000 elements : " + sw.ElapsedMilliseconds + " ms");
            }
        }
        public void ArbitrageVolumePnL_Complex2_Test()
        {
            // https://docs.google.com/spreadsheets/d/1plnbQSS-WP6ykTv8wIi_hbAhk_aSz_tllXFIE3jhFpU/edit#gid=2011486790
            const string source    = "FE";
            var          timestamp = DateTime.UtcNow;

            var bids = new List <LimitOrder>
            {
                new LimitOrder("", "", 3.2m, 1),
                new LimitOrder("", "", 3.1m, 1),
                new LimitOrder("", "", 3m, 1),
                new LimitOrder("", "", 2.5m, 1),
                new LimitOrder("", "", 2.1m, 100),
                new LimitOrder("", "", 1.6m, 5),
                new LimitOrder("", "", 1.5m, 5),
                new LimitOrder("", "", 1.4m, 5)
            };
            var asks = new List <LimitOrder>
            {
                new LimitOrder("", "", 2.9m, 10),
                new LimitOrder("", "", 2.8m, 10),
                new LimitOrder("", "", 2.7m, 10),
                new LimitOrder("", "", 2.6m, 10),
                new LimitOrder("", "", 2.4m, 10),
                new LimitOrder("", "", 2.3m, 10),
                new LimitOrder("", "", 2.2m, 10),
                new LimitOrder("", "", 2.0m, 10),
                new LimitOrder("", "", 1.9m, 10),
                new LimitOrder("", "", 1.8m, 10),
                new LimitOrder("", "", 1.7m, 10),
                new LimitOrder("", "", 1.3m, 10),
                new LimitOrder("", "", 1.2m, 10),
                new LimitOrder("", "", 1.1m, 10),
            };

            var bidsOrderBook = new OrderBook(source, _btcusd, bids, new List <LimitOrder>(), timestamp);
            var asksOrderBook = new OrderBook(source, _btcusd, new List <LimitOrder>(), asks, timestamp);

            var volumePnL = Arbitrage.GetArbitrageVolumeAndPnL(bidsOrderBook.Bids, asksOrderBook.Asks);

            Assert.Equal(70, volumePnL?.Volume);
            Assert.Equal(40.4m, volumePnL?.PnL);
        }
示例#26
0
        private void MoveFromActualToHistory(Arbitrage arbitrage)
        {
            var key = arbitrage.ToString();

            // Remove from actual arbitrages
            arbitrage.EndedAt = DateTime.UtcNow;
            _arbitrages.Remove(key);

            // If found in history and old PnL is better then don't replace it
            var found = _arbitrageHistory.TryGetValue(key, out var oldArbitrage);

            if (found && arbitrage.PnL < oldArbitrage.PnL)
            {
                return;
            }

            // Otherwise add or update
            _arbitrageHistory[key] = arbitrage;
        }
        public void ArbitrageVolumePnL_Complex1_Test()
        {
            // https://docs.google.com/spreadsheets/d/1plnbQSS-WP6ykTv8wIi_hbAhk_aSz_tllXFIE3jhFpU/edit#gid=0

            const string exchangeName = "FE";
            var          assetPair    = new AssetPair("BTC", "USD", 8, 8);
            var          timestamp    = DateTime.UtcNow;

            var asks = new List <VolumePrice>
            {
                new VolumePrice(1000, 10),
                new VolumePrice(950, 10),
                new VolumePrice(850, 10), // <-
                new VolumePrice(800, 10), // <-
                new VolumePrice(700, 10), // <-
                new VolumePrice(650, 10), // <-
                new VolumePrice(600, 10), // <-
                new VolumePrice(550, 1),  // <-
                new VolumePrice(500, 10)  // <-
            };

            var bids = new List <VolumePrice>
            {
                new VolumePrice(900, 5),   // <-
                new VolumePrice(750, 100), // <-
                new VolumePrice(550, 1)    // <-
            };

            var bidsOrderBook = new OrderBook(exchangeName, assetPair, bids, new List <VolumePrice>(), timestamp);
            var asksOrderBook = new OrderBook(exchangeName, assetPair, new List <VolumePrice>(), asks, timestamp);

            var volumePnL = Arbitrage.GetArbitrageVolumePnL(bidsOrderBook.Bids, asksOrderBook.Asks);

            Assert.Equal(41, volumePnL?.Volume);
            Assert.Equal(6450, volumePnL?.PnL);
        }
        public void ArbitrageVolume_NoArbitrage_TheSameOrderBook_Test()
        {
            const string source    = "FE";
            var          timestamp = DateTime.UtcNow;

            var bids = new List <LimitOrder>
            {
                new LimitOrder("", "", 8825, 9),
                new LimitOrder("", "", 8823, 5)
            };
            var asks = new List <LimitOrder>
            {
                new LimitOrder("", "", 9000, 10),
                new LimitOrder("", "", 8999.95m, 7),
                new LimitOrder("", "", 8900.12345677m, 3)
            };

            var orderBook1 = new OrderBook(source, _btcusd, bids, asks, timestamp);
            var orderBook2 = new OrderBook(source, _btcusd, bids, asks, timestamp);

            var volume = Arbitrage.GetArbitrageVolumeAndPnL(orderBook1.Bids, orderBook2.Asks);

            Assert.Null(volume);
        }
示例#29
0
        private IEnumerable <Arbitrage> GetArbitrages(IReadOnlyCollection <OrderBook> orderBooks)
        {
            orderBooks = orderBooks.Where(x => x.BestBid != null || x.BestAsk != null)
                         .OrderBy(x => x.AssetPair.Name).ToList();

            var result = new List <Arbitrage>();

            var watch = Stopwatch.StartNew();

            var synthsCount = 0;

            // O( (n^2)/2 )
            // TODO: cache should be implemented to avoid iterating over all asset pairs every time
            for (var i = 0; i < orderBooks.Count; i++)
            {
                if (i == orderBooks.Count - 1)
                {
                    break;
                }

                var target = orderBooks.ElementAt(i);

                for (var j = i + 1; j < orderBooks.Count; j++)
                {
                    var source = orderBooks.ElementAt(j);

                    if (target.ToString() == source.ToString())
                    {
                        continue;
                    }

                    // Calculate all synthetic order books between source order book and target order book
                    var synthOrderBooks = SynthOrderBook.GetSynthsFromAll(target.AssetPair, source, orderBooks);
                    synthsCount += synthOrderBooks.Count;

                    // Compare each synthetic with target
                    foreach (var synthOrderBook in synthOrderBooks)
                    {
                        decimal spread     = 0;
                        decimal volume     = 0;
                        decimal pnL        = 0;
                        string  targetSide = null;
                        IReadOnlyList <string> marketMakers = new List <string>();

                        if (target.BestBid?.Price > synthOrderBook.BestAsk?.Price)
                        {
                            spread = Arbitrage.GetSpread(target.BestBid.Price, synthOrderBook.BestAsk.Price);
                            var volumePnL = Arbitrage.GetArbitrageVolumeAndPnL(target.Bids, synthOrderBook.Asks);
                            Debug.Assert(volumePnL?.Volume != null);
                            Debug.Assert(volumePnL?.PnL != null);
                            targetSide   = Bid;
                            marketMakers = GetMarketMakers(target.BestBid, synthOrderBook.GetLimitOrdersOfBestAsk());
                            volume       = volumePnL.Value.Volume;
                            pnL          = volumePnL.Value.PnL;
                        }

                        if (synthOrderBook.BestBid?.Price > target.BestAsk?.Price)
                        {
                            spread = Arbitrage.GetSpread(synthOrderBook.BestBid.Price, target.BestAsk.Price);
                            var volumePnL = Arbitrage.GetArbitrageVolumeAndPnL(synthOrderBook.Bids, target.Asks);
                            Debug.Assert(volumePnL?.Volume != null);
                            Debug.Assert(volumePnL?.PnL != null);
                            targetSide   = Ask;
                            marketMakers = GetMarketMakers(target.BestAsk, synthOrderBook.GetLimitOrdersOfBestBid());
                            volume       = volumePnL.Value.Volume;
                            pnL          = volumePnL.Value.PnL;
                        }

                        if (targetSide == null) // no arbitrages
                        {
                            continue;
                        }

                        var volumeInUsd = _orderBooksService.ConvertToUsd(target.AssetPair.Base.Id, volume);
                        var pnLInUsd    = _orderBooksService.ConvertToUsd(target.AssetPair.Quote.Id, pnL);

                        var lykkeArbitrage = new Arbitrage(
                            target.AssetPair,
                            source.AssetPair,
                            spread,
                            targetSide,
                            synthOrderBook.ConversionPath,
                            volume,
                            volumeInUsd,
                            pnL,
                            pnLInUsd,
                            target.BestBid?.Price,
                            target.BestAsk?.Price,
                            synthOrderBook.BestBid?.Price,
                            synthOrderBook.BestAsk?.Price,
                            marketMakers,
                            DateTime.UtcNow
                            );
                        result.Add(lykkeArbitrage);
                    }
                }
            }

            watch.Stop();
            if (watch.ElapsedMilliseconds > 1000)
            {
                _log.Info($"Performance issue - {watch.ElapsedMilliseconds} ms, {result.Count} arbitrages, {orderBooks.Count} order books," +
                          $"{synthsCount} synthetic order books created.");
            }

            return(result.ToList());
        }
        private Task <IReadOnlyList <LykkeArbitrageRow> > GetArbitragesAsync(IReadOnlyList <OrderBook> orderBooks)
        {
            orderBooks = orderBooks.Where(x => x.BestBid.HasValue || x.BestAsk.HasValue).OrderBy(x => x.AssetPair.Name).ToList();

            var result = new List <LykkeArbitrageRow>();

            var watch = Stopwatch.StartNew();

            var synthsCount = 0;

            // O( (n^2)/2 )
            for (var i = 0; i < orderBooks.Count; i++)
            {
                if (i == orderBooks.Count - 1)
                {
                    break;
                }

                var target = orderBooks.ElementAt(i);

                for (var j = i + 1; j < orderBooks.Count; j++)
                {
                    var source = orderBooks.ElementAt(j);

                    if (target.ToString() == source.ToString())
                    {
                        continue;
                    }

                    // Calculate all synthetic order books between a source order book and a target order book
                    var synthOrderBooks = SynthOrderBook.GetSynthsFromAll(target.AssetPair, source, orderBooks);
                    synthsCount += synthOrderBooks.Count;

                    // Compare each synthetic with current target asset pair
                    foreach (var synthOrderBook in synthOrderBooks)
                    {
                        decimal spread     = 0;
                        decimal volume     = 0;
                        decimal pnL        = 0;
                        string  targetSide = null;

                        // Bid side
                        if (target.BestBid?.Price > synthOrderBook.BestAsk?.Price)
                        {
                            spread = Arbitrage.GetSpread(target.BestBid.Value.Price, synthOrderBook.BestAsk.Value.Price);
                            var volumePnL = Arbitrage.GetArbitrageVolumePnL(target.Bids, synthOrderBook.Asks);
                            Debug.Assert(volumePnL?.Volume != null);
                            Debug.Assert(volumePnL?.PnL != null);
                            targetSide = "Bid";
                            volume     = volumePnL.Value.Volume;
                            pnL        = volumePnL.Value.PnL;
                        }

                        // Ask side
                        if (synthOrderBook.BestBid?.Price > target.BestAsk?.Price)
                        {
                            spread = Arbitrage.GetSpread(synthOrderBook.BestBid.Value.Price, target.BestAsk.Value.Price);
                            var volumePnL = Arbitrage.GetArbitrageVolumePnL(synthOrderBook.Bids, target.Asks);
                            Debug.Assert(volumePnL?.Volume != null);
                            Debug.Assert(volumePnL?.PnL != null);
                            targetSide = "Ask";
                            volume     = volumePnL.Value.Volume;
                            pnL        = volumePnL.Value.PnL;
                        }

                        if (string.IsNullOrWhiteSpace(targetSide)) // no arbitrage
                        {
                            continue;
                        }

                        var baseToUsdRate  = Convert(target.AssetPair.Base, Usd, orderBooks);
                        var quoteToUsdRate = Convert(target.AssetPair.Quote, Usd, orderBooks);
                        var volumeInUsd    = volume * baseToUsdRate;
                        volumeInUsd = volumeInUsd.HasValue ? Math.Round(volumeInUsd.Value) : (decimal?)null;
                        var pnLInUsd = pnL * quoteToUsdRate;
                        pnLInUsd = pnLInUsd.HasValue ? Math.Round(pnLInUsd.Value) : (decimal?)null;

                        var lykkeArbitrage = new LykkeArbitrageRow(target.AssetPair, source.AssetPair, spread, targetSide, synthOrderBook.ConversionPath,
                                                                   volume, target.BestBid?.Price, target.BestAsk?.Price, synthOrderBook.BestBid?.Price, synthOrderBook.BestAsk?.Price, volumeInUsd,
                                                                   pnL, pnLInUsd);
                        result.Add(lykkeArbitrage);
                    }
                }
            }

            watch.Stop();
            if (watch.ElapsedMilliseconds > 1000)
            {
                _log.Info($"{watch.ElapsedMilliseconds} ms, {result.Count} arbitrages, {orderBooks.Count} order books, {synthsCount} synthetic order books.");
            }

            return(Task.FromResult(result.OrderBy(x => x.Target).ThenBy(x => x.Source).ToList() as IReadOnlyList <LykkeArbitrageRow>));
        }