/// <summary> /// Places a new order and assigns a new broker ID to the order /// </summary> /// <param name="order">The order to be placed</param> /// <returns>True if the request for a new order has been placed, false otherwise</returns> public override bool PlaceOrder(Order order) { const int orderFee = 0; ApiResponse <InlineResponse201> response; lock (_locker) { var request = GenerateOrderRequest(order); response = _apiRest.CreateOrder(Authorization, AccountId, request); order.BrokerId.Add(response.Data.OrderCreateTransaction.Id); // send Submitted order event order.PriceCurrency = SecurityProvider.GetSecurity(order.Symbol).SymbolProperties.QuoteCurrency; OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee) { Status = OrderStatus.Submitted }); } // if market order, find fill quantity and price var fill = response.Data.OrderFillTransaction; var marketOrderFillPrice = 0m; var marketOrderFillQuantity = 0; if (order.Type == OrderType.Market) { marketOrderFillPrice = Convert.ToDecimal(fill.Price); if (fill.TradeOpened != null && fill.TradeOpened.TradeID.Length > 0) { marketOrderFillQuantity = Convert.ToInt32(fill.TradeOpened.Units); } if (fill.TradeReduced != null && fill.TradeReduced.TradeID.Length > 0) { marketOrderFillQuantity = Convert.ToInt32(fill.TradeReduced.Units); } if (fill.TradesClosed != null && fill.TradesClosed.Count > 0) { marketOrderFillQuantity += fill.TradesClosed.Sum(trade => Convert.ToInt32(trade.Units)); } } if (order.Type == OrderType.Market && order.Status != OrderStatus.Filled) { order.Status = OrderStatus.Filled; // if market order, also send Filled order event OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee, "Oanda Fill Event") { Status = OrderStatus.Filled, FillPrice = marketOrderFillPrice, FillQuantity = marketOrderFillQuantity }); } return(true); }
/// <summary> /// Places a new order and assigns a new broker ID to the order /// </summary> /// <param name="order">The order to be placed</param> /// <returns>True if the request for a new order has been placed, false otherwise</returns> public override bool PlaceOrder(Order order) { var orderFee = OrderFee.Zero; var marketOrderFillQuantity = 0; var marketOrderFillPrice = 0m; var marketOrderRemainingQuantity = 0; var marketOrderStatus = OrderStatus.Filled; var request = GenerateOrderRequest(order); order.PriceCurrency = SecurityProvider.GetSecurity(order.Symbol).SymbolProperties.QuoteCurrency; lock (Locker) { var response = _apiRest.CreateOrder(Authorization, AccountId, request); order.BrokerId.Add(response.Data.OrderCreateTransaction.Id); // Market orders are special, due to the callback not being triggered always, // if the order was Filled/PartiallyFilled, find fill quantity and price and inform the user if (order.Type == OrderType.Market) { var fill = response.Data.OrderFillTransaction; marketOrderFillPrice = fill.Price.ConvertInvariant <decimal>(); if (fill.TradeOpened != null && fill.TradeOpened.TradeID.Length > 0) { marketOrderFillQuantity = fill.TradeOpened.Units.ConvertInvariant <int>(); } if (fill.TradeReduced != null && fill.TradeReduced.TradeID.Length > 0) { marketOrderFillQuantity = fill.TradeReduced.Units.ConvertInvariant <int>(); } if (fill.TradesClosed != null && fill.TradesClosed.Count > 0) { marketOrderFillQuantity += fill.TradesClosed.Sum(trade => trade.Units.ConvertInvariant <int>()); } marketOrderRemainingQuantity = Convert.ToInt32(order.AbsoluteQuantity - Math.Abs(marketOrderFillQuantity)); if (marketOrderRemainingQuantity > 0) { marketOrderStatus = OrderStatus.PartiallyFilled; // The order was not fully filled lets save it so the callback can inform the user PendingFilledMarketOrders[order.Id] = marketOrderStatus; } } } OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee) { Status = OrderStatus.Submitted }); // If 'marketOrderRemainingQuantity < order.AbsoluteQuantity' is false it means the order was not even PartiallyFilled, wait for callback if (order.Type == OrderType.Market && marketOrderRemainingQuantity < order.AbsoluteQuantity) { OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee, "Oanda Fill Event") { Status = marketOrderStatus, FillPrice = marketOrderFillPrice, FillQuantity = marketOrderFillQuantity }); } return(true); }