Пример #1
0
        private async Task GetInitialTickPrices()
        {
            foreach (var instrument in Instruments)
            {
                try
                {
                    var orderBook =
                        await apiClient.MakeGetRequestAsync <List <OrderBook> >(
                            $"{Config.EndpointUrl}/api/OrderBooks/{instrument.Name}", ctSource.Token);

                    var tickPrices = orderBook.GroupBy(x => x.AssetPair)
                                     .Select(g => new TickPrice(
                                                 new Instrument(Name, g.Key),
                                                 g.FirstOrDefault()?.Timestamp ?? DateTime.UtcNow,
                                                 g.FirstOrDefault(ob => !ob.IsBuy)?.Prices.Select(x => x.Price).DefaultIfEmpty(0).Min() ?? 0,
                                                 g.FirstOrDefault(ob => ob.IsBuy)?.Prices.Select(x => x.Price).DefaultIfEmpty(0).Max() ?? 0)
                                             )
                                     .Where(x => x.Ask > 0 && x.Bid > 0);

                    foreach (var tickPrice in tickPrices)
                    {
                        _lastAsks[instrument.Name] = tickPrice.Ask;
                        _lastBids[instrument.Name] = tickPrice.Bid;

                        await _tickPriceHandler.Handle(tickPrice);
                    }
                }
                catch (Exception e)
                {
                    await LykkeLog.WriteErrorAsync(nameof(LykkeExchange), nameof(GetInitialTickPrices), e);
                }
            }
        }
Пример #2
0
        private async Task HandleOrderStatus(LimitOrderMessage message)
        {
            foreach (var order in message.Orders.Where(x => x.Order.ClientId == Config.ClientId))
            {
                if (order.Order.Status == OrderStatus.Cancelled)
                {
                    await LykkeLog.WriteInfoAsync(nameof(LykkeExchange), nameof(HandleOrderStatus), order.ToString(),
                                                  "Order canceled. Calling ExecutedTradeHandlers");

                    await _tradeHandler.Handle(new ExecutionReport(new Instrument(Name, order.Order.AssetPairId),
                                                                   DateTime.UtcNow,
                                                                   order.Order.Price ?? 0,
                                                                   Math.Abs(order.Order.Volume),
                                                                   order.Order.Volume < 0 ? TradeType.Sell : TradeType.Buy,
                                                                   order.Order.ExternalId,
                                                                   OrderExecutionStatus.Cancelled));
                }
                else if (order.Order.Status == OrderStatus.Matched && order.Trades.Any())
                {
                    await LykkeLog.WriteInfoAsync(nameof(LykkeExchange), nameof(HandleOrderStatus), order.ToString(),
                                                  "Order executed. Calling ExecutedTradeHandlers");

                    await _tradeHandler.Handle(new ExecutionReport(new Instrument(Name, order.Order.AssetPairId),
                                                                   order.Trades.Last().Timestamp,
                                                                   order.Order.Price ?? order.Trades.Last().Price ?? 0,
                                                                   Math.Abs(order.Order.Volume - order.Order.RemainingVolume),
                                                                   order.Order.Volume < 0 ? TradeType.Sell : TradeType.Buy,
                                                                   order.Order.ExternalId,
                                                                   OrderExecutionStatus.Fill));
                }
            }
        }
Пример #3
0
        private async Task LogAsync(Exception ex, [CallerMemberName] string context = null)
        {
            if (LykkeLog == null)
            {
                return;
            }

            await LykkeLog.WriteErrorAsync(_gdaxExchangeTypeName, _gdaxExchangeTypeName, context, ex);
        }
Пример #4
0
        protected override void StartImpl()
        {
            LykkeLog.WriteInfoAsync(nameof(LykkeExchange), nameof(StartImpl), string.Empty, $"Starting {Name} exchange").Wait();

            ctSource = new CancellationTokenSource();

            //StartWampConnection(); // TODO: wamp sends strange tickprices with ask=bid, temporary switch to direct rabbitmq connection:

            StartRabbitMqTickPriceSubscription();
            StartRabbitMqOrdersSubscription();
            OnConnected();
        }
Пример #5
0
        private async Task <bool> CheckServerTime(CancellationToken cancellationToken)
        {
            var serverTime = await publicData.GetServerTime(cancellationToken);

            var  now                   = DateTime.UtcNow;
            long differenceTicks       = Math.Abs(serverTime.FromUnixTime.Ticks - now.Ticks);
            bool differenceInThreshold = differenceTicks <= TimeSpan.FromMinutes(2).Ticks;

            await LykkeLog.WriteInfoAsync(
                nameof(Kraken),
                nameof(KrakenExchange),
                nameof(pricesJob),
                $"Server time: {serverTime.FromUnixTime}; now: {now}; difference ticks: {differenceTicks}. In threshold: {differenceInThreshold}");

            return(differenceInThreshold);
        }
Пример #6
0
        private async Task LogAsync(string message, [CallerMemberName] string context = null)
        {
            const int maxMessageLength = 32000;

            if (LykkeLog == null)
            {
                return;
            }

            if (message.Length >= maxMessageLength)
            {
                message = message.Substring(0, maxMessageLength);
            }

            await LykkeLog.WriteInfoAsync(_gdaxExchangeTypeName, _gdaxExchangeTypeName, context, message);
        }
Пример #7
0
        private async Task <TResult> ExecuteApiMethod <TResult>(Func <CancellationToken, Task <TResult> > method, CancellationToken token)
        {
            try
            {
                var response = await method(token);

                return(response);
            }
            catch (ApiException ex)
            {
                await LykkeLog.WriteErrorAsync(nameof(BitfinexExchange), method.Method.Name, ex);

                throw;
            }
            catch (Exception ex)
            {
                await LykkeLog.WriteErrorAsync(nameof(BitfinexExchange), method.Method.Name, ex);

                throw new ApiException(ex.Message, HttpStatusCode.InternalServerError);
            }
        }
Пример #8
0
        public override async Task <long> CancelOrder(long orderId, TimeSpan timeout)
        {
            using (var cts = new CancellationTokenSource(timeout))
            {
                try
                {
                    var response = await ExecuteApiMethod(_exchangeApi.CancelOrderAsync, orderId, cts.Token);

                    return(response.Id);
                }
                catch (ApiException ex)
                {
                    if (ex.Message == "Order could not be cancelled.")
                    {
                        LykkeLog.WriteInfo(nameof(BitfinexExchange), null, ex.Message);
                        return(orderId);
                    }

                    throw;
                }
            }
        }
Пример #9
0
        protected override void StartImpl()
        {
            ctSource = new CancellationTokenSource();

            CheckServerTime(ctSource.Token)
            .ContinueWith(task =>
            {
                if (!task.IsFaulted && task.Result)
                {
                    OnConnected();
                }
            });

            if (config.PubQuotesToRabbit)
            {
                pricesJob = Task.Run(async() =>
                {
                    var lasts = Instruments.ToDictionary(x => x.Name, x => 0L);

                    while (!ctSource.IsCancellationRequested)
                    {
                        try
                        {
                            foreach (var pair in config.SupportedCurrencySymbols)
                            {
                                SpreadDataResult result;

                                try
                                {
                                    result = await publicData.GetSpread(ctSource.Token, pair.ExchangeSymbol, lasts[pair.LykkeSymbol]);
                                }
                                catch (Exception e)
                                {
                                    await LykkeLog.WriteErrorAsync(
                                        nameof(Kraken),
                                        nameof(KrakenExchange),
                                        nameof(pricesJob),
                                        e);
                                    continue;
                                }

                                lasts[pair.LykkeSymbol] = result.Last;
                                var prices = result.Data.Single().Value.Select(x =>
                                                                               new TickPrice(Instruments.Single(i => i.Name == pair.LykkeSymbol),
                                                                                             x.Time, x.Ask, x.Bid)).ToArray();

                                if (prices.Any())
                                {
                                    if (prices.Length == 1 && prices[0].Time == DateTimeUtils.FromUnix(lasts[pair.LykkeSymbol]))
                                    {
                                        // If there is only one price and it has timestamp of last one, ignore it.
                                    }
                                    else
                                    {
                                        foreach (var tickPrice in prices)
                                        {
                                            await _tickPriceHandler.Handle(tickPrice);
                                        }
                                    }
                                }

                                await Task.Delay(TimeSpan.FromSeconds(10), ctSource.Token);
                            }

                            await CheckExecutedOrders();
                        }
                        catch (Exception e)
                        {
                            await LykkeLog.WriteErrorAsync(
                                nameof(Kraken),
                                nameof(KrakenExchange),
                                nameof(pricesJob),
                                e);
                        }
                    }

                    OnStopped();
                });
            }
        }
Пример #10
0
        protected override void StartImpl()
        {
            ctSource = new CancellationTokenSource();
            var random = new Random();

            var nPoints = 10000000;

            var gbms =
                Instruments.ToDictionary(x => x,
                                         x => new GeometricalBrownianMotion(1.0, 0.95, 1.0, nPoints, 0, random));

            streamJob = Task.Run(async() =>
            {
                OnConnected();

                while (!ctSource.IsCancellationRequested)
                {
                    foreach (var instrument in Instruments)
                    {
                        try
                        {
                            var currentTickPrice = new TickPrice(instrument, DateTime.UtcNow, Math.Round((decimal)gbms[instrument].GenerateNextValue(), 6));

                            lock (syncRoot)
                            {
                                var trades         = new List <ExecutionReport>();
                                var executedOrders = new List <TradingSignal>();

                                foreach (var tradingSignal in ActualSignals[instrument.Name].Where(x => x.Volume > 0))
                                {
                                    if (tradingSignal.TradeType == TradeType.Buy &&
                                        currentTickPrice.Ask <= tradingSignal.Price)
                                    {
                                        var trade = new ExecutionReport(
                                            instrument,
                                            DateTime.UtcNow,
                                            tradingSignal.Price.Value,
                                            tradingSignal.Volume,
                                            TradeType.Buy,
                                            tradingSignal.OrderId,
                                            OrderExecutionStatus.Fill);

                                        trades.Add(trade);
                                        executedOrders.Add(tradingSignal);

                                        LykkeLog.WriteInfoAsync(nameof(StubExchange), nameof(StartImpl), nameof(streamJob),
                                                                $"EXECUTION of order {tradingSignal} by price {trade.Price}").Wait();
                                    }
                                    else if (tradingSignal.TradeType == TradeType.Sell &&
                                             currentTickPrice.Bid >= tradingSignal.Price)
                                    {
                                        var trade = new ExecutionReport(instrument,
                                                                        DateTime.UtcNow,
                                                                        tradingSignal.Price.Value,
                                                                        tradingSignal.Volume,
                                                                        TradeType.Sell,
                                                                        tradingSignal.OrderId,
                                                                        OrderExecutionStatus.Fill);

                                        trades.Add(trade);
                                        executedOrders.Add(tradingSignal);

                                        LykkeLog.WriteInfoAsync(nameof(StubExchange), nameof(streamJob), trade.ToString(),
                                                                $"EXECUTION of order {tradingSignal} by price {trade.Price}").Wait();
                                    }
                                }

                                foreach (var signal in executedOrders)
                                {
                                    ActualSignals[instrument.Name].Remove(signal);
                                    LykkeLog.WriteInfoAsync(nameof(StubExchange), nameof(StartImpl), nameof(streamJob),
                                                            $"Trading order {signal} was removed from actual signals as executed").Wait();
                                }

                                trades.ForEach(async x =>
                                {
                                    Positions[instrument.Name].AddTrade(x);
                                    try
                                    {
                                        await _tradeHandler.Handle(x);
                                    }
                                    catch (Exception e)
                                    {
                                        Console.WriteLine(e);
                                    }
                                });


                                if (++counter % 100 == 0)
                                {
                                    LykkeLog.WriteInfoAsync(nameof(StubExchange), nameof(StartImpl), nameof(streamJob),
                                                            $"Step {counter}, total PnL: {Positions[instrument.Name].GetPnL(currentTickPrice.Mid)}").Wait();
                                }
                            }

                            // TODO: deal with awaitable. I don't want to wait here for Azure and Rabbit connections
                            await _tickPriceHandler.Handle(currentTickPrice);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e);
                        }

                        await Task.Delay(config.PricesIntervalInMilliseconds, ctSource.Token);
                    }
                }

                OnStopped();
            });
        }