public void TryMatchLimitOrder(ILimitOrder order) { switch (order.Way) { case WayEnum.Buy: if (SellOrders.Count == 0) { return; } while (order.Quantity > 0 && SellOrders.Count > 0) { limitOrderMatchingAlgorithm.TryMatch(order, SellOrders[0]); } break; case WayEnum.Sell: if (BuyOrders.Count == 0) { return; } while (order.Quantity > 0 && BuyOrders.Count > 0) { limitOrderMatchingAlgorithm.TryMatch(BuyOrders[0], order); } break; } }
private static IClientTrade[] CreateTradeRecordForClientWithVolumes(LimitQueueItem.LimitTradeInfo trade, ILimitOrder limitOrder, string btcTransactionId, IWalletCredentials walletCredentialsLimitA, IWalletCredentials walletCredentialsLimitB, double limitVolume, double oppositeLimitVolume) { var clientId = walletCredentialsLimitA?.ClientId ?? limitOrder.ClientId; var mutlisig = walletCredentialsLimitA?.MultiSig; var fromMultisig = walletCredentialsLimitB?.MultiSig; var depositAssetRecord = CreateCommonPartForTradeRecord(trade, limitOrder, btcTransactionId); var withdrawAssetRecord = CreateCommonPartForTradeRecord(trade, limitOrder, btcTransactionId); depositAssetRecord.ClientId = withdrawAssetRecord.ClientId = clientId; depositAssetRecord.AddressFrom = withdrawAssetRecord.AddressFrom = fromMultisig; depositAssetRecord.AddressTo = withdrawAssetRecord.AddressTo = mutlisig; depositAssetRecord.Multisig = withdrawAssetRecord.Multisig = mutlisig; depositAssetRecord.Amount = oppositeLimitVolume; depositAssetRecord.AssetId = trade.OppositeAsset; withdrawAssetRecord.Amount = -1 * limitVolume; withdrawAssetRecord.AssetId = trade.Asset; depositAssetRecord.Id = Utils.GenerateRecordId(depositAssetRecord.DateTime); withdrawAssetRecord.Id = Utils.GenerateRecordId(withdrawAssetRecord.DateTime); return(new IClientTrade[] { depositAssetRecord, withdrawAssetRecord }); }
public void HandleAddLimitOrder(ILimitOrder limitOrder) { string symbol = limitOrder.Symbol; if (!OrderBooks.ContainsKey(symbol)) { var bookMatchingLimitAlgo = new LimitOrderMatchingAlgorithm(dateService); bookMatchingLimitAlgo.AddExecutionsHandler(outgoingQueue.EnqueueClientExecution); var bookMatchingMarketAlgo = new MarketOrderMatchingAlgorithm(dateService); bookMatchingMarketAlgo.AddExecutionsHandler(outgoingQueue.EnqueueClientExecution); var level1 = new OrderBookBestBidAsk(symbol); level1.RegisterUpdateHandler(outgoingQueue.EnqueueLevel1Update); var book = new OrderBook(symbol, bookMatchingLimitAlgo, bookMatchingMarketAlgo, level1); OrderBooks.Add(symbol, book); } outgoingQueue.EnqueueAddedLimitOrder(limitOrder); limitOrder.RegisterDeleteNotificationHandler(OrderBooks[symbol].RemoveLimitOrder); limitOrder.RegisterFilledNotification(OrderBooks[symbol].RemoveLimitOrder); limitOrder.RegisterModifyNotificationHandler(OrderBooks[symbol].HandleLimitOrderModify); OrderBooks[symbol].AddLimitOrder(limitOrder); }
private void HandleDeletedLimitOrder(ILimitOrder order) { order.UnRegisterDeleteNotificationHandler(HandleDeletedLimitOrder); order.UnRegisterFilledNotification(HandleDeletedLimitOrder); LimitOrders.Remove(order.ExchangeOrderId); ClientOrders[order.ClientId].Remove(order); }
public void EnqueueUpdatedLimitOrder(ILimitOrder limitOrder, int oldQuantity, double oldPrice) { serverToClientMessage.Reset(); serverToClientMessage.ReceiverClientId = limitOrder.ClientId; serverToClientMessage.LimitOrder.Update(limitOrder.ToDto()); serverToClientMessage.MessageType = ServerToClientMessageTypeEnum.LimitOrderChanged; Enqueue(); }
public void EnqueueAddedLimitOrder(ILimitOrder limitOrder) { serverToClientMessage.Reset(); serverToClientMessage.ReceiverClientId = limitOrder.ClientId; serverToClientMessage.LimitOrder.Update(limitOrder.ToDto()); serverToClientMessage.MessageType = ServerToClientMessageTypeEnum.LimitOrderAccepted; Enqueue(); }
public static LimitOrderEntity Create(ILimitOrder limitOrder) { var entity = CreateNew(limitOrder); entity.RowKey = GenerateRowKey(limitOrder.Id); entity.PartitionKey = GeneratePartitionKey(limitOrder.CreatedAt); return(entity); }
public void EnqueueDeletedLimitOrder(ILimitOrder limitOrder) { serverToClientMessage.Reset(); serverToClientMessage.ReceiverClientId = limitOrder.ClientId; serverToClientMessage.LimitOrder.Update(limitOrder.ToDto()); serverToClientMessage.MessageType = ServerToClientMessageTypeEnum.LimitOrderDeleted; Enqueue(); }
public static MatchedLimitOrder Create(ILimitOrder limitOrder, double volume) { return(new MatchedLimitOrder { Price = limitOrder.Price, Id = limitOrder.Id, Volume = volume }); }
public void HandleLimitOrderModify(ILimitOrder order, int oldQuantity, double oldPrice) { if (oldPrice != order.Price) { MoveOrder(oldPrice, order); } SetBestBidAndAsk(); }
private double FindMatchPrice(ILimitOrder buyLimitOrder, ILimitOrder sellLimitOrder) { if (buyLimitOrder.Price.Equals(sellLimitOrder.Price)) { return(buyLimitOrder.Price); } priceDifference = buyLimitOrder.Price - sellLimitOrder.Price; return(Math.Min(buyLimitOrder.Price, sellLimitOrder.Price) + (priceDifference / 2)); }
private void MoveOrder(double oldPrice, ILimitOrder currentOrder) { if (PriceSlots.ContainsKey(oldPrice)) { PriceSlots[oldPrice].RemoveOrder(currentOrder); } RemoveSlotIfEmpty(oldPrice); AddLimitOrder(currentOrder); }
public void HandDuoLimitOrderUpdate(ILimitOrder limitOrder1, double limitOrder1NewPrice, int limitOrder1NewQuantity, ILimitOrder limitOrder2, double limitOrder2NewPrice, int limitOrder2NewQuantity) { if (!OrderBooks.ContainsKey(limitOrder1.Symbol)) return; OrderBooks[limitOrder1.Symbol].SetSuspendLimitOrderMatchingStatus(true); limitOrder1.Modify(limitOrder1NewQuantity, limitOrder1NewPrice); limitOrder2.Modify(limitOrder2NewQuantity, limitOrder2NewPrice); OrderBooks[limitOrder1.Symbol].SetSuspendLimitOrderMatchingStatus(false); OrderBooks[limitOrder1.Symbol].TryMatchLimitOrder(limitOrder1); OrderBooks[limitOrder1.Symbol].TryMatchLimitOrder(limitOrder2); }
public void TryMatchLimitOrder(ILimitOrder limitOrder) { if (LimitOrderMatchingIsSuspended) { return; } if (limitOrder.Quantity == 0) { return; } switch (limitOrder.Way) { case WayEnum.Buy: if (!orderBookBestBidAsk.BestAskPrice.HasValue) { return; } if (limitOrder.Price < orderBookBestBidAsk.BestAskPrice) { return; } PriceSlots[orderBookBestBidAsk.BestAskPrice.Value].TryMatchLimitOrder(limitOrder); SetBestBidAndAsk(); TryMatchLimitOrder(limitOrder); break; case WayEnum.Sell: if (!orderBookBestBidAsk.BestBidPrice.HasValue) { return; } if (limitOrder.Price > orderBookBestBidAsk.BestBidPrice) { return; } PriceSlots[orderBookBestBidAsk.BestBidPrice.Value].TryMatchLimitOrder(limitOrder); SetBestBidAndAsk(); TryMatchLimitOrder(limitOrder); break; } }
internal void AddLimitOrder(ILimitOrder limitOrder) { var limitOrderAction = limitOrder.OrderAction(); var orderBookLine = _orderBookLines.FirstOrDefault(itm => itm.OrderAction == limitOrderAction && AssetPair.PricesAreTheSame(itm.Price, limitOrder.Price)); if (orderBookLine == null) { orderBookLine = OrderBookLine.Create(limitOrder.Price, limitOrder.RemainingVolume, limitOrderAction); _orderBookLines.Add(orderBookLine); } else { orderBookLine.Volume += limitOrder.RemainingVolume; } }
public void RemoveOrder(ILimitOrder order) { switch (order.Way) { case WayEnum.Buy: BuyOrders.Remove(order); break; case WayEnum.Sell: SellOrders.Remove(order); break; } order.UnRegisterDeleteNotificationHandler(HandleDeleteOrFilled); order.UnRegisterFilledNotification(HandleDeleteOrFilled); }
public void RemoveLimitOrder(ILimitOrder order) { if (!PriceSlots.ContainsKey(order.Price)) { return; } PriceSlots[order.Price].RemoveOrder(order); RemoveSlotIfEmpty(order.Price); order.UnRegisterDeleteNotificationHandler(RemoveLimitOrder); order.UnRegisterFilledNotification(RemoveLimitOrder); order.UnRegisterModifyNotificationHandler(HandleLimitOrderModify); SetBestBidAndAsk(); }
public void AddLimitOrder(ILimitOrder limitOrder) { TryMatchLimitOrder(limitOrder); if (limitOrder.Quantity == 0) return; if (!PriceSlots.ContainsKey(limitOrder.Price)) PriceSlots.Add(limitOrder.Price, new PriceSlot(limitOrder.Price, limitOrderMatchingAlgorithm, marketOrderMatchingAlgorithm)); if (PriceSlots[limitOrder.Price].ContainsOrder(limitOrder)) return; PriceSlots[limitOrder.Price].AddOrder(limitOrder); SetBestBidAndAsk(); }
public static LimitOrderEntity CreateNew(ILimitOrder limitOrder) { return(new LimitOrderEntity { AssetPairId = limitOrder.AssetPairId, ClientId = limitOrder.ClientId, CreatedAt = limitOrder.CreatedAt, Id = limitOrder.Id, Price = limitOrder.Price, Status = limitOrder.Status, Straight = limitOrder.Straight, Volume = limitOrder.Volume, RemainingVolume = limitOrder.RemainingVolume, MatchingId = limitOrder.MatchingId }); }
private OrderModel FromLimitOrder(ILimitOrder limitOrder) { return(new OrderModel { AvgExecutionPrice = limitOrder.AvgExecutionPrice ?? 0, ExecutedVolume = limitOrder.ExecutedAmount, ExecutionStatus = limitOrder.Status, Id = limitOrder.Id, OriginalVolume = limitOrder.Amount, Price = limitOrder.Price, RemainingAmount = limitOrder.RemainingAmount, Symbol = limitOrder.Instrument, Timestamp = limitOrder.CreatedUtc, TradeType = limitOrder.TradeType, }); }
public void HandDuoLimitOrderUpdate(ILimitOrder limitOrder1, double limitOrder1NewPrice, int limitOrder1NewQuantity, ILimitOrder limitOrder2, double limitOrder2NewPrice, int limitOrder2NewQuantity) { if (!OrderBooks.ContainsKey(limitOrder1.Symbol)) { return; } OrderBooks[limitOrder1.Symbol].SetSuspendLimitOrderMatchingStatus(true); limitOrder1.Modify(limitOrder1NewQuantity, limitOrder1NewPrice); limitOrder2.Modify(limitOrder2NewQuantity, limitOrder2NewPrice); OrderBooks[limitOrder1.Symbol].SetSuspendLimitOrderMatchingStatus(false); OrderBooks[limitOrder1.Symbol].TryMatchLimitOrder(limitOrder1); OrderBooks[limitOrder1.Symbol].TryMatchLimitOrder(limitOrder2); }
private IReadOnlyCollection <OrderTransaction> GetTransactions( ILimitOrder order, IEnumerable <JObject> transactions) { var(cryptoCurrency, _) = GetSymbols(order.Instrument); var result = new List <OrderTransaction>(); foreach (var transaction in transactions) { try { var dict = new Dictionary <string, JToken>(StringComparer.InvariantCultureIgnoreCase); foreach (var keyValue in transaction) { dict[keyValue.Key] = keyValue.Value; } if (!dict.ContainsKey(cryptoCurrency)) { throw new InvalidOperationException($"Result currency not found in response: {cryptoCurrency}"); } var tran = new OrderTransaction { Amount = decimal.Parse(dict[cryptoCurrency].Value <string>(), System.Globalization.NumberStyles.Any), Price = decimal.Parse(dict["price"].Value <string>(), System.Globalization.NumberStyles.Any) }; result.Add(tran); } catch (Exception ex) { _log.Error(ex, context: $"tran: {transaction}, order: {order.ToJson()}"); throw; } } return(result); }
public void AddOrder(ILimitOrder order) { if (order.Price != Price) return; switch (order.Way) { case WayEnum.Buy: BuyOrders.Add(order); break; case WayEnum.Sell: SellOrders.Add(order); break; } order.RegisterDeleteNotificationHandler(HandleDeleteOrFilled); order.RegisterFilledNotification(HandleDeleteOrFilled); }
public bool ContainsOrder(ILimitOrder order) { switch (order.Way) { case WayEnum.Buy: if (BuyOrders.Contains(order)) { return(true); } break; case WayEnum.Sell: if (SellOrders.Contains(order)) { return(true); } break; } return(false); }
public async Task CreateOrUpdateAsync(ILimitOrder limitOrder) { var status = (OrderStatus)Enum.Parse(typeof(OrderStatus), limitOrder.Status); var byOrderEntity = LimitOrderEntity.ByOrderId.Create(limitOrder); var byClientEntity = LimitOrderEntity.ByClientId.Create(limitOrder); var byClientEntityActive = LimitOrderEntity.ByClientIdActive.Create(limitOrder); await _tableStorage.InsertOrMergeAsync(byOrderEntity); await _tableStorage.InsertOrMergeAsync(byClientEntity); if (status == OrderStatus.InOrderBook || status == OrderStatus.Processing) { await _tableStorage.InsertOrMergeAsync(byClientEntityActive); } else { await _tableStorage.DeleteAsync(LimitOrderEntity.ByClientIdActive.GeneratePartitionKey(limitOrder.ClientId), limitOrder.Id); } }
public void AddOrder(ILimitOrder order) { if (order.Price != Price) { return; } switch (order.Way) { case WayEnum.Buy: BuyOrders.Add(order); break; case WayEnum.Sell: SellOrders.Add(order); break; } order.RegisterDeleteNotificationHandler(HandleDeleteOrFilled); order.RegisterFilledNotification(HandleDeleteOrFilled); }
public void TryMatch(ILimitOrder buyLimitOrder, ILimitOrder sellLimitOrder) { /*if (buyLimitOrder.ClientId == sellLimitOrder.ClientId) * return;*/ if (buyLimitOrder.Symbol != sellLimitOrder.Symbol) { return; } if (buyLimitOrder.Price < sellLimitOrder.Price) { return; } if (buyLimitOrder.Quantity == 0 || sellLimitOrder.Quantity == 0) { return; } double matchPrice = FindMatchPrice(buyLimitOrder, sellLimitOrder); int matchQuantity = FindMatchQuantity(buyLimitOrder, sellLimitOrder); if (matchQuantity == 0) { return; } buyLimitOrder.Modify(buyLimitOrder.Quantity - matchQuantity); sellLimitOrder.Modify(sellLimitOrder.Quantity - matchQuantity); var execution = new NewExecution(buyLimitOrder, sellLimitOrder, matchQuantity, matchPrice, dateService.UtcNow()); for (int i = 0; i < executionHandlers.Count; i++) { executionHandlers[i].Invoke(execution); } }
public void AddLimitOrder(ILimitOrder limitOrder) { TryMatchLimitOrder(limitOrder); if (limitOrder.Quantity == 0) { return; } if (!PriceSlots.ContainsKey(limitOrder.Price)) { PriceSlots.Add(limitOrder.Price, new PriceSlot(limitOrder.Price, limitOrderMatchingAlgorithm, marketOrderMatchingAlgorithm)); } if (PriceSlots[limitOrder.Price].ContainsOrder(limitOrder)) { return; } PriceSlots[limitOrder.Price].AddOrder(limitOrder); SetBestBidAndAsk(); }
public void TryMatch(ILimitOrder buyLimitOrder, IMarketOrder sellMarketOrder) { if (sellMarketOrder.Way != WayEnum.Sell || buyLimitOrder.Way != WayEnum.Buy) return; if (sellMarketOrder.Symbol != buyLimitOrder.Symbol) return; if (sellMarketOrder.Quantity == 0 || buyLimitOrder.Quantity == 0) return; int matchQuantity = FindMatchQuantity(sellMarketOrder, buyLimitOrder); if (matchQuantity == 0) return; double matchPrice = buyLimitOrder.Price; sellMarketOrder.Modify(sellMarketOrder.Quantity - matchQuantity); buyLimitOrder.Modify(buyLimitOrder.Quantity - matchQuantity); var execution = new NewExecution(buyLimitOrder, sellMarketOrder, matchQuantity, matchPrice, dateService.UtcNow()); for (int i = 0; i < executionHandlers.Count; i++) executionHandlers[i].Invoke(execution); }
public async Task CreateOrUpdateAsync(ILimitOrder limitOrder) { var tasks = new List <Task> { _tableStorage.InsertOrMergeAsync(LimitOrderEntity.ByDate.Create(limitOrder)), _tableStorage.InsertOrMergeAsync(LimitOrderEntity.ByClientId.Create(limitOrder)), }; var status = (OrderStatus)Enum.Parse(typeof(OrderStatus), limitOrder.Status); if (status == OrderStatus.InOrderBook || status == OrderStatus.Placed || // new version of InOrderBook status == OrderStatus.Processing || status == OrderStatus.PartiallyMatched) // new version of Processing { tasks.Add(_tableStorage.InsertOrMergeAsync(LimitOrderEntity.ByClientIdActive.Create(limitOrder))); } else { tasks.Add(_tableStorage.DeleteIfExistAsync(LimitOrderEntity.ByClientIdActive.GeneratePartitionKey(limitOrder.ClientId), limitOrder.Id)); } await Task.WhenAll(tasks); }
public void TryMatch(ILimitOrder buyLimitOrder, IMarketOrder sellMarketOrder) { if (sellMarketOrder.Way != WayEnum.Sell || buyLimitOrder.Way != WayEnum.Buy) { return; } if (sellMarketOrder.Symbol != buyLimitOrder.Symbol) { return; } if (sellMarketOrder.Quantity == 0 || buyLimitOrder.Quantity == 0) { return; } int matchQuantity = FindMatchQuantity(sellMarketOrder, buyLimitOrder); if (matchQuantity == 0) { return; } double matchPrice = buyLimitOrder.Price; sellMarketOrder.Modify(sellMarketOrder.Quantity - matchQuantity); buyLimitOrder.Modify(buyLimitOrder.Quantity - matchQuantity); var execution = new NewExecution(buyLimitOrder, sellMarketOrder, matchQuantity, matchPrice, dateService.UtcNow()); for (int i = 0; i < executionHandlers.Count; i++) { executionHandlers[i].Invoke(execution); } }
public void RemoveLimitOrder(ILimitOrder order) { if (!PriceSlots.ContainsKey(order.Price)) return; PriceSlots[order.Price].RemoveOrder(order); RemoveSlotIfEmpty(order.Price); order.UnRegisterDeleteNotificationHandler(RemoveLimitOrder); order.UnRegisterFilledNotification(RemoveLimitOrder); order.UnRegisterModifyNotificationHandler(HandleLimitOrderModify); SetBestBidAndAsk(); }
private int FindMatchQuantity(ILimitOrder buyLimitOrder, ILimitOrder sellLimitOrder) { return(Math.Min(buyLimitOrder.Quantity, sellLimitOrder.Quantity)); }
public DuoLimitOrder(ILimitOrder limitOrder1, ILimitOrder limitOrder2) { LimitOrder1 = limitOrder1; LimitOrder2 = limitOrder2; }
private void MoveOrder(double oldPrice, ILimitOrder currentOrder) { if (PriceSlots.ContainsKey(oldPrice)) PriceSlots[oldPrice].RemoveOrder(currentOrder); RemoveSlotIfEmpty(oldPrice); AddLimitOrder(currentOrder); }
public void TryMatchLimitOrder(ILimitOrder limitOrder) { if (LimitOrderMatchingIsSuspended) return; if (limitOrder.Quantity == 0) return; switch (limitOrder.Way) { case WayEnum.Buy: if (!orderBookBestBidAsk.BestAskPrice.HasValue) return; if (limitOrder.Price < orderBookBestBidAsk.BestAskPrice) return; PriceSlots[orderBookBestBidAsk.BestAskPrice.Value].TryMatchLimitOrder(limitOrder); SetBestBidAndAsk(); TryMatchLimitOrder(limitOrder); break; case WayEnum.Sell: if (!orderBookBestBidAsk.BestBidPrice.HasValue) return; if (limitOrder.Price > orderBookBestBidAsk.BestBidPrice) return; PriceSlots[orderBookBestBidAsk.BestBidPrice.Value].TryMatchLimitOrder(limitOrder); SetBestBidAndAsk(); TryMatchLimitOrder(limitOrder); break; } }
private int FindMatchQuantity(IMarketOrder marketOrder, ILimitOrder limitOrder) { return Math.Min(marketOrder.Quantity, limitOrder.Quantity); }
public void HandleLimitOrderModify(ILimitOrder order, int oldQuantity, double oldPrice) { if (oldPrice != order.Price) MoveOrder(oldPrice, order); SetBestBidAndAsk(); }
private void HandleDeleteOrFilled(ILimitOrder order) { RemoveOrder(order); }
public void TryMatchLimitOrder(ILimitOrder order) { switch (order.Way) { case WayEnum.Buy: if (SellOrders.Count == 0) return; while (order.Quantity > 0 && SellOrders.Count > 0) limitOrderMatchingAlgorithm.TryMatch(order, SellOrders[0]); break; case WayEnum.Sell: if (BuyOrders.Count == 0) return; while (order.Quantity > 0 && BuyOrders.Count > 0) limitOrderMatchingAlgorithm.TryMatch(BuyOrders[0], order); break; } }
public bool ContainsOrder(ILimitOrder order) { switch (order.Way) { case WayEnum.Buy: if (BuyOrders.Contains(order)) return true; break; case WayEnum.Sell: if (SellOrders.Contains(order)) return true; break; } return false; }
public Task InsertAsync(ILimitOrder order, string internalApiKey) { return(_storage.InsertAsync(LimitOrderEntity.ByOrder.Create(order, internalApiKey))); }
private int FindMatchQuantity(IMarketOrder marketOrder, ILimitOrder limitOrder) { return(Math.Min(marketOrder.Quantity, limitOrder.Quantity)); }