Ejemplo n.º 1
0
        private async Task PlaceSellIOC(ArbitragePair pair, decimal price)
        {
            decimal sellQuantity = 0;

            try
            {
                decimal raw = pair.AskMultiplier * pair.TradeThreshold / price;
                sellQuantity = Helper.RoundQuantity(pair, pair.AskMultiplier * pair.TradeThreshold / price);

                if (sellQuantity > 0)
                {
                    var result = await baseExchange.ImmediateOrCancel("sell", pair.BaseSymbol, sellQuantity, price);

                    Console.WriteLine(string.Format("LIMIT SELL {0} {1} {2:P2}", pair.Symbol, price, pair.AskSpread));
                }
            }
            catch (ApiException ae)
            {
                EndWorkForPair(pair);

                if (ae.Content.ToLowerInvariant().Contains("insufficient"))
                {
                    pair.Status = "error";
                    dbService.SaveArbitragePair(pair);
                }
                logger.Error(JsonConvert.SerializeObject(JsonConvert.DeserializeObject(ae.Content), Formatting.Indented));
            }
            catch (Exception e)
            {
                logger.Error(e);
            }
        }
Ejemplo n.º 2
0
        private async Task PlaceCounterOrder(ArbitragePair pair, IMatch trade)
        {
            try
            {
                decimal quantity = Helper.RoundQuantity(pair, trade.QuantityFilled);

                if (trade.Side == OrderSide.Sell)
                {
                    var result = await counterExchange.MarketBuy(trade.Symbol, quantity);

                    logger.Trace(string.Format("COUNTER BUY {0} {1} {2} {3}", pair.Symbol, quantity, trade.Uuid, result.Uuid));
                    dbService.InsertMakerOrder(pair.Id, "basesell", trade.Uuid, result.Uuid);
                }
                else if (trade.Side == OrderSide.Buy)
                {
                    var result = await counterExchange.MarketSell(trade.Symbol, quantity);

                    logger.Trace(string.Format("COUNTER SELL {0} {1} {2} {3}", pair.Symbol, quantity, trade.Uuid, result.Uuid));
                    dbService.InsertMakerOrder(pair.Id, "basebuy", trade.Uuid, result.Uuid);
                }
            }
            catch (ApiException ae)
            {
                if (ae.Content.ToLowerInvariant().Contains("insufficient"))
                {
                    pair.Status = "error";
                    dbService.SaveArbitragePair(pair);
                }
                logger.Error(JsonConvert.SerializeObject(JsonConvert.DeserializeObject(ae.Content), Formatting.Indented));
            }
            catch (Exception e)
            {
                logger.Error(e);
            }
        }
Ejemplo n.º 3
0
        public async Task ProcessTrades(ArbitragePair pair, CancellationToken cancellationToken)
        {
            var baseSocket = baseSockets.ContainsKey(pair.Symbol) ? baseSockets[pair.Symbol] : baseExchange.GetSocket();

            baseSockets[pair.Symbol] = baseSocket;

            baseSocket.OnMatch += async(trade) =>
            {
                try
                {
                    if (trade.Symbol == pair.Symbol && trade.QuantityFilled > 0)
                    {
                        logger.Trace(JsonConvert.SerializeObject(trade, Formatting.Indented));

                        await PlaceCounterOrder(pair, trade);
                    }
                }
                catch (AggregateException ae)
                {
                    ae.Handle((x) =>
                    {
                        if (x is ApiException) // This we know how to handle.
                        {
                            logger.Error(((ApiException)x).Content);
                        }
                        return(false); // Let anything else stop the application.
                    });
                    EndWorkForPair(pair);
                }
            };

            baseSocket.SubscribeTrades(pair.Symbol);

            await Task.FromResult(true);
        }
Ejemplo n.º 4
0
        public async Task AuditCompletedOrdersForPair(ArbitragePair pair, CancellationToken cancellationToken)
        {
            foreach (var order in dbService.GetMakerOrdersByStatus("filled", pair.Id).Where(o => o.BaseExchange == baseExchange.Name && o.CounterExchange == counterExchange.Name))
            {
                try
                {
                    var baseOrder = await baseExchange.CheckOrder(order.BaseOrderUuid, pair.Symbol);

                    var counterOrder = await counterExchange.CheckOrder(order.CounterOrderUuid, pair.Symbol);

                    if (baseOrder != null && counterOrder != null)
                    {
                        decimal commission = 0m;
                        if (baseOrder.Side == OrderSide.Buy)
                        {
                            commission = counterOrder.CostProceeds - baseOrder.CostProceeds;
                        }
                        else
                        {
                            commission = baseOrder.CostProceeds - counterOrder.CostProceeds;
                        }

                        dbService.UpdateOrder(order.Id, baseRate: baseOrder.AvgRate, counterRate: counterOrder.AvgRate, baseCost: baseOrder.CostProceeds, counterCost: counterOrder.CostProceeds, commission: commission, status: "complete", baseQuantityFilled: baseOrder.QuantityFilled, counterQuantityFilled: counterOrder.QuantityFilled);
                    }
                    // await EmailHelper.SendSimpleMailAsync(gmail, string.Format("Trade {0} - {1}", baseOrder.Symbol, commission), JsonConvert.SerializeObject(new { baseOrder = baseOrder, counterOrder = counterOrder }, Formatting.Indented));
                }
                catch (Exception e)
                {
                    logger.Error(e);
                }
            }
        }
Ejemplo n.º 5
0
        public static ArbitrageOpportunity FakeOpportunity(ArbitragePair pair)
        {
            decimal baseBuy        = 0M;
            decimal baseSell       = 0M;
            decimal arbBuy         = 0M;
            decimal arbSell        = 0M;
            decimal baseBuySpread  = 0M;
            decimal baseSellSpread = 0M;

            baseBuy  = GetPriceAtVolumeThreshold(pair.TradeThreshold, pair.baseBook.asks);
            baseSell = GetPriceAtVolumeThreshold(pair.TradeThreshold, pair.baseBook.bids);
            arbBuy   = GetPriceAtVolumeThreshold(pair.TradeThreshold, pair.counterBook.asks);
            arbSell  = GetPriceAtVolumeThreshold(pair.TradeThreshold, pair.counterBook.bids);

            if (baseBuy > 0 && baseSell > 0 && arbBuy > 0 && arbSell > 0)
            {
                baseBuySpread  = Math.Abs((baseBuy - arbSell) / baseBuy) - (pair.BaseExchangeFee + pair.CounterExchangeFee);
                baseSellSpread = Math.Abs((baseSell - arbBuy) / baseSell) - (pair.BaseExchangeFee + pair.CounterExchangeFee);

                return(new ArbitrageOpportunity()
                {
                    Type = "basesell",
                    BasePrice = baseSell,
                    CounterPrice = arbBuy,
                    Spread = baseSellSpread
                });
            }
            return(null);
        }
Ejemplo n.º 6
0
        public async Task ProcessTrade(IBaseSocketExchange baseExchange, ArbitragePair pair, IMatch trade)
        {
            if (trade.Symbol == pair.Symbol && trade.QuantityFilled > 0)
            {
                logger.Trace(JsonConvert.SerializeObject(trade, Formatting.Indented));

                await PlaceCounterOrder(pair, trade);
            }
        }
Ejemplo n.º 7
0
        public async Task ProcessOrderBook(ArbitragePair pair, CancellationToken cancellationToken)
        {
            var counterSocket = counterSockets.ContainsKey(pair.Symbol) ? counterSockets[pair.Symbol] : counterExchange.GetSocket();

            counterSockets[pair.Symbol] = counterSocket;

            counterSocket.OnBook += async(book) =>
            {
                if (!cancellationToken.IsCancellationRequested)
                {
                    try
                    {
                        decimal counterBuy  = Helper.RoundPrice(pair, EngineHelper.GetPriceAtVolumeThreshold(pair.BidMultiplier * pair.TradeThreshold, book.asks));
                        decimal counterSell = Helper.RoundPrice(pair, EngineHelper.GetPriceAtVolumeThreshold(pair.AskMultiplier * pair.TradeThreshold, book.bids));

                        //Calculate the BID based off what we can sell for on the counter exchange
                        decimal buy  = Helper.RoundPrice(pair, counterSell - (counterSell * pair.BidSpread));
                        decimal sell = Helper.RoundPrice(pair, counterBuy + (counterBuy * pair.AskSpread));

                        if (buy >= counterSell)
                        {
                            buy -= pair.TickSize;
                        }

                        if (sell <= counterBuy)
                        {
                            sell += pair.TickSize;
                        }

                        var tasks = new List <Task>
                        {
                            PlaceBuyIOC(pair, buy),
                            PlaceSellIOC(pair, sell)
                        };

                        await Task.WhenAll(tasks);
                    }
                    catch (AggregateException ae)
                    {
                        ae.Handle((x) =>
                        {
                            if (x is ApiException) // This we know how to handle.
                            {
                                logger.Error(((ApiException)x).Content);
                            }
                            return(false); // Let anything else stop the application.
                        });
                        EndWorkForPair(pair);
                    }
                }
            };

            counterSocket.SubscribeOrderbook(pair.CounterSymbol);
            await Task.FromResult(true);
        }
Ejemplo n.º 8
0
 public void RegisterPair(ArbitragePair pair, SocketTradeHandler handler)
 {
     if (!_pairs.TryAdd(pair.Symbol, pair))
     {
         throw new Exception("Duplicate pair");
     }
     if (!_handlers.TryAdd(pair.Symbol, handler))
     {
         throw new Exception("Duplicate handler");
     }
 }
Ejemplo n.º 9
0
        void EndWorkForPair(ArbitragePair pair)
        {
            var wtoken = tokens[pair.Symbol];

            // CancellationTokenSource implements IDisposable.
            using (wtoken)
            {
                // Cancel.  This will cancel the task.
                wtoken.Cancel();
            }

            // Set everything to null, since the references
            // are on the class level and keeping them around
            // is holding onto invalid state.
            tokens.Remove(pair.Symbol, out wtoken);
            wtoken = null;
        }
Ejemplo n.º 10
0
        void StartWorkForPair(ArbitragePair pair)
        {
            // Create the token source.
            var wtoken = new CancellationTokenSource();

            // Set the tasks.
            //    var task1 = (ActionBlock<ArbitragePair>)CreateNeverEndingTask((p, ct) => ProcessOrderBook(p, ct), wtoken.Token);
            // var task2 = (ActionBlock<ArbitragePair>)CreateNeverEndingTask((p, ct) => ProcessTrades(p, ct), wtoken.Token);
            var task3 = (ActionBlock <ArbitragePair>)CreateNeverEndingTask((p, ct) => AuditCompletedOrdersForPair(p, ct), wtoken.Token);

            if (tokens.TryAdd(pair.Symbol, wtoken))
            {
                // Start the task.  Post the time.
                //    task1.Post(pair);
                //    task2.Post(pair);
                task3.Post(pair);
            }
        }
Ejemplo n.º 11
0
        private async Task PlaceBuyIOC(IBaseSocketExchange baseExchange, ArbitragePair pair, decimal price)
        {
            decimal buyQuantity = 0;

            try
            {
                //   decimal raw = pair.BidMultiplier * pair.TradeThreshold / price;
                //  buyQuantity = Helper.RoundQuantity(pair, pair.BidMultiplier * pair.TradeThreshold / price);

                buyQuantity = pair.Increment;

                if (buyQuantity > 0)
                {
                    var result = await baseExchange.ImmediateOrCancel("buy", pair.BaseSymbol, buyQuantity, price);

                    Console.WriteLine(string.Format("IOK  BUY {0} {1} {2:P2}", pair.Symbol, price, pair.BidSpread));
                }
                else
                {
                    logger.Error("No Quantity for {0}", pair.Symbol);
                }
            }
            catch (ApiException ae)
            {
                if (ae.Content.ToLowerInvariant().Contains("insufficient"))
                {
                    pair.Status = "error";
                    dbService.SaveArbitragePair(pair);
                }
                logger.Error(JsonConvert.SerializeObject(JsonConvert.DeserializeObject(ae.Content), Formatting.Indented));
            }
            catch (Exception e)
            {
                logger.Error(e);
                Thread.Sleep(1000 * 10);
            }
        }
Ejemplo n.º 12
0
        public void AuditCompletedOrdersForPair(ArbitragePair pair, CancellationToken cancellationToken)
        {
            var orders = dbService.GetMakerOrdersByStatus("filled", pair.Id).Where(o => o.BaseExchange == baseExchange.Name && o.CounterExchange == counterExchange.Name);

            if (orders.Any())
            {
                logger.Trace("Audit {0} orders for {1}", orders.Count(), pair.Symbol);
            }
            else
            {
                logger.Trace("No orders for {0}", pair.Symbol);
            }

            foreach (var order in orders)
            {
                try
                {
                    var baseOrder    = baseExchange.CheckOrder(order.BaseOrderUuid, pair.BaseSymbol).Result;
                    var counterOrder = counterExchange.CheckOrder(order.CounterOrderUuid, pair.CounterSymbol).Result;

                    if (baseOrder != null && counterOrder != null)
                    {
                        decimal commission = 0m;
                        if (baseOrder.Side == OrderSide.Buy)
                        {
                            commission = counterOrder.CostProceeds - baseOrder.CostProceeds;
                        }
                        else
                        {
                            commission = baseOrder.CostProceeds - counterOrder.CostProceeds;
                        }

                        dbService.UpdateOrder(order.Id, baseRate: baseOrder.AvgRate, counterRate: counterOrder.AvgRate, baseCost: baseOrder.CostProceeds, counterCost: counterOrder.CostProceeds, commission: commission, status: "complete", baseQuantityFilled: baseOrder.QuantityFilled, counterQuantityFilled: counterOrder.QuantityFilled);
                    }
                }
                catch (AggregateException ae)
                {
                    ae.Handle((x) =>
                    {
                        if (x is ApiException) // This we know how to handle.
                        {
                            string content = ((ApiException)x).Content;

                            if (content.Contains("Order does not exist")) // Dont know why we are seeing this but update status
                            {
                                dbService.UpdateOrder(order.Id, status: "notexists");
                            }
                            else
                            {
                                logger.Error(content);
                            }
                        }
                        return(true);
                    });
                }
                catch (Exception e)
                {
                    logger.Error(e);
                }
            }
        }
Ejemplo n.º 13
0
        public static async Task <ArbitragePair> AppendCounterMarketData(IDbService dbService, IExchange counterExchange, ArbitragePair pair, bool includeMarket = true, bool includeBook = true)
        {
            if (includeMarket)
            {
                pair.counterMarket = await counterExchange.Ticker(pair.Symbol);
            }

            if (includeBook)
            {
                pair.counterBook = await counterExchange.OrderBook(pair.Symbol);
            }

            if ((pair.counterMarket == null && includeMarket) || (pair.counterBook == null && includeBook))
            {
                var ex = new Exception("No Market Data");
                dbService.LogError("", counterExchange.Name, pair.Symbol, "AppendCounterMarketData", ex, pair.Id);
                Console.WriteLine("{0}: Null Market Data", pair.Symbol);
                throw ex;
            }

            return(pair);
        }
Ejemplo n.º 14
0
 public static decimal RoundPrice(ArbitragePair pair, decimal price)
 {
     return(RoundToIncrement(price, pair.TickSize));
 }
Ejemplo n.º 15
0
 public static decimal RoundQuantity(ArbitragePair pair, decimal quantity)
 {
     return(RoundToIncrement(quantity, pair.Increment));
 }
Ejemplo n.º 16
0
        public static void AuditCompletedOrdersForPair(IDbService dbService, IExchange baseExchange, IExchange counterExchange, ArbitragePair pair)
        {
            foreach (var order in dbService.GetMakerOrdersByStatus("filled", pair.Id).Where(o => o.BaseExchange == baseExchange.Name && o.CounterExchange == counterExchange.Name))
            {
                try
                {
                    var baseOrder    = baseExchange.CheckOrder(order.BaseOrderUuid, pair.Symbol).Result;
                    var counterOrder = counterExchange.CheckOrder(order.CounterOrderUuid, pair.Symbol).Result;

                    if (baseOrder != null && counterOrder != null)
                    {
                        decimal commission = 0m;
                        if (baseOrder.Side == OrderSide.Buy)
                        {
                            commission = counterOrder.CostProceeds - baseOrder.CostProceeds;
                        }
                        else
                        {
                            commission = baseOrder.CostProceeds - counterOrder.CostProceeds;
                        }

                        dbService.UpdateOrder(order.Id, baseRate: baseOrder.AvgRate, counterRate: counterOrder.AvgRate, baseCost: baseOrder.CostProceeds, counterCost: counterOrder.CostProceeds, commission: commission, status: "complete", baseQuantityFilled: baseOrder.QuantityFilled, counterQuantityFilled: counterOrder.QuantityFilled);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }
        }
 public void Save([FromBody] ArbitragePair pair)
 {
     dbService.SaveArbitragePair(pair);
 }