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)); } } }
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(); }
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); }
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); }
private async Task <TResult> ExecuteApiMethod <TRequest, TResult>(Func <TRequest, CancellationToken, Task <TResult> > method, TRequest request, CancellationToken token) { try { var response = await method(request, token); return(response); } catch (ApiException ex) { await LykkeLog.WriteInfoAsync(nameof(BitfinexExchange), method.Method.Name, request.ToString(), ex.Message); throw; } catch (Exception ex) { await LykkeLog.WriteWarningAsync(nameof(BitfinexExchange), method.Method.Name, request.ToString(), ex); throw new ApiException(ex.Message, HttpStatusCode.InternalServerError); } }
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(); }); }