/// <summary> /// Gets all orders not yet closed /// </summary> /// <returns></returns> public override List<Order> GetOpenOrders() { var list = new List<Order>(); var req = new RestRequest("/orders?status=open&status=pending", Method.GET); GetAuthenticationToken(req); var response = ExecuteRestRequest(req, GdaxEndpointType.Private); if (response.StatusCode != HttpStatusCode.OK) { throw new Exception($"GDAXBrokerage.GetOpenOrders: request failed: [{(int) response.StatusCode}] {response.StatusDescription}, Content: {response.Content}, ErrorMessage: {response.ErrorMessage}"); } var orders = JsonConvert.DeserializeObject<Messages.Order[]>(response.Content); foreach (var item in orders) { Order order; if (item.Type == "market") { order = new MarketOrder { Price = item.Price }; } else if (item.Type == "limit") { order = new LimitOrder { LimitPrice = item.Price }; } else if (item.Type == "stop") { order = new StopMarketOrder { StopPrice = item.Price }; } else { OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Error, (int)response.StatusCode, "GDAXBrokerage.GetOpenOrders: Unsupported order type returned from brokerage: " + item.Type)); continue; } order.Quantity = item.Side == "sell" ? -item.Size : item.Size; order.BrokerId = new List<string> { item.Id }; order.Symbol = ConvertProductId(item.ProductId); order.Time = DateTime.UtcNow; order.Status = ConvertOrderStatus(item); order.Price = item.Price; list.Add(order); } foreach (var item in list) { if (item.Status.IsOpen()) { var cached = CachedOrderIDs.Where(c => c.Value.BrokerId.Contains(item.BrokerId.First())); if (cached.Any()) { CachedOrderIDs[cached.First().Key] = item; } } } return list; }
private void OrderMatch(string data) { var message = JsonConvert.DeserializeObject <Messages.Matched>(data, JsonSettings); var cached = CachedOrderIDs.Where(o => o.Value.BrokerId.Contains(message.MakerOrderId) || o.Value.BrokerId.Contains(message.TakerOrderId)); var symbol = ConvertProductId(message.ProductId); if (!cached.Any()) { return; } Log.Trace($"GDAXBrokerage.OrderMatch(): Match: {message.ProductId} {data}"); var orderId = cached.First().Key; var orderObj = cached.First().Value; if (!FillSplit.ContainsKey(orderId)) { FillSplit[orderId] = new GDAXFill(orderObj); } var split = FillSplit[orderId]; split.Add(message); //is this the total order at once? Is this the last split fill? var status = Math.Abs(message.Size) == Math.Abs(cached.Single().Value.Quantity) || Math.Abs(split.OrderQuantity) == Math.Abs(split.TotalQuantity()) ? OrderStatus.Filled : OrderStatus.PartiallyFilled; OrderDirection direction; // Messages are always from the perspective of the market maker. Flip it in cases of a market order. if (orderObj.Type == OrderType.Market) { direction = message.Side == "sell" ? OrderDirection.Buy : OrderDirection.Sell; } else { direction = message.Side == "sell" ? OrderDirection.Sell : OrderDirection.Buy; } var orderEvent = new OrderEvent ( cached.First().Key, symbol, message.Time, status, direction, message.Price, direction == OrderDirection.Sell ? -message.Size : message.Size, GetFee(cached.First().Value), $"GDAX Match Event {direction}" ); //if we're filled we won't wait for done event if (orderEvent.Status == OrderStatus.Filled) { Orders.Order outOrder = null; CachedOrderIDs.TryRemove(cached.First().Key, out outOrder); } OnOrderEvent(orderEvent); }
private void OrderDone(string data) { Log.Trace($"GDAXBrokerage.Messaging.OrderDone(): Order completed with data {data}"); var message = JsonConvert.DeserializeObject <Messages.Done>(data, JsonSettings); //if we don't exit now, will result in fill message if (message.Reason == "canceled" || message.RemainingSize > 0) { Log.Trace($"GDAXBrokerage.Messaging.OrderDone(): Order cancelled. Remaining {message.RemainingSize}"); return; } //is this our order? var cached = CachedOrderIDs.Where(o => o.Value.BrokerId.Contains(message.OrderId)).ToList(); if (cached.Count == 0 || cached[0].Value.Status == OrderStatus.Filled) { Log.Trace($"GDAXBrokerage.Messaging.OrderDone(): Order could not locate order in cache with order id {message.OrderId}"); return; } var orderId = cached[0].Key; OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Information, -1, $"GDAXWebsocketsBrokerage.OrderDone: Encountered done message prior to match filling order brokerId: {message.OrderId} orderId: {orderId}")); var split = FillSplit[orderId]; var symbol = ConvertProductId(message.ProductId); var fillPrice = message.Price; var fillQuantity = message.Side == "sell" ? -split.TotalQuantity() : split.TotalQuantity(); var orderFee = GetFillFee(symbol, fillPrice, fillQuantity, true); //should have already been filled but match message may have been missed. Let's say we've filled now var orderEvent = new OrderEvent ( orderId, symbol, message.Time, OrderStatus.Filled, message.Side == "sell" ? OrderDirection.Sell : OrderDirection.Buy, fillPrice, fillQuantity, orderFee, "GDAX Fill Event" ); Order outOrder; CachedOrderIDs.TryRemove(orderId, out outOrder); OnOrderEvent(orderEvent); }
private void OrderDone(string data) { var message = JsonConvert.DeserializeObject <Messages.Done>(data, JsonSettings); //if we don't exit now, will result in fill message if (message.Reason == "canceled" || message.RemainingSize > 0) { return; } //is this our order? var cached = CachedOrderIDs.Where(o => o.Value.BrokerId.Contains(message.OrderId)); if (!cached.Any() || cached.Single().Value.Status == OrderStatus.Filled) { return; } OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Information, -1, $"GDAXWebsocketsBrokerage.OrderDone: Encountered done message prior to match filling order brokerId: {message.OrderId} orderId: {cached.FirstOrDefault().Key}")); var split = this.FillSplit[cached.First().Key]; //should have already been filled but match message may have been missed. Let's say we've filled now var orderEvent = new OrderEvent ( cached.First().Key, ConvertProductId(message.ProductId), message.Time, OrderStatus.Filled, message.Side == "sell" ? OrderDirection.Sell : OrderDirection.Buy, message.Price, message.Side == "sell" ? -split.TotalQuantity() : split.TotalQuantity(), GetFee(cached.First().Value), "GDAX Fill Event" ); Orders.Order outOrder = null; CachedOrderIDs.TryRemove(cached.First().Key, out outOrder); OnOrderEvent(orderEvent); }
private void OrderMatch(string data) { var message = JsonConvert.DeserializeObject <Messages.Matched>(data, JsonSettings); var cached = CachedOrderIDs.Where(o => o.Value.BrokerId.Contains(message.MakerOrderId) || o.Value.BrokerId.Contains(message.TakerOrderId)); var symbol = ConvertProductId(message.ProductId); if (!cached.Any()) { return; } var split = this.FillSplit[cached.First().Key]; split.Add(message); //is this the total order at once? Is this the last split fill? var status = Math.Abs(message.Size) == Math.Abs(cached.Single().Value.Quantity) || Math.Abs(split.OrderQuantity) == Math.Abs(split.TotalQuantity()) ? OrderStatus.Filled : OrderStatus.PartiallyFilled; var orderEvent = new OrderEvent ( cached.First().Key, symbol, message.Time, status, message.Side == "sell" ? OrderDirection.Sell : OrderDirection.Buy, message.Price, message.Side == "sell" ? -message.Size : message.Size, GetFee(cached.First().Value), "GDAX Match Event" ); //if we're filled we won't wait for done event if (orderEvent.Status == OrderStatus.Filled) { Orders.Order outOrder = null; CachedOrderIDs.TryRemove(cached.First().Key, out outOrder); } OnOrderEvent(orderEvent); }
/// <summary> /// Gets all orders not yet closed /// </summary> /// <returns></returns> public override List <Order> GetOpenOrders() { var orders = _apiClient.GetOpenOrders(); List <Order> list = new List <Order>(); foreach (var item in orders) { Order order; switch (item.Type.LazyToUpper()) { case "MARKET": order = new MarketOrder { Price = item.Price }; break; case "LIMIT": case "LIMIT_MAKER": order = new LimitOrder { LimitPrice = item.Price }; break; case "STOP_LOSS": case "TAKE_PROFIT": order = new StopMarketOrder { StopPrice = item.StopPrice, Price = item.Price }; break; case "STOP_LOSS_LIMIT": case "TAKE_PROFIT_LIMIT": order = new StopLimitOrder { StopPrice = item.StopPrice, LimitPrice = item.Price }; break; default: OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Error, -1, "BinanceBrokerage.GetOpenOrders: Unsupported order type returned from brokerage: " + item.Type)); continue; } order.Quantity = item.Quantity; order.BrokerId = new List <string> { item.Id }; order.Symbol = _symbolMapper.GetLeanSymbol(item.Symbol, SecurityType.Crypto, Market.Binance); order.Time = Time.UnixMillisecondTimeStampToDateTime(item.Time); order.Status = ConvertOrderStatus(item.Status); order.Price = item.Price; if (order.Status.IsOpen()) { var cached = CachedOrderIDs.Where(c => c.Value.BrokerId.Contains(order.BrokerId.First())).ToList(); if (cached.Any()) { CachedOrderIDs[cached.First().Key] = order; } } list.Add(order); } return(list); }
/// <summary> /// Gets all orders not yet closed /// </summary> /// <returns></returns> public override List <Order> GetOpenOrders() { var list = new List <Order>(); var endpoint = GetEndpoint("orders"); var request = new RestRequest(endpoint, Method.POST); JsonObject payload = new JsonObject(); payload.Add("request", endpoint); payload.Add("nonce", GetNonce().ToStringInvariant()); request.AddJsonBody(payload.ToString()); SignRequest(request, payload.ToString()); var response = ExecuteRestRequest(request); if (response.StatusCode != HttpStatusCode.OK) { throw new Exception($"BitfinexBrokerage.GetOpenOrders: request failed: [{(int)response.StatusCode}] {response.StatusDescription}, Content: {response.Content}, ErrorMessage: {response.ErrorMessage}"); } var orders = JsonConvert.DeserializeObject <Messages.Order[]>(response.Content) .Where(OrderFilter(_algorithm.BrokerageModel.AccountType)); foreach (var item in orders) { Order order; if (item.Type.Replace("exchange", "").Trim() == "market") { order = new MarketOrder { Price = item.Price }; } else if (item.Type.Replace("exchange", "").Trim() == "limit") { order = new LimitOrder { LimitPrice = item.Price }; } else if (item.Type.Replace("exchange", "").Trim() == "stop") { order = new StopMarketOrder { StopPrice = item.Price }; } else { OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Error, (int)response.StatusCode, "BitfinexBrokerage.GetOpenOrders: Unsupported order type returned from brokerage: " + item.Type)); continue; } order.Quantity = item.Side == "sell" ? -item.OriginalAmount : item.OriginalAmount; order.BrokerId = new List <string> { item.Id }; order.Symbol = _symbolMapper.GetLeanSymbol(item.Symbol); order.Time = Time.UnixTimeStampToDateTime(item.Timestamp); order.Status = ConvertOrderStatus(item); order.Price = item.Price; list.Add(order); } foreach (var item in list) { if (item.Status.IsOpen()) { var cached = CachedOrderIDs.Where(c => c.Value.BrokerId.Contains(item.BrokerId.First())); if (cached.Any()) { CachedOrderIDs[cached.First().Key] = item; } } } return(list); }
private void OrderMatch(string data) { var message = JsonConvert.DeserializeObject <Messages.Matched>(data, JsonSettings); if (_isDataQueueHandler) { EmitTradeTick(message); } var cached = CachedOrderIDs .Where(o => o.Value.BrokerId.Contains(message.MakerOrderId) || o.Value.BrokerId.Contains(message.TakerOrderId)) .ToList(); var symbol = ConvertProductId(message.ProductId); if (cached.Count == 0) { return; } Log.Trace($"GDAXBrokerage.OrderMatch(): Match: {message.ProductId} {data}"); var orderId = cached[0].Key; var order = cached[0].Value; if (!FillSplit.ContainsKey(orderId)) { FillSplit[orderId] = new GDAXFill(order); } var split = FillSplit[orderId]; split.Add(message); //is this the total order at once? Is this the last split fill? var status = Math.Abs(message.Size) == Math.Abs(order.Quantity) || Math.Abs(split.OrderQuantity) == Math.Abs(split.TotalQuantity()) ? OrderStatus.Filled : OrderStatus.PartiallyFilled; OrderDirection direction; // Messages are always from the perspective of the market maker. Flip direction if executed as a taker. if (order.BrokerId[0] == message.TakerOrderId) { direction = message.Side == "sell" ? OrderDirection.Buy : OrderDirection.Sell; } else { direction = message.Side == "sell" ? OrderDirection.Sell : OrderDirection.Buy; } decimal totalOrderFee; if (!_orderFees.TryGetValue(orderId, out totalOrderFee)) { totalOrderFee = GetFee(order); _orderFees[orderId] = totalOrderFee; } // apply order fee on a pro rata basis var orderFee = totalOrderFee * Math.Abs(message.Size) / Math.Abs(order.Quantity); var orderEvent = new OrderEvent ( orderId, symbol, message.Time, status, direction, message.Price, direction == OrderDirection.Sell ? -message.Size : message.Size, orderFee, $"GDAX Match Event {direction}" ); //if we're filled we won't wait for done event if (orderEvent.Status == OrderStatus.Filled) { Order outOrder; CachedOrderIDs.TryRemove(orderId, out outOrder); decimal outOrderFee; _orderFees.TryRemove(orderId, out outOrderFee); } OnOrderEvent(orderEvent); }