private async Task ProcessTradeAsync(MtTradeMessage message) { // Just discarding trades with negative or zero prices and\or volumes. if (message.Price <= 0 || message.Volume <= 0) { await _log.WriteWarningAsync(nameof(ProcessTradeAsync), message.ToJson(), "Got an MT trade with non-positive price or volume value."); return; } var quotingVolume = (double)(message.Volume * message.Price); var trade = new Trade( message.AssetPairId, message.Date, (double)message.Volume, quotingVolume, (double)message.Price); await _candlesManager.ProcessTradeAsync(trade); }
private async Task ProcessLimitTradesAsync(LimitOrdersMessage message) { if (message.Orders == null || !message.Orders.Any()) { return; } var limitOrderIds = message.Orders .Select(o => o.Order.Id) .ToHashSet(); foreach (var orderMessage in message.Orders) { if (orderMessage.Trades == null) { continue; } var assetPair = await _assetPairsManager.TryGetEnabledPairAsync(orderMessage.Order.AssetPairId); foreach (var tradeMessage in orderMessage.Trades.OrderBy(t => t.Timestamp).ThenBy(t => t.Index)) { // If both orders of the trade are limit, then both of them should be contained in the single message, // this is by design. var isOppositeOrderIsLimit = limitOrderIds.Contains(tradeMessage.OppositeOrderId); // If opposite order is market order, then unconditionally takes the given limit order. // But if both of orders are limit orders, we should take only one of them. if (isOppositeOrderIsLimit) { var isBuyOrder = orderMessage.Order.Volume > 0; // Takes trade only for the sell limit orders if (isBuyOrder) { continue; } } // Volumes in the asset pair base and quoting assets double baseVolume; double quotingVolume; if (tradeMessage.Asset == assetPair.BaseAssetId) { baseVolume = tradeMessage.Volume; quotingVolume = tradeMessage.OppositeVolume; } else { baseVolume = tradeMessage.OppositeVolume; quotingVolume = tradeMessage.Volume; } // Just discarding trades with negative prices and\or volumes. It's better to do it here instead of // at the first line of foreach 'case we have some additional trade selection logic in the begining. // ReSharper disable once InvertIf if (tradeMessage.Price > 0 && baseVolume > 0 && quotingVolume > 0) { var trade = new Trade( orderMessage.Order.AssetPairId, tradeMessage.Timestamp, baseVolume, quotingVolume, tradeMessage.Price ); await _candlesManager.ProcessTradeAsync(trade); } else { await _log.WriteWarningAsync(nameof(ProcessLimitTradesAsync), tradeMessage.ToJson(), "Got a Spot trade with non-positive price or volume value."); } } } }