예제 #1
0
        /// <summary>
        /// Cancels the order with the specified ID
        /// </summary>
        /// <param name="order">The order to cancel</param>
        /// <returns>True if the request was made for the order to be canceled, false otherwise</returns>
        public override bool CancelOrder(Order order)
        {
            Log.Trace("OandaBrokerage.CancelOrder(): " + order);

            if (!order.BrokerId.Any())
            {
                Log.Trace("OandaBrokerage.CancelOrder(): Unable to cancel order without BrokerId.");
                return(false);
            }

            foreach (var orderId in order.BrokerId)
            {
                CancelOrder(long.Parse(orderId));
                OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, 0, "Oanda Cancel Order Event")
                {
                    Status = OrderStatus.Canceled
                });
            }

            return(true);
        }
예제 #2
0
        /// <summary>
        /// Updates the order with the same id
        /// </summary>
        /// <param name="order">The new order information</param>
        /// <returns>True if the request was made for the order to be updated, false otherwise</returns>
        public override bool UpdateOrder(Order order)
        {
            Log.Trace("OandaBrokerage.UpdateOrder(): " + order);

            if (!order.BrokerId.Any())
            {
                // we need the brokerage order id in order to perform an update
                Log.Trace("OandaBrokerage.UpdateOrder(): Unable to update order without BrokerId.");
                return(false);
            }

            var requestParams = new Dictionary <string, string>
            {
                { "instrument", _symbolMapper.GetBrokerageSymbol(order.Symbol) },
                { "units", Convert.ToInt32(order.AbsoluteQuantity).ToString() },
            };

            // we need the brokerage order id in order to perform an update
            PopulateOrderRequestParameters(order, requestParams);

            UpdateOrder(long.Parse(order.BrokerId.First()), requestParams);

            return(true);
        }
예제 #3
0
        /// <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 requestParams = new Dictionary <string, string>
            {
                { "instrument", _symbolMapper.GetBrokerageSymbol(order.Symbol) },
                { "units", Convert.ToInt32(order.AbsoluteQuantity).ToString() }
            };

            PopulateOrderRequestParameters(order, requestParams);

            var postOrderResponse = PostOrderAsync(requestParams);

            if (postOrderResponse == null)
            {
                return(false);
            }

            // if market order, find fill quantity and price
            var marketOrderFillPrice = 0m;

            if (order.Type == OrderType.Market)
            {
                marketOrderFillPrice = Convert.ToDecimal(postOrderResponse.price);
            }

            var marketOrderFillQuantity = 0;

            if (postOrderResponse.tradeOpened != null && postOrderResponse.tradeOpened.id > 0)
            {
                if (order.Type == OrderType.Market)
                {
                    marketOrderFillQuantity = postOrderResponse.tradeOpened.units;
                }
                else
                {
                    order.BrokerId.Add(postOrderResponse.tradeOpened.id.ToString());
                }
            }

            if (postOrderResponse.tradeReduced != null && postOrderResponse.tradeReduced.id > 0)
            {
                if (order.Type == OrderType.Market)
                {
                    marketOrderFillQuantity = postOrderResponse.tradeReduced.units;
                }
                else
                {
                    order.BrokerId.Add(postOrderResponse.tradeReduced.id.ToString());
                }
            }

            if (postOrderResponse.orderOpened != null && postOrderResponse.orderOpened.id > 0)
            {
                if (order.Type != OrderType.Market)
                {
                    order.BrokerId.Add(postOrderResponse.orderOpened.id.ToString());
                }
            }

            if (postOrderResponse.tradesClosed != null && postOrderResponse.tradesClosed.Count > 0)
            {
                marketOrderFillQuantity += postOrderResponse.tradesClosed
                                           .Where(trade => order.Type == OrderType.Market)
                                           .Sum(trade => trade.units);
            }

            // send Submitted order event
            const int orderFee = 0;

            order.PriceCurrency = _securityProvider.GetSecurity(order.Symbol).SymbolProperties.QuoteCurrency;
            OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee)
            {
                Status = OrderStatus.Submitted
            });

            if (order.Type == OrderType.Market)
            {
                // if market order, also send Filled order event
                OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee)
                {
                    Status       = OrderStatus.Filled,
                    FillPrice    = marketOrderFillPrice,
                    FillQuantity = marketOrderFillQuantity * Math.Sign(order.Quantity)
                });
            }

            return(true);
        }
예제 #4
0
        private static void PopulateOrderRequestParameters(Order order, Dictionary <string, string> requestParams)
        {
            if (order.Direction != OrderDirection.Buy && order.Direction != OrderDirection.Sell)
            {
                throw new Exception("Invalid Order Direction");
            }

            requestParams.Add("side", order.Direction == OrderDirection.Buy ? "buy" : "sell");

            if (order.Type == OrderType.Market)
            {
                requestParams.Add("type", "market");
            }

            if (order.Type == OrderType.Limit)
            {
                requestParams.Add("type", "limit");
                requestParams.Add("price", ((LimitOrder)order).LimitPrice.ToString(CultureInfo.InvariantCulture));
                switch (order.Direction)
                {
                case OrderDirection.Buy:
                    //Limit Order Does not like Lower Bound Values == Limit Price value
                    //Don't set bounds when placing limit orders.
                    //Orders can be submitted with lower and upper bounds. If the market price on execution falls outside these bounds, it is considered a "Bounds Violation" and the order is cancelled.
                    break;

                case OrderDirection.Sell:
                    //Limit Order Does not like Lower Bound Values == Limit Price value
                    //Don't set bounds when placing limit orders.
                    //Orders can be submitted with lower and upper bounds. If the market price on execution falls outside these bounds, it is considered a "Bounds Violation" and the order is cancelled.
                    break;
                }

                //3 months is the max expiry for Oanda, and OrderDuration.GTC is only currently available
                requestParams.Add("expiry", XmlConvert.ToString(DateTime.Now.AddMonths(3), XmlDateTimeSerializationMode.Utc));
            }

            //this type should contain a stop and a limit to that stop.
            if (order.Type == OrderType.StopLimit)
            {
                requestParams.Add("type", "stop");
                requestParams.Add("price", ((StopLimitOrder)order).StopPrice.ToString(CultureInfo.InvariantCulture));
                switch (order.Direction)
                {
                case OrderDirection.Buy:
                    requestParams.Add("upperBound", ((StopLimitOrder)order).LimitPrice.ToString(CultureInfo.InvariantCulture));
                    break;

                case OrderDirection.Sell:
                    requestParams.Add("lowerBound", ((StopLimitOrder)order).LimitPrice.ToString(CultureInfo.InvariantCulture));
                    break;
                }

                //3 months is the max expiry for Oanda, and OrderDuration.GTC is only currently available
                requestParams.Add("expiry", XmlConvert.ToString(DateTime.Now.AddMonths(3), XmlDateTimeSerializationMode.Utc));
            }

            if (order.Type == OrderType.StopMarket)
            {
                requestParams.Add("type", "marketIfTouched");
                requestParams.Add("price", ((StopMarketOrder)order).StopPrice.ToString(CultureInfo.InvariantCulture));

                //3 months is the max expiry for Oanda, and OrderDuration.GTC is only currently available
                requestParams.Add("expiry", XmlConvert.ToString(DateTime.Now.AddMonths(3), XmlDateTimeSerializationMode.Utc));
            }
        }