コード例 #1
0
ファイル: ArbitrageService.cs プロジェクト: w1r2p1/QuantBox
        public void StoreNormalResults(ArbitrageResult result)
        {
            //Generate a result key so we can match the same results later with an O(1) lookup
            string resultKey = string.Join(',', result.Exchanges) + '-' + string.Join(',', result.Pairs.Select(x => x.AltCurrency + "/" + x.BaseCurrency));

            if (bestNormalProfit.Profit < result.Profit)
            {
                bestNormalProfit = result;
            }
            if (worstNormalProfit.Profit > result.Profit)
            {
                worstNormalProfit = result;
            }

            if (!normalResults.TryGetValue(resultKey, out ArbitrageResult currentResult))
            {
                normalResults.Add(resultKey, result);
            }
            else
            {
                currentResult = result;
            }

            if (result.Profit > result.TransactionFee)
            {
                var @newTradeEvent = new ArbitrageFoundIntegrationEvent(result);
                _eventBus.Publish(@newTradeEvent);
            }
        }
コード例 #2
0
        private ArbitrageResult ComparePrices(ICurrencyCoin value1, ICurrencyCoin value2)
        {
            ArbitrageResult result = null;

            if (value1.Price > value2.Price && ((1 - (value2.Price / value1.Price)) * 100) > 5)
            {
                result = new ArbitrageResult
                {
                    Market         = value1.Market,
                    Symbol         = value1.TickerSymbol,
                    Exchange1      = value1.Exchange,
                    Exchange1Logo  = value1.Logo,
                    Exchange1Price = value1.Price,
                    Exchange2      = value2.Exchange,
                    Exchange2Logo  = value2.Logo,
                    Exchange2Price = value2.Price,
                };
            }
            else if (((1 - (value1.Price / value2.Price)) * 100) > 5)
            {
                result = new ArbitrageResult
                {
                    Market         = value1.Market,
                    Symbol         = value1.TickerSymbol,
                    Exchange1      = value2.Exchange,
                    Exchange1Logo  = value2.Logo,
                    Exchange1Price = value2.Price,
                    Exchange2      = value1.Exchange,
                    Exchange2Logo  = value1.Logo,
                    Exchange2Price = value1.Price,
                };
            }
            return(result);
        }
コード例 #3
0
 public ArbitrageFoundIntegrationEvent(ArbitrageResult result)
 {
     Result = result;
 }
コード例 #4
0
ファイル: TradingService.cs プロジェクト: w1r2p1/QuantBox
        public async Task ExecuteArbitrage(ArbitrageResult result)
        {
            try
            {
                //Temp bot grabbing so we can check settings (to be called from bot later?)
                Bot            bot;
                ExchangeConfig account;

                if (result.Type == ArbitrageType.Triangle)
                {
                    bot = _context.Bots
                          .Include(x => x.TradeSettings)
                          .Include(x => x.Exchanges)
                          .First(x => x.Name == "Triangle Arbitrage");
                }
                else
                {
                    bot = _context.Bots
                          .Include(x => x.TradeSettings)
                          .Include(x => x.Exchanges)
                          .First(x => x.Name == "Normal Arbitrage");
                }

                if (bot.TradeSettings.TradingEnabled)
                {
                    //Grab bot accounts for this trade
                    var exchange = bot.Exchanges.FirstOrDefault(x => x.Name == result.Exchanges.First());
                    if (exchange == null || exchange.SelectedConfig == null)
                    {
                        //_logger.LogWarning("No account chosen for " + result.Exchanges.First());
                        return;
                    }
                    else
                    {
                        account = exchange.SelectedConfig;
                    }

                    var arbitrageTradeResults = new TradeResults();

                    if (result.Type == ArbitrageType.Triangle)
                    {
                        var ex = _exchanges.First(x => x.Name == result.Exchanges.First()); //Triangle arb only has one exchange
                        if (!account.Simulated && !ex.IsAuthenticated)
                        {
                            throw new Exception("Can't create a trade, user is not authenticated.");
                        }

                        //TODO: Check that we have enough liquidity for trades (and potentially swap from available liquidity to fill them)

                        //Step 1: Buy/Sell initial coins
                        //Step 2: Swap coin into misc coin
                        //Step 3: Swap misc coin back to original
                        var previousCurrency = result.InitialCurrency;  //Set start currency for choosing buy/sell
                        var currentLiquidity = result.InitialLiquidity; //The amount of the current asset we have
                        var simDelay         = new Random().NextDouble() + 0.1;
                        foreach (var pair in result.Pairs)
                        {
                            //If we start on the base, we want to buy the alt
                            var side = pair.BaseCurrency == previousCurrency ? OrderSide.Buy : OrderSide.Sell;

                            ExchangeOrderResult orderResult;
                            if (account.Simulated)
                            {
                                orderResult = await ex.SimulateOrder(pair.MarketSymbol, side, OrderType.Market, 0, currentLiquidity, simDelay); //Use delay to simulate lag between placing and filling the order
                            }
                            else
                            {
                                orderResult = await ex.CreateOrder(pair.MarketSymbol, side, OrderType.Market, 0, currentLiquidity);
                            }

                            arbitrageTradeResults.BotId = bot.Name;
                            arbitrageTradeResults.Trades.Add(new TradeResult()
                            {
                                Amount       = orderResult.Amount,
                                AmountFilled = orderResult.AmountFilled,
                                AveragePrice = orderResult.AveragePrice,
                                Fees         = orderResult.Fees,
                                FeesCurrency = orderResult.FeesCurrency,
                                FillDate     = orderResult.FillDate,
                                OrderSide    = side,
                                MarketSymbol = pair.MarketSymbol,
                                Message      = orderResult.Message,
                                OrderDate    = orderResult.OrderDate,
                                OrderId      = orderResult.OrderId,
                                Price        = orderResult.Price,
                                Result       = orderResult.Result.ToOrderResult(),
                                TradeId      = orderResult.TradeId,
                            });

                            if (orderResult.Result == ExchangeAPIOrderResult.Canceled || orderResult.Result == ExchangeAPIOrderResult.Error || orderResult.Result == ExchangeAPIOrderResult.Unknown)
                            {
                                throw new Exception("Something went wrong with order " + orderResult.OrderId + ",\r\nResult:" + orderResult.Result + "\r\n" + orderResult.Message);
                            }

                            if (side == OrderSide.Buy)
                            {
                                previousCurrency = pair.AltCurrency;
                            }
                            else
                            {
                                previousCurrency = pair.BaseCurrency;
                            }
                            currentLiquidity = orderResult.AmountFilled;
                        }

                        arbitrageTradeResults.InitialCurrency = result.InitialCurrency;
                        arbitrageTradeResults.EstimatedProfit = result.Profit;
                        arbitrageTradeResults.ActualProfit    = (arbitrageTradeResults.Trades.Last().AmountFilled - result.InitialLiquidity) / result.InitialLiquidity * 100;

                        //Trade 1 gets converted back to the initial currency and added to the dust collected
                        var trade1 = arbitrageTradeResults.Trades.First();
                        if (trade1.OrderSide == OrderSide.Buy)
                        {
                            arbitrageTradeResults.Dust += trade1.AveragePrice * (trade1.Amount - trade1.AmountFilled);
                        }
                        else
                        {
                            arbitrageTradeResults.Dust += (trade1.Amount - trade1.AmountFilled) / trade1.AveragePrice;
                        }

                        //Trade 2 gets converted back to the second currency from the first trade and then to the initial currency
                        var trade2 = arbitrageTradeResults.Trades[1];
                        if (trade2.OrderSide == OrderSide.Buy)
                        {
                            var baseAmount = trade2.AveragePrice * (trade2.Amount - trade2.AmountFilled);
                            if (trade1.OrderSide == OrderSide.Buy)
                            {
                                arbitrageTradeResults.Dust += trade1.AveragePrice * baseAmount;
                            }
                            else
                            {
                                arbitrageTradeResults.Dust += baseAmount / trade1.AveragePrice;
                            }
                        }
                        else
                        {
                            var altAmount = (trade2.Amount - trade2.AmountFilled) / trade2.AveragePrice;
                            if (trade1.OrderSide == OrderSide.Buy)
                            {
                                arbitrageTradeResults.Dust += trade1.AveragePrice * altAmount;
                            }
                            else
                            {
                                arbitrageTradeResults.Dust += altAmount / trade1.AveragePrice;
                            }
                        }

                        //Dust for the final trade is already in the right currency
                        var trade3 = arbitrageTradeResults.Trades.Last();
                        arbitrageTradeResults.Dust += trade3.Amount - trade3.AmountFilled;

                        arbitrageTradeResults.TimeFinished = DateTime.Now;

                        _context.ArbitrageResults.Add(arbitrageTradeResults);
                        _context.SaveChanges();
                    }
                    else
                    {
                        //TODO: Implemented normal arb
                    }
                }
            }
            catch (Exception e)
            {
                _logger.LogCritical("Something went wrong executing arbitrage", e);
            }
        }
コード例 #5
0
ファイル: ArbitrageService.cs プロジェクト: w1r2p1/QuantBox
        public void CheckExchangeForNormalArbitrage(IExchange startExchange)
        {
            var     orderbooks = startExchange.Orderbooks;
            decimal endAmountBought;
            decimal audInvested = 100;

            try
            {
                foreach (var startOrderbook in orderbooks.Values)
                {
                    foreach (var exchange in _exchanges.Where(x => x.Name != startExchange.Name))
                    {
                        //Base->Alt->Base
                        var baseAmount = ConvertAudToCrypto(orderbooks, startOrderbook.BaseCurrency, audInvested);
                        if (baseAmount == 0)
                        {
                            continue; //Asset prices not loaded yet
                        }

                        if (!exchange.Orderbooks.TryGetValue(startOrderbook.AltCurrency + "/" + startOrderbook.BaseCurrency, out Orderbook endOrderbook))
                        {
                            exchange.Orderbooks.TryGetValue(startOrderbook.BaseCurrency + "/" + startOrderbook.AltCurrency, out endOrderbook);
                        }
                        if (endOrderbook == null)
                        {
                            continue; //Other exchange doesn't have the pair
                        }

                        var asks = startOrderbook.Asks;
                        if (asks.Count() == 0)
                        {
                            continue;
                        }
                        var startAmountBought = baseAmount / PriceCalculator.GetPriceQuote(asks, PriceCalculator.ConvertBaseToAlt(asks.First().Price, baseAmount));

                        if (endOrderbook.BaseCurrency == startOrderbook.BaseCurrency)
                        {
                            var endBids = endOrderbook.Bids;
                            if (endBids.Count() == 0)
                            {
                                continue;
                            }
                            endAmountBought = startAmountBought * PriceCalculator.GetPriceQuote(endBids, startAmountBought);
                        }
                        else
                        {
                            var endAsks = endOrderbook.Asks;
                            if (endAsks.Count() == 0)
                            {
                                continue;
                            }
                            endAmountBought = startAmountBought / PriceCalculator.GetPriceQuote(endAsks, PriceCalculator.ConvertBaseToAlt(endAsks.First().Price, startAmountBought));
                        }

                        decimal percentProfit = (endAmountBought - baseAmount) / baseAmount * 100;

                        var result = new ArbitrageResult()
                        {
                            Exchanges = new List <string>()
                            {
                                startExchange.Name, exchange.Name
                            },
                            Pairs = new List <Pair>()
                            {
                                new Pair(startOrderbook.Pair, startOrderbook.BaseCurrency, startOrderbook.AltCurrency)
                            },
                            Profit           = percentProfit,
                            TransactionFee   = startExchange.Fee + exchange.Fee,
                            InitialCurrency  = startOrderbook.BaseCurrency,
                            InitialLiquidity = baseAmount,
                            Type             = ArbitrageType.Normal
                        };
                        StoreNormalResults(result);

                        //Alt->Base->Alt
                        baseAmount = ConvertAudToCrypto(orderbooks, startOrderbook.AltCurrency, audInvested);
                        if (baseAmount == 0)
                        {
                            continue; //Asset prices not loaded yet
                        }

                        var bids = startOrderbook.Bids;
                        if (bids.Count() == 0)
                        {
                            continue;
                        }
                        startAmountBought = baseAmount * PriceCalculator.GetPriceQuote(bids, baseAmount);

                        if (endOrderbook.BaseCurrency == startOrderbook.BaseCurrency)
                        {
                            var endAsks = endOrderbook.Asks;
                            if (endAsks.Count() == 0)
                            {
                                continue;
                            }
                            endAmountBought = startAmountBought / PriceCalculator.GetPriceQuote(endAsks, PriceCalculator.ConvertBaseToAlt(endAsks.First().Price, startAmountBought));
                        }
                        else
                        {
                            var endBids = endOrderbook.Bids;
                            if (endBids.Count() == 0)
                            {
                                continue;
                            }
                            endAmountBought = startAmountBought * PriceCalculator.GetPriceQuote(endBids, startAmountBought);
                        }

                        percentProfit = (endAmountBought - baseAmount) / baseAmount * 100;

                        result = new ArbitrageResult()
                        {
                            Exchanges = new List <string>()
                            {
                                startExchange.Name, exchange.Name
                            },
                            Pairs = new List <Pair>()
                            {
                                new Pair(startOrderbook.Pair, startOrderbook.AltCurrency, startOrderbook.BaseCurrency)
                            },
                            Profit           = percentProfit,
                            TransactionFee   = startExchange.Fee + exchange.Fee,
                            InitialCurrency  = startOrderbook.AltCurrency,
                            InitialLiquidity = baseAmount,
                            Type             = ArbitrageType.Normal
                        };
                        StoreNormalResults(result);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error in CheckExchangeForNormalArbitrage (" + e.Message + ")");
            }
        }
コード例 #6
0
ファイル: ArbitrageService.cs プロジェクト: w1r2p1/QuantBox
        public void CheckExchangeForTriangleArbitrage(IExchange exchange)
        {
            try {
                decimal altAmount, alt2Amount, finalAmount, baseAmount;
                //Assuming we are testing BTC/ETH->ETH/XRP->XRP/BTC, startCurrency == BTC, middleCurrency == ETH, endCurrency == XRP
                string startCurrency, middleCurrency, endCurrency; //The currency that's bought/sold from in the first transaction
                var    audInvested = 100;
                var    orderbooks  = exchange.Orderbooks;

                foreach (var market in orderbooks.Values)
                {
                    //Loop every market with a matching currency except itself (this could start on the base or alt currency)
                    foreach (var market2 in orderbooks.Values.Where(x => x.Pair != market.Pair && (x.AltCurrency == market.AltCurrency || x.BaseCurrency == market.AltCurrency || x.AltCurrency == market.BaseCurrency || x.BaseCurrency == market.BaseCurrency)))
                    {
                        //If the base/alt currency for the next market is the base currency, we need to bid (i.e. Buy for first trade)
                        if (market.BaseCurrency == market2.BaseCurrency || market.BaseCurrency == market2.AltCurrency)
                        {
                            baseAmount = ConvertAudToCrypto(orderbooks, market.AltCurrency, audInvested);

                            if (baseAmount == 0)
                            {
                                continue; //Asset prices not loaded yet
                            }

                            try
                            {
                                var bids = orderbooks[market.AltCurrency + "/" + market.BaseCurrency].Bids;
                                if (bids.Count() == 0)
                                {
                                    continue;
                                }
                                altAmount = baseAmount * PriceCalculator.GetPriceQuote(bids, baseAmount);
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e.Message);
                                continue;
                            }
                            startCurrency  = market.AltCurrency;
                            middleCurrency = market.BaseCurrency;
                        }
                        else //Else we need to ask (i.e. Sell for first trade)
                        {
                            baseAmount = ConvertAudToCrypto(orderbooks, market.BaseCurrency, audInvested);
                            if (baseAmount == 0)
                            {
                                continue; //Asset prices not loaded yet
                            }

                            try
                            {
                                var asks = orderbooks[market.AltCurrency + "/" + market.BaseCurrency].Asks;
                                if (asks.Count() == 0)
                                {
                                    continue;                                                                                                                   //Prices not loaded yet
                                }
                                altAmount = baseAmount / PriceCalculator.GetPriceQuote(asks, PriceCalculator.ConvertBaseToAlt(asks.First().Price, baseAmount)); //~3000 ETH from 100 BTC
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e.Message);
                                continue;
                            }
                            startCurrency  = market.BaseCurrency;
                            middleCurrency = market.AltCurrency;
                        }

                        //If the alt bought in step 1 is now a base, use ask price
                        if (market2.BaseCurrency == middleCurrency)
                        {
                            endCurrency = market2.AltCurrency;
                            try
                            {
                                var asks = orderbooks[market2.AltCurrency + "/" + market2.BaseCurrency].Asks;
                                if (asks.Count() == 0)
                                {
                                    continue; //Prices not loaded yet
                                }
                                alt2Amount = altAmount / PriceCalculator.GetPriceQuote(asks, PriceCalculator.ConvertBaseToAlt(asks.First().Price, altAmount));
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e.Message);
                                continue;
                            }
                        }
                        else //Otherwise it's the alt currency (i.e. we're selling to the new coin)
                        {
                            endCurrency = market2.BaseCurrency;
                            try
                            {
                                var bids = orderbooks[market2.AltCurrency + "/" + market2.BaseCurrency].Bids;
                                if (bids.Count() == 0)
                                {
                                    continue; //Not loaded yet
                                }
                                alt2Amount = altAmount * PriceCalculator.GetPriceQuote(bids, altAmount);
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e.Message);
                                continue;
                            }
                        }
                        //Find the final market (i.e. the market that has the middle and end currencies)
                        if (!orderbooks.TryGetValue(startCurrency + "/" + endCurrency, out Orderbook finalMarket))
                        {
                            orderbooks.TryGetValue(endCurrency + "/" + startCurrency, out finalMarket);
                        }

                        //If null, there's no pairs to finish the arb
                        if (finalMarket == null)
                        {
                            continue;
                        }

                        //If the base currency is the first currency, we need to sell (i.e. use bid)
                        if (finalMarket.BaseCurrency == startCurrency)
                        {
                            try
                            {
                                var bids = orderbooks[finalMarket.AltCurrency + "/" + finalMarket.BaseCurrency].Bids;
                                if (bids.Count() == 0)
                                {
                                    continue; //Not loaded yet
                                }
                                finalAmount = alt2Amount * PriceCalculator.GetPriceQuote(bids, alt2Amount);
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e.Message);
                                continue;
                            }
                        }
                        else //Else we buy (i.e. use ask)
                        {
                            try
                            {
                                var asks = orderbooks[finalMarket.AltCurrency + "/" + finalMarket.BaseCurrency].Asks;
                                if (asks.Count() == 0)
                                {
                                    continue; //Prices not loaded yet
                                }
                                finalAmount = alt2Amount / PriceCalculator.GetPriceQuote(asks, PriceCalculator.ConvertBaseToAlt(asks.First().Price, alt2Amount));
                            }
                            catch (Exception e)
                            {
                                Console.WriteLine(e.Message);
                                continue;
                            }
                        }

                        decimal percentProfit = (finalAmount - baseAmount) / baseAmount * 100;
                        var     result        = new ArbitrageResult()
                        {
                            Exchanges = new List <string>()
                            {
                                exchange.Name
                            },
                            Pairs = new List <Pair>()
                            {
                                new Pair(market.Pair, market.BaseCurrency, market.AltCurrency),
                                new Pair(market2.Pair, market2.BaseCurrency, market2.AltCurrency),
                                new Pair(finalMarket.Pair, finalMarket.BaseCurrency, finalMarket.AltCurrency)
                            },
                            Profit           = percentProfit,
                            TransactionFee   = exchange.Fee * 3,
                            InitialCurrency  = startCurrency,
                            InitialLiquidity = baseAmount,
                            Type             = ArbitrageType.Triangle
                        };
                        StoreTriangleResults(result);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }