Esempio n. 1
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 request = GenerateOrderRequest(order);

            var orderId  = order.BrokerId.First();
            var response = _apiRest.ReplaceOrder(Authorization, AccountId, orderId, request);

            // replace the brokerage order id
            order.BrokerId[0] = response.Data.OrderCreateTransaction.Id;

            // check if the updated (marketable) order was filled
            if (response.Data.OrderFillTransaction != null)
            {
                OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, OrderFee.Zero, "Oanda Fill Event")
                {
                    Status       = OrderStatus.Filled,
                    FillPrice    = response.Data.OrderFillTransaction.Price.ToDecimal(),
                    FillQuantity = response.Data.OrderFillTransaction.Units.ConvertInvariant <int>()
                });
            }

            return(true);
        }
Esempio n. 2
0
        /// <summary>
        /// Get the slippage approximation for this order
        /// </summary>
        /// <returns>Decimal value of the slippage approximation</returns>
        /// <seealso cref="Order"/>
        public override decimal GetSlippageApproximation(Security security, Order order)
        {
            //Return 0 by default
            decimal slippage = 0;
            //For FOREX, the slippage is the Bid/Ask Spread for Tick, and an approximation for TradeBars
            switch (security.Resolution)
            {
                case Resolution.Minute:
                case Resolution.Second:
                    //Get the last data packet:
                    //Assume slippage is 1/10,000th of the price
                    slippage = security.GetLastData().Value * 0.0001m;
                    break;

                case Resolution.Tick:
                    var lastTick = (Tick)security.GetLastData();
                    switch (order.Direction)
                    {
                        case OrderDirection.Buy:
                            //We're buying, assume slip to Asking Price.
                            slippage = Math.Abs(order.Price - lastTick.AskPrice);
                            break;

                        case OrderDirection.Sell:
                            //We're selling, assume slip to the bid price.
                            slippage = Math.Abs(order.Price - lastTick.BidPrice);
                            break;
                    }
                    break;
            }
            return slippage;
        }
Esempio n. 3
0
        /// <summary>
        /// Returns true if the brokerage could accept this order. This takes into account
        /// order type, security type, and order size limits.
        /// </summary>
        /// <remarks>
        /// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
        /// </remarks>
        /// <param name="security"></param>
        /// <param name="order">The order to be processed</param>
        /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be submitted</param>
        /// <returns>True if the brokerage could process the order, false otherwise</returns>
        public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
        {
            message = null;

            // validate security type
            if (security.Type != SecurityType.Forex && security.Type != SecurityType.Cfd)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
                    "This model does not support " + security.Type + " security type."
                    );

                return false;
            }

            // validate order type
            if (order.Type != OrderType.Limit && order.Type != OrderType.Market && order.Type != OrderType.StopMarket)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
                    "This model does not support " + order.Type + " order type."
                    );

                return false;
            }

            return true;
        }
Esempio n. 4
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)
        {
            //! UPDATE ORDER
            //todo: maybe make it so, that this broker doesn't support updating orders (because it doesnt)
            bool success = false;

            if (CancelOrder(order))
            {
                order.BrokerId.Clear();

                if (PlaceOrder(order))
                {
                    return(true);
                }
                else
                {
                    // try again
                    if (PlaceOrder(order))
                    {
                        return(true);
                    }
                    else
                    {
                        throw new KrakenException("The update failed! Order was canceled but not placed again");
                    }
                }
            }

            return(false);
        }
Esempio n. 5
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)
        {
            KrakenOrder krakenOrder = new KrakenOrder();

            krakenOrder.Pair = SymbolMapper.GetBrokerageSymbol(order.Symbol);

            // buy/sell
            krakenOrder.Type      = TranslateDirectionToKraken(order.Direction);
            krakenOrder.OrderType = TranslateOrderTypeToKraken(order.Type);
            krakenOrder.Volume    = order.AbsoluteQuantity;

            if (order.Type == OrderType.Limit)
            {
                krakenOrder.Price = order.Price;
            }

            // krakenOrder.Leverage = ?

            var result = _restApi.AddOrder(krakenOrder);

            if (result.Txid != null & result.Txid.Length != 0)
            {
                order.BrokerId.AddRange(result.Txid);

                return(true);
            }

            return(false);
        }
        public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice)
        {
            // FXCM Buy Limit orders will be rejected if the limit price is above the market price
            // FXCM Sell Limit orders will be rejected if the limit price is below the market price

            var limit = (LimitOrder)order;
            var previousLimit = limit.LimitPrice;

            var fxcmBrokerage = (FxcmBrokerage)brokerage;
            var quotes = fxcmBrokerage.GetBidAndAsk(new List<string> { new FxcmSymbolMapper().GetBrokerageSymbol(order.Symbol) });

            if (order.Quantity > 0)
            {
                // for limit buys we need to increase the limit price
                // buy limit price must be at bid price or below
                var bidPrice = Convert.ToDecimal(quotes.Single().BidPrice);
                Log.Trace("FxcmLimitOrderTestParameters.ModifyOrderToFill(): Bid: " + bidPrice);
                limit.LimitPrice = Math.Max(previousLimit, Math.Min(bidPrice, limit.LimitPrice * 2));
            }
            else
            {
                // for limit sells we need to decrease the limit price
                // sell limit price must be at ask price or above
                var askPrice = Convert.ToDecimal(quotes.Single().AskPrice);
                Log.Trace("FxcmLimitOrderTestParameters.ModifyOrderToFill(): Ask: " + askPrice);
                limit.LimitPrice = Math.Min(previousLimit, Math.Max(askPrice, limit.LimitPrice / 2));
            }

            return limit.LimitPrice != previousLimit;
        }
Esempio n. 7
0
        /// <summary>
        /// Returns true if the brokerage could accept this order. This takes into account
        /// order type, security type, and order size limits.
        /// </summary>
        /// <remarks>
        /// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
        /// </remarks>
        /// <param name="security">The security of the order</param>
        /// <param name="order">The order to be processed</param>
        /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be submitted</param>
        /// <returns>True if the brokerage could process the order, false otherwise</returns>
        public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
        {
            message = null;

            var securityType = order.SecurityType;
            if (securityType != SecurityType.Equity)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
                    "This model only supports equities."
                    );
                
                return false;
            }

            if (order.Type == OrderType.MarketOnOpen || order.Type == OrderType.MarketOnClose)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
                    "Tradier brokerage only supports Market orders. MarketOnOpen and MarketOnClose orders not supported."
                    );

                return false;
            }

            if (!CanExecuteOrder(security, order))
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "ExtendedMarket",
                    "Tradier does not support extended market hours trading.  Your order will be processed at market open."
                    );
            }

            // tradier order limits
            return true;
        }
        public void ClientCancelsLimitOrder()
        {
            OrderStatus status = OrderStatus.New;
            var manualResetEvent = new ManualResetEvent(false);

            var ib = new InteractiveBrokersBrokerage();
            ib.Connect();

            ib.OrderEvent += (sender, args) =>
            {
                status = args.Status;
                manualResetEvent.Set();
            };

            // try to sell a single share at a ridiculous price, we'll cancel this later
            var order = new Order("AAPL", SecurityType.Equity, -1, OrderType.Limit, DateTime.UtcNow, 100000);
            ib.PlaceOrder(order);
            manualResetEvent.WaitOne(2500);

            ib.CancelOrder(order);

            manualResetEvent.Reset();
            manualResetEvent.WaitOne(2500);

            Assert.AreEqual(OrderStatus.Canceled, status);
        }
        /********************************************************
        * CLASS PROPERTIES
        *********************************************************/
        /********************************************************
        * CLASS METHODS
        *********************************************************/
        /// <summary>
        /// Process a order fill with the supplied security and order.
        /// </summary>
        /// <param name="vehicle">Asset we're working with</param>
        /// <param name="order">Order class to check if filled.</param>
        /// <returns>OrderEvent packet with the full or partial fill information</returns>
        public virtual OrderEvent Fill(Security vehicle, Order order)
        {
            var fill = new OrderEvent(order);

            try
            {
                //Based on the order type, select the fill model method.
                switch (order.Type)
                {
                    case OrderType.Limit:
                        fill = LimitFill(vehicle, order);
                        break;
                    case OrderType.StopMarket:
                        fill = StopFill(vehicle, order);
                        break;
                    case OrderType.Market:
                        fill = MarketFill(vehicle, order);
                        break;
                }
            }
            catch (Exception err)
            {
                Log.Error("Equity.EquityTransactionModel.Fill(): " + err.Message);
            }
            return fill;
        }
Esempio n. 10
0
        public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice)
        {
            var stop = (StopLimitOrder) order;
            var previousStop = stop.StopPrice;
            if (order.Quantity > 0)
            {
                // for stop buys we need to decrease the stop price
                stop.StopPrice = Math.Min(stop.StopPrice, Math.Max(stop.StopPrice/2, Math.Round(lastMarketPrice, 2, MidpointRounding.AwayFromZero)));
                
                //change behaviour for forex type unit tests
                if(order.SecurityType == SecurityType.Forex)
                {
                    stop.StopPrice = Math.Min(stop.StopPrice, Math.Max(stop.StopPrice / 2, Math.Round(lastMarketPrice, 4, MidpointRounding.AwayFromZero)));
                }
            }
            else
            {
                // for stop sells we need to increase the stop price
                stop.StopPrice = Math.Max(stop.StopPrice, Math.Min(stop.StopPrice * 2, Math.Round(lastMarketPrice, 2, MidpointRounding.AwayFromZero)));


                //change behaviour for forex type unit tests
                if (order.SecurityType == SecurityType.Forex)
                {
                    stop.StopPrice = Math.Max(stop.StopPrice, Math.Min(stop.StopPrice * 2, Math.Round(lastMarketPrice, 4, MidpointRounding.AwayFromZero)));
                }
            }
            stop.LimitPrice = stop.StopPrice;
            return stop.StopPrice != previousStop;
        }
Esempio n. 11
0
        /********************************************************
        * CLASS PROPERTIES
        *********************************************************/
        /********************************************************
        * CLASS METHODS
        *********************************************************/
        /// <summary>
        /// Perform neccessary check to see if the model has been filled, appoximate the best we can.
        /// </summary>
        /// <param name="vehicle">Asset we're working with</param>
        /// <param name="order">Order class to check if filled.</param>
        /// <returns>OrderEvent packet with the full or partial fill information</returns>
        /// <seealso cref="OrderEvent"/>
        /// <seealso cref="Order"/>
        public virtual OrderEvent Fill(Security vehicle, Order order)
        {
            var fill = new OrderEvent(order);

            try
            {
                switch (order.Type)
                {
                    case OrderType.Limit:
                        fill = LimitFill(vehicle, order);
                        break;
                    case OrderType.StopMarket:
                        fill = StopFill(vehicle, order);
                        break;
                    case OrderType.Market:
                        fill = MarketFill(vehicle, order);
                        break;
                }
            }
            catch (Exception err)
            {
                Log.Error("Forex.ForexTransactionModel.Fill(): " + err.Message);
            }
            return fill;
        }
Esempio n. 12
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(QuantConnect.Orders.Order order)
        {
            try
            {
                Log.Trace("TEBBrokerage.CancelOrder(): Symbol: " + order.Symbol.Value + " Quantity: " + order.Quantity);

                if (!IsConnected)
                {
                    Log.Error("TEBBrokerage.CancelOrder(): Unable to place order while not connected.");
                    throw new InvalidOperationException("TEBBrokerage.CancelOrder(): Unable to place order while not connected.");
                }

                // this could be better
                foreach (var id in order.BrokerId)
                {
                    TEBCancelOrder(order, int.Parse(id));
                }

                // canceled order events fired upon confirmation, see HandleError
            }
            catch (Exception err)
            {
                Log.Error("TEBBrokerage.CancelOrder(): OrderID: " + order.Id + " - " + err);
                return(false);
            }
            return(true);
        }
Esempio n. 13
0
        /// <summary>
        /// Cancels the order with the specified ID
        /// </summary>
        /// <param name="order">The order to cancel</param>
        /// <returns>True if the request was submitted for cancellation, false otherwise</returns>
        public override bool CancelOrder(Order order)
        {
            Log.Trace("BitfinexBrokerage.CancelOrder(): {0}", order);

            if (!order.BrokerId.Any())
            {
                // we need the brokerage order id in order to perform a cancellation
                Log.Trace("BitfinexBrokerage.CancelOrder(): Unable to cancel order without BrokerId.");
                return(false);
            }

            var parameters = new JsonObject
            {
                { "id", order.BrokerId.Select(Parse.Long).First() }
            };

            var obj = new JsonArray {
                0, "oc", null, parameters
            };
            var json = JsonConvert.SerializeObject(obj);

            WebSocket.Send(json);

            return(true);
        }
Esempio n. 14
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)
        {
            if (order.BrokerId.Count == 0)
            {
                throw new ArgumentNullException(nameof(order.BrokerId), "BitfinexBrokerage.UpdateOrder: There is no brokerage id to be updated for this order.");
            }

            if (order.BrokerId.Count > 1)
            {
                throw new NotSupportedException("BitfinexBrokerage.UpdateOrder: Multiple orders update not supported. Please cancel and re-create.");
            }

            var parameters = new JsonObject
            {
                { "id", Parse.Long(order.BrokerId.First()) },
                { "amount", order.Quantity.ToStringInvariant() },
                { "price", GetOrderPrice(order).ToStringInvariant() }
            };

            var obj = new JsonArray {
                0, "ou", null, parameters
            };
            var json = JsonConvert.SerializeObject(obj);

            WebSocket.Send(json);

            return(true);
        }
        public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice)
        {
            // FXCM Buy StopMarket orders will be rejected if the stop price is below the market price
            // FXCM Sell StopMarket orders will be rejected if the stop price is above the market price

            var stop = (StopMarketOrder)order;
            var previousStop = stop.StopPrice;

            var fxcmBrokerage = (FxcmBrokerage)brokerage;
            var quotes = fxcmBrokerage.GetBidAndAsk(new List<string> { new FxcmSymbolMapper().GetBrokerageSymbol(order.Symbol) });
            
            if (order.Quantity > 0)
            {
                // for stop buys we need to decrease the stop price
                // buy stop price must be strictly above ask price
                var askPrice = Convert.ToDecimal(quotes.Single().AskPrice);
                Log.Trace("FxcmStopMarketOrderTestParameters.ModifyOrderToFill(): Ask: " + askPrice);
                stop.StopPrice = Math.Min(previousStop, Math.Max(askPrice, stop.StopPrice / 2) + 0.00001m);
            }
            else
            {
                // for stop sells we need to increase the stop price
                // sell stop price must be strictly below bid price
                var bidPrice = Convert.ToDecimal(quotes.Single().BidPrice);
                Log.Trace("FxcmStopMarketOrderTestParameters.ModifyOrderToFill(): Bid: " + bidPrice);
                stop.StopPrice = Math.Max(previousStop, Math.Min(bidPrice, stop.StopPrice * 2) - 0.00001m);
            }

            return stop.StopPrice != previousStop;
        }
Esempio n. 16
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", order.AbsoluteQuantity.ConvertInvariant <int>().ToStringInvariant() },
            };

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

            if (UpdateOrder(Parse.Long(order.BrokerId.First()), requestParams))
            {
                OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, OrderFee.Zero)
                {
                    Status = OrderStatus.UpdateSubmitted
                });
            }

            return(true);
        }
Esempio n. 17
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)
        {
            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);
        }
Esempio n. 18
0
        /// <summary>
        /// Generates an Oanda order request
        /// </summary>
        /// <param name="order">The LEAN order</param>
        /// <returns>The request in JSON format</returns>
        private string GenerateOrderRequest(Order order)
        {
            var instrument = SymbolMapper.GetBrokerageSymbol(order.Symbol);

            string request;

            switch (order.Type)
            {
            case OrderType.Market:
                var marketOrderRequest = new MarketOrderRequest
                {
                    Type       = MarketOrderRequest.TypeEnum.MARKET,
                    Instrument = instrument,
                    Units      = order.Quantity.ToStringInvariant()
                };
                request = JsonConvert.SerializeObject(new { order = marketOrderRequest });
                break;

            case OrderType.Limit:
                var limitOrderRequest = new LimitOrderRequest
                {
                    Type       = LimitOrderRequest.TypeEnum.LIMIT,
                    Instrument = instrument,
                    Units      = order.Quantity.ToStringInvariant(),
                    Price      = ((LimitOrder)order).LimitPrice.ToString(CultureInfo.InvariantCulture)
                };
                request = JsonConvert.SerializeObject(new { order = limitOrderRequest });
                break;

            case OrderType.StopMarket:
                var marketIfTouchedOrderRequest = new MarketIfTouchedOrderRequest
                {
                    Type       = MarketIfTouchedOrderRequest.TypeEnum.MARKETIFTOUCHED,
                    Instrument = instrument,
                    Units      = order.Quantity.ToStringInvariant(),
                    Price      = ((StopMarketOrder)order).StopPrice.ToString(CultureInfo.InvariantCulture)
                };
                request = JsonConvert.SerializeObject(new { order = marketIfTouchedOrderRequest });
                break;

            case OrderType.StopLimit:
                var stopOrderRequest = new StopOrderRequest
                {
                    Type       = StopOrderRequest.TypeEnum.STOP,
                    Instrument = instrument,
                    Units      = order.Quantity.ToStringInvariant(),
                    Price      = ((StopLimitOrder)order).StopPrice.ToString(CultureInfo.InvariantCulture),
                    PriceBound = ((StopLimitOrder)order).LimitPrice.ToString(CultureInfo.InvariantCulture)
                };
                request = JsonConvert.SerializeObject(new { order = stopOrderRequest });
                break;

            default:
                throw new NotSupportedException("The order type " + order.Type + " is not supported.");
            }

            return(request);
        }
Esempio n. 19
0
 /// <summary>
 /// Gets the total margin required to execute the specified order in units of the account currency including fees
 /// </summary>
 /// <param name="security">The security to compute initial margin for</param>
 /// <param name="order">The order to be executed</param>
 /// <returns>The total margin in terms of the currency quoted in the order</returns>
 public override decimal GetInitialMarginRequiredForOrder(Security security, Order order)
 {
     //Get the order value from the non-abstract order classes (MarketOrder, LimitOrder, StopMarketOrder)
     //Market order is approximated from the current security price and set in the MarketOrder Method in QCAlgorithm.
     var orderFees = security.FeeModel.GetOrderFee(security, order);
     
     var orderCostInAccountCurrency = order.GetValue(security);
     return orderCostInAccountCurrency*InitialMarginRequirement + orderFees;
 }
Esempio n. 20
0
 /// <summary>
 /// Returns true if the brokerage would be able to execute this order at this time assuming
 /// market prices are sufficient for the fill to take place. This is used to emulate the 
 /// brokerage fills in backtesting and paper trading. For example some brokerages may not perform
 /// executions during extended market hours. This is not intended to be checking whether or not
 /// the exchange is open, that is handled in the Security.Exchange property.
 /// </summary>
 /// <param name="security">The security being ordered</param>
 /// <param name="order">The order to test for execution</param>
 /// <returns>True if the brokerage would be able to perform the execution, false otherwise</returns>
 public bool CanExecuteOrder(Security security, Order order)
 {
     // tradier doesn't support after hours trading
     var timeOfDay = security.Time.TimeOfDay;
     if (timeOfDay < EquityExchange.MarketOpen || timeOfDay > EquityExchange.MarketClose)
     {
         return false;
     }
     return true;
 }
Esempio n. 21
0
        /// <summary>
        /// Returns true if the brokerage could accept this order. This takes into account
        /// order type, security type, and order size limits.
        /// </summary>
        /// <remarks>
        /// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
        /// </remarks>
        /// <param name="security"></param>
        /// <param name="order">The order to be processed</param>
        /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be submitted</param>
        /// <returns>True if the brokerage could process the order, false otherwise</returns>
        public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
        {
            message = null;

            // validate security type
            if (security.Type != SecurityType.Forex && security.Type != SecurityType.Cfd)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
                    "This model does not support " + security.Type + " security type."
                    );

                return false;
            }

            // validate order type
            if (order.Type != OrderType.Limit && order.Type != OrderType.Market && order.Type != OrderType.StopMarket)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
                    "This model does not support " + order.Type + " order type."
                    );

                return false;
            }

            // validate order quantity
            if (order.Quantity % 1000 != 0)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
                    "The order quantity must be a multiple of 1000."
                    );

                return false;
            }

            // validate stop/limit orders= prices
            var limit = order as LimitOrder;
            if (limit != null)
            {
                return IsValidOrderPrices(security, OrderType.Limit, limit.Direction, security.Price, limit.LimitPrice, ref message);
            }

            var stopMarket = order as StopMarketOrder;
            if (stopMarket != null)
            {
                return IsValidOrderPrices(security, OrderType.StopMarket, stopMarket.Direction, stopMarket.StopPrice, security.Price, ref message);
            }

            var stopLimit = order as StopLimitOrder;
            if (stopLimit != null)
            {
                return IsValidOrderPrices(security, OrderType.StopLimit, stopLimit.Direction, stopLimit.StopPrice, stopLimit.LimitPrice, ref message);
            }

            return true;
        }
        /// <summary>
        /// Returns true if the brokerage would allow updating the order as specified by the request
        /// </summary>
        /// <param name="security">The security of the order</param>
        /// <param name="order">The order to be updated</param>
        /// <param name="request">The requested update to be made to the order</param>
        /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be updated</param>
        /// <returns>True if the brokerage would allow updating the order, false otherwise</returns>
        public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
        {
            message = null;

            if (order.SecurityType == SecurityType.Forex && request.Quantity != null)
            {
                return IsForexWithinOrderSizeLimits(order.Symbol.Value, request.Quantity.Value, out message);
            }

            return true;
        }
Esempio n. 23
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)
        {
            int sum = 0;

            foreach (string txid in order.BrokerId)
            {
                var result = _restApi.CancelOrder(txid);
                sum += result.Count;
            }

            return(sum > 0);
        }
Esempio n. 24
0
        /// <summary>
        /// Gets the total margin required to execute the specified order in units of the account currency including fees
        /// </summary>
        /// <param name="security">The security to compute initial margin for</param>
        /// <param name="order">The order to be executed</param>
        /// <returns>The total margin in terms of the currency quoted in the order</returns>
        public override decimal GetInitialMarginRequiredForOrder(Security security, Order order)
        {
            var forex = (Forex)security;

            //Get the order value from the non-abstract order classes (MarketOrder, LimitOrder, StopMarketOrder)
            //Market order is approximated from the current security price and set in the MarketOrder Method in QCAlgorithm.
            var orderFees = security.TransactionModel.GetOrderFee(security, order);

            var price = order.Status.IsFill() ? order.Price : security.Price;
            var orderCostInAccountCurrency = order.GetValue(price)*forex.QuoteCurrency.ConversionRate;
            return orderCostInAccountCurrency*InitialMarginRequirement + orderFees;
        }
        /// <summary>
        /// Returns true if the brokerage could accept this order. This takes into account
        /// order type, security type, and order size limits.
        /// </summary>
        /// <remarks>
        /// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
        /// </remarks>
        /// <param name="security"></param>
        /// <param name="order">The order to be processed</param>
        /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be submitted</param>
        /// <returns>True if the brokerage could process the order, false otherwise</returns>
        public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
        {
            message = null;

            // validate security type
            if (security.Type != SecurityType.Forex && security.Type != SecurityType.Cfd)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
                    "This model does not support " + security.Type + " security type."
                    );

                return false;
            }

            // validate order type
            if (order.Type != OrderType.Limit && order.Type != OrderType.Market && order.Type != OrderType.StopMarket)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
                    "This model does not support " + order.Type + " order type."
                    );

                return false;
            }

            // validate order quantity
            if (order.Quantity % 1000 != 0)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
                    "The order quantity must be a multiple of 1000."
                    );

                return false;
            }

            // validate order price
            var invalidPrice = order.Type == OrderType.Limit && order.Direction == OrderDirection.Buy && ((LimitOrder)order).LimitPrice > security.Price ||
                               order.Type == OrderType.Limit && order.Direction == OrderDirection.Sell && ((LimitOrder)order).LimitPrice < security.Price ||
                               order.Type == OrderType.StopMarket && order.Direction == OrderDirection.Buy && ((StopMarketOrder)order).StopPrice < security.Price ||
                               order.Type == OrderType.StopMarket && order.Direction == OrderDirection.Sell && ((StopMarketOrder)order).StopPrice > security.Price;
            if (invalidPrice)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "NotSupported",
                    "Limit Buy orders and Stop Sell orders must be below market, Limit Sell orders and Stop Buy orders must be above market."
                    );
            }

            return true;
        }
 public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice)
 {
     var stop = (StopMarketOrder)order;
     var previousStop = stop.StopPrice;
     if (order.Quantity > 0)
     {
         // for stop buys we need to decrease the stop price
         stop.StopPrice = Math.Min(stop.StopPrice, Math.Max(stop.StopPrice / 2, lastMarketPrice));
     }
     else
     {
         // for stop sells we need to increase the stop price
         stop.StopPrice = Math.Max(stop.StopPrice, Math.Min(stop.StopPrice * 2, lastMarketPrice));
     }
     return stop.StopPrice != previousStop;
 }
Esempio n. 27
0
        /// <summary>
        /// Get the fee for this order
        /// </summary>
        /// <param name="security">The security matching the order</param>
        /// <param name="order">The order to compute fees for</param>
        /// <returns>The cost of the order in units of the account currency</returns>
        public override decimal GetOrderFee(Security security, Order order)
        {
            // From http://www.fxcm.com/forex/forex-pricing/ (on Oct 6th, 2015)
            // Forex: $0.04 per side per 1k lot for EURUSD, GBPUSD, USDJPY, USDCHF, AUDUSD, EURJPY, GBPJPY
            //        $0.06 per side per 1k lot for other instruments

            // From https://www.fxcm.com/uk/markets/cfds/frequently-asked-questions/
            // CFD: no commissions

            if (security.Type != SecurityType.Forex)
                return 0m;

            var commissionRate = _groupCommissionSchedule1.Contains(security.Symbol) ? 0.04m : 0.06m;

            return commissionRate * order.AbsoluteQuantity / 1000;
        }
Esempio n. 28
0
        /// <summary>
        /// Returns true if the brokerage would allow updating the order as specified by the request
        /// </summary>
        /// <param name="security">The security of the order</param>
        /// <param name="order">The order to be updated</param>
        /// <param name="request">The requested update to be made to the order</param>
        /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be updated</param>
        /// <returns>True if the brokerage would allow updating the order, false otherwise</returns>
        public override bool CanUpdateOrder(Security security, Order order, UpdateOrderRequest request, out BrokerageMessageEvent message)
        {
            message = null;

            // Tradier doesn't allow updating order quantities
            if (request.Quantity != null && request.Quantity != order.Quantity)
            {
                message = new BrokerageMessageEvent(BrokerageMessageType.Warning, "UpdateRejected",
                    "Traider does not support updating order quantities."
                    );

                return false;
            }

            return true;
        }
Esempio n. 29
0
        public override bool ModifyOrderToFill(IBrokerage brokerage, Order order, decimal lastMarketPrice)
        {
            // limit orders will process even if they go beyond the market price

            var limit = (LimitOrder) order;
            if (order.Quantity > 0)
            {
                // for limit buys we need to increase the limit price
                limit.LimitPrice *= 2;
            }
            else
            {
                // for limit sells we need to decrease the limit price
                limit.LimitPrice /= 2;
            }
            return true;
        }
Esempio n. 30
0
        /// <summary>
        /// Returns true if the brokerage would be able to execute this order at this time assuming
        /// market prices are sufficient for the fill to take place. This is used to emulate the 
        /// brokerage fills in backtesting and paper trading. For example some brokerages may not perform
        /// executions during extended market hours. This is not intended to be checking whether or not
        /// the exchange is open, that is handled in the Security.Exchange property.
        /// </summary>
        /// <param name="security">The security being ordered</param>
        /// <param name="order">The order to test for execution</param>
        /// <returns>True if the brokerage would be able to perform the execution, false otherwise</returns>
        public override bool CanExecuteOrder(Security security, Order order)
        {
            EquityExchange.SetLocalDateTimeFrontier(security.Exchange.LocalTime);

            var cache = security.GetLastData();
            if (cache == null)
            {
                return false;
            }

            // tradier doesn't support after hours trading
            if (!EquityExchange.IsOpenDuringBar(cache.Time, cache.EndTime, false))
            {
                return false;
            }
            return true;
        }
 public override bool ModifyOrderToFill(Order order, decimal lastMarketPrice)
 {
     var stop = (StopLimitOrder) order;
     var previousStop = stop.StopPrice;
     if (order.Quantity > 0)
     {
         // for stop buys we need to decrease the stop price
         stop.StopPrice = Math.Min(stop.StopPrice, Math.Max(stop.StopPrice/2, Math.Round(lastMarketPrice, 2, MidpointRounding.AwayFromZero)));
     }
     else
     {
         // for stop sells we need to increase the stop price
         stop.StopPrice = Math.Max(stop.StopPrice, Math.Min(stop.StopPrice * 2, Math.Round(lastMarketPrice, 2, MidpointRounding.AwayFromZero)));
     }
     stop.LimitPrice = stop.StopPrice;
     return stop.StopPrice != previousStop;
 }
Esempio n. 32
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 parameters = new JsonObject
            {
                { "symbol", _symbolMapper.GetBrokerageSymbol(order.Symbol) },
                { "amount", order.Quantity.ToStringInvariant() },
                { "type", ConvertOrderType(_algorithm.BrokerageModel.AccountType, order.Type) },
                { "price", GetOrderPrice(order).ToStringInvariant() }
            };

            var orderProperties = order.Properties as BitfinexOrderProperties;

            if (orderProperties != null)
            {
                if (order.Type == OrderType.Limit)
                {
                    var flags = 0;
                    if (orderProperties.Hidden)
                    {
                        flags |= OrderFlags.Hidden;
                    }
                    if (orderProperties.PostOnly)
                    {
                        flags |= OrderFlags.PostOnly;
                    }

                    parameters.Add("flags", flags);
                }
            }

            var clientOrderId = GetNextClientOrderId();

            parameters.Add("cid", clientOrderId);

            _orderMap.TryAdd(clientOrderId, order);

            var obj = new JsonArray {
                0, "on", null, parameters
            };
            var json = JsonConvert.SerializeObject(obj);

            WebSocket.Send(json);

            return(true);
        }
        /// <summary>
        /// Return a relevant price for order depending on order type
        /// Price must be positive
        /// </summary>
        /// <param name="order"></param>
        /// <returns></returns>
        private static decimal GetOrderPrice(Order order)
        {
            switch (order.Type)
            {
            case OrderType.Limit:
                return(((LimitOrder)order).LimitPrice);

            case OrderType.Market:
                // Order price must be positive for market order too;
                // refuses for price = 0
                return(1);

            case OrderType.StopMarket:
                return(((StopMarketOrder)order).StopPrice);
            }

            throw new NotSupportedException($"BitfinexBrokerage.ConvertOrderType: Unsupported order type: {order.Type}");
        }
Esempio n. 34
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(QuantConnect.Orders.Order order)
        {
            try
            {
                Log.Trace("TEBBrokerage.UpdateOrder(): Symbol: " + order.Symbol.Value + " Quantity: " + order.Quantity + " Status: " + order.Status);

                if (!IsConnected)
                {
                    Log.Error("TEBBrokerage.UpdateOrder(): Unable to place order while not connected.");
                    throw new InvalidOperationException("TEBBrokerage.UpdateOrder(): Unable to place order while not connected.");
                }


                int clOrdID = 0;
                //if (needsNewID)
                //{
                // the order ids are generated for us by the SecurityTransactionManaer
                int id = NextClientID();
                order.BrokerId.Add(id.ToString());
                clOrdID = id;
                //}
                //else if (order.BrokerId.Any())
                //{
                //    // this is *not* perfect code
                //    clOrdID = int.Parse(order.BrokerId[0]);
                //}
                //else
                //{
                //    throw new ArgumentException("Expected order with populated BrokerId for updating orders.");
                //}

                var  content = CreateContent(order, clOrdID);
                bool isSent  = false;
                _fixContext.SendNewOrderToCash(content, out isSent);
                return(isSent);
            }
            catch (Exception err)
            {
                Log.Error("TEBBrokerage.UpdateOrder(): " + err);
                return(false);
            }
        }
Esempio n. 35
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)
            {
                _apiRest.CancelOrder(Authorization, AccountId, orderId);
                OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, 0, "Oanda Cancel Order Event")
                {
                    Status = OrderStatus.Canceled
                });
            }

            return(true);
        }
Esempio n. 36
0
        public void PlaceOrderTest(string orderId, HttpStatusCode httpStatus, Orders.OrderStatus status, decimal quantity, decimal price, OrderType orderType)
        {
            var response = new
            {
                id        = _brokerId,
                fill_fees = "0.11"
            };

            SetupResponse(JsonConvert.SerializeObject(response), httpStatus);

            _unit.OrderStatusChanged += (s, e) =>
            {
                Assert.AreEqual(status, e.Status);
                if (orderId != null)
                {
                    Assert.AreEqual("BTCUSD", e.Symbol.Value);
                    Assert.That((quantity > 0 && e.Direction == Orders.OrderDirection.Buy) || (quantity < 0 && e.Direction == Orders.OrderDirection.Sell));
                    Assert.IsTrue(orderId == null || _unit.CachedOrderIDs.SelectMany(c => c.Value.BrokerId.Where(b => b == _brokerId)).Any());
                }
            };

            Order order = null;

            if (orderType == OrderType.Limit)
            {
                order = new Orders.LimitOrder(_symbol, quantity, price, DateTime.UtcNow);
            }
            else if (orderType == OrderType.Market)
            {
                order = new Orders.MarketOrder(_symbol, quantity, DateTime.UtcNow);
            }
            else
            {
                order = new Orders.StopMarketOrder(_symbol, quantity, price, DateTime.UtcNow);
            }

            bool actual = _unit.PlaceOrder(order);

            Assert.IsTrue(actual || (orderId == null && !actual));
        }
Esempio n. 37
0
        /// <summary>
        /// Uses the Interactive Brokers equities fixes fee schedule.
        /// </summary>
        /// <remarks>
        /// Default implementation uses the Interactive Brokers fee model of 0.5c per share with a maximum of 0.5% per order
        /// and minimum of $1.00.
        /// </remarks>
        /// <param name="security">The security matching the order</param>
        /// <param name="order">The order to compute fees for</param>
        /// <returns>The cost of the order in units of the account currency</returns>
        public override decimal GetOrderFee(Security security, Order order)
        {
            var tradeValue = Math.Abs(order.Value);

            //Per share fees
            var tradeFee = 0.005m*order.AbsoluteQuantity;

            //Maximum Per Order: 0.5%
            //Minimum per order. $1.0
            var maximumPerOrder = 0.005m*tradeValue;
            if (tradeFee < 1)
            {
                tradeFee = 1;
            }
            else if (tradeFee > maximumPerOrder)
            {
                tradeFee = maximumPerOrder;
            }

            //Always return a positive fee.
            return Math.Abs(tradeFee);
        }
        /// <summary>
        /// Returns true if the brokerage could accept this order. This takes into account
        /// order type, security type, and order size limits.
        /// </summary>
        /// <remarks>
        /// For example, a brokerage may have no connectivity at certain times, or an order rate/size limit
        /// </remarks>
        /// <param name="security">The security being ordered</param>
        /// <param name="order">The order to be processed</param>
        /// <param name="message">If this function returns false, a brokerage message detailing why the order may not be submitted</param>
        /// <returns>True if the brokerage could process the order, false otherwise</returns>
        public override bool CanSubmitOrder(Security security, Order order, out BrokerageMessageEvent message)
        {
            message = null;

            //https://www.interactivebrokers.com/en/?f=%2Fen%2Ftrading%2FforexOrderSize.php
            switch (order.SecurityType)
            {
                case SecurityType.Base:
                    return false;
                case SecurityType.Equity:
                    return true; // could not find order limits on equities
                case SecurityType.Option:
                    return true;
                case SecurityType.Commodity:
                    return true;
                case SecurityType.Forex:
                    return IsForexWithinOrderSizeLimits(order.Symbol.Value, order.Quantity, out message);
                case SecurityType.Future:
                    return true;
                default:
                    throw new ArgumentOutOfRangeException();
            }
        }
Esempio n. 39
0
        public QuantConnect.Orders.Order ConvertToOrder(Teb.FIX.Model.Order tebOrder)
        {
            QuantConnect.Orders.Order o = null;

            if (tebOrder.OrdType == CashDefinition.ORDTYPE_MARKET)
            {
                o = new QuantConnect.Orders.MarketOrder();
            }
            else
            {
                o = new QuantConnect.Orders.LimitOrder();
                (o as LimitOrder).LimitPrice = tebOrder.Price.HasValue ? tebOrder.Price.Value : 0;
            }

            o.Duration = ConvertToTimeInForce(tebOrder.Core.TimeInForce);;
            o.Id       = int.Parse(tebOrder.ClOrdID.Replace("CS", ""));
            o.Price    = tebOrder.Price.HasValue ? tebOrder.Price.Value : 0;
            o.Quantity = ConvertToQuantity(tebOrder);
            o.Status   = ConvertToStatus(tebOrder);
            o.Time     = tebOrder.TransactTime.HasValue ? tebOrder.TransactTime.Value : DateTime.Now;
            o.Symbol   = tebOrder.Symbol;
            o.BrokerId.Add(tebOrder.ConnectionClOrdID);
            return(o);
        }
Esempio n. 40
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);
        }
Esempio n. 41
0
        private Content CreateContent(QuantConnect.Orders.Order order, int clOrdId)
        {
            Content content = ContentFactory.Create();

            content.ServerStatus = ContentServerStatus.Waiting;
            content.ClientStatus = ContentClientStatus.PendingNew;
            content.TransactTime = DateTime.Now;
            content.ClOrdID      = clOrdId.ToString();
            content.MarketID     = clOrdId.ToString();
            content.Side         = convertHelper.ConvertToSide(order.Quantity);
            //content.IsSellShort = builder.IsSellShort;
            content.OrdType       = convertHelper.ConvertToOrdType(order.Type);
            content.Account       = _account;
            content.OrderCapacity = CashDefinition.ACCOUNT_TYPE_CUSTOMER;
            content.SenderSubID   = _senderSubId;
            content.Symbol        = order.Symbol;     //content.SymbolSfxMarket = builder.Market.Value.Trim();
            content.OrderQty      = Math.Abs(order.Quantity);

            if (order is LimitOrder)
            {
                decimal limitPrice = (decimal)((LimitOrder)order).LimitPrice;
                content.Price = limitPrice;
            }
            else
            {
                content.Price = order.Price;
            }

            content.TransactTime = order.Time;
            content.OrderQty     = Math.Abs(order.Quantity);
            content.TimeInForce  = convertHelper.ConvertToTimeInForce(order.Type);
            content.SecurityType = CashDefinition.SECURITY_CASH;


            return(content);
        }
Esempio n. 42
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,
                                            OrderFee.Zero,
                                            "Oanda Cancel Order Event")
                {
                    Status = OrderStatus.Canceled
                });
            }

            return(true);
        }
Esempio n. 43
0
        /// <summary>
        /// Gets all open orders on the account.
        /// NOTE: The order objects returned do not have QC order IDs.
        /// </summary>
        /// <returns>The open orders returned from IB</returns>
        public override List <Order> GetOpenOrders()
        {
            List <Order> list = new List <Order>();

            Dictionary <string, OrderInfo> orders = _restApi.GetOpenOrders();

            foreach (KeyValuePair <string, OrderInfo> pair in orders)
            {
                OrderInfo info = pair.Value;

                OrderDescription desc = info.Descr;

                // check for debug purposes here
                if (pair.Key != desc.Pair)
                {
                    throw new KrakenException("this doesn't match, please inspect!!");
                }

                var SOR = new SubmitOrderRequest(

                    TranslateOrderTypeToLean(info.Descr.OrderType),
                    SecurityType.Crypto,
                    this.SymbolMapper.GetLeanSymbol(desc.Pair, SecurityType.Crypto, Market.Kraken),
                    info.Volume - info.VolumeExecuted,
                    info.StopPrice.HasValue ? info.StopPrice.Value : 0m,
                    info.LimitPrice.HasValue ? info.LimitPrice.Value : 0m,
                    UnixTimeStampToDateTime(info.OpenTm),
                    ""
                    );

                var order = Order.CreateOrder(SOR);
                list.Add(order);
            }

            return(list);
        }
Esempio n. 44
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)
        {
            Log.Trace("FxcmBrokerage.PlaceOrder(): {0}", order);

            if (!IsConnected)
                throw new InvalidOperationException("FxcmBrokerage.PlaceOrder(): Unable to place order while not connected.");

            if (order.Direction != OrderDirection.Buy && order.Direction != OrderDirection.Sell)
                throw new ArgumentException("FxcmBrokerage.PlaceOrder(): Invalid Order Direction");

            var fxcmSymbol = _symbolMapper.GetBrokerageSymbol(order.Symbol);
            var orderSide = order.Direction == OrderDirection.Buy ? SideFactory.BUY : SideFactory.SELL;
            var quantity = (double)order.AbsoluteQuantity;

            OrderSingle orderRequest;
            switch (order.Type)
            {
                case OrderType.Market:
                    orderRequest = MessageGenerator.generateMarketOrder(_accountId, quantity, orderSide, fxcmSymbol, "");
                    break;

                case OrderType.Limit:
                    var limitPrice = (double)((LimitOrder)order).LimitPrice;
                    orderRequest = MessageGenerator.generateOpenOrder(limitPrice, _accountId, quantity, orderSide, fxcmSymbol, "");
                    orderRequest.setOrdType(OrdTypeFactory.LIMIT);
                    orderRequest.setTimeInForce(TimeInForceFactory.GOOD_TILL_CANCEL);
                    break;

                case OrderType.StopMarket:
                    var stopPrice = (double)((StopMarketOrder)order).StopPrice;
                    orderRequest = MessageGenerator.generateOpenOrder(stopPrice, _accountId, quantity, orderSide, fxcmSymbol, "");
                    orderRequest.setOrdType(OrdTypeFactory.STOP);
                    orderRequest.setTimeInForce(TimeInForceFactory.GOOD_TILL_CANCEL);
                    break;

                default:
                    throw new NotSupportedException("FxcmBrokerage.PlaceOrder(): Order type " + order.Type + " is not supported.");
            }

            _isOrderSubmitRejected = false;
            AutoResetEvent autoResetEvent;
            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(orderRequest);
                _mapRequestsToOrders[_currentRequest] = order;
                autoResetEvent = new AutoResetEvent(false);
                _mapRequestsToAutoResetEvents[_currentRequest] = autoResetEvent;
            }
            if (!autoResetEvent.WaitOne(ResponseTimeout))
                throw new TimeoutException(string.Format("FxcmBrokerage.PlaceOrder(): Operation took longer than {0} seconds.", (decimal)ResponseTimeout / 1000));

            return !_isOrderSubmitRejected;
        }
Esempio n. 45
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 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);
        }
Esempio n. 46
0
 /// <summary>
 /// Returns true when the specified order is in a completed state
 /// </summary>
 private static bool Completed(Order order)
 {
     return order.Status == OrderStatus.Filled || order.Status == OrderStatus.PartiallyFilled || order.Status == OrderStatus.Invalid || order.Status == OrderStatus.Canceled;
 }
Esempio n. 47
0
        /// <summary>
        /// Check if there is sufficient capital to execute this order.
        /// </summary>
        /// <param name="portfolio">Our portfolio</param>
        /// <param name="order">Order we're checking</param>
        /// <returns>True if suficient capital.</returns>
        public bool GetSufficientCapitalForOrder(SecurityPortfolioManager portfolio, Order order)
        {
            // short circuit the div 0 case
            if (order.Quantity == 0) return true;

            var security = _securities[order.Symbol];

            var ticket = GetOrderTicket(order.Id);
            if (ticket == null)
            {
                Log.Error("SecurityTransactionManager.GetSufficientCapitalForOrder(): Null order ticket for id: " + order.Id);
                return false;
            }

            var freeMargin = security.MarginModel.GetMarginRemaining(portfolio, security, order.Direction);
            var initialMarginRequiredForOrder = security.MarginModel.GetInitialMarginRequiredForOrder(security, order);

            // pro-rate the initial margin required for order based on how much has already been filled
            var percentUnfilled = (Math.Abs(order.Quantity) - Math.Abs(ticket.QuantityFilled))/Math.Abs(order.Quantity);
            var initialMarginRequiredForRemainderOfOrder = percentUnfilled*initialMarginRequiredForOrder;

            if (Math.Abs(initialMarginRequiredForRemainderOfOrder) > freeMargin)
            {
                Log.Error(string.Format("SecurityTransactionManager.GetSufficientCapitalForOrder(): Id: {0}, Initial Margin: {1}, Free Margin: {2}", order.Id, initialMarginRequiredForOrder, freeMargin));
                return false;
            }
            return true;
        }
 /// <summary>
 /// Returns true if the specified order can be updated
 /// </summary>
 /// <param name="order">The order to check if we can update</param>
 /// <returns>True if the order can be updated, false otherwise</returns>
 private bool CanUpdateOrder(Order order)
 {
     return order.Status != OrderStatus.Filled
         && order.Status != OrderStatus.Canceled
         && order.Status != OrderStatus.PartiallyFilled
         && order.Status != OrderStatus.Invalid;
 }
Esempio n. 49
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() }
            };

            var     orderFee = OrderFee.Zero;
            var     marketOrderFillQuantity      = 0;
            var     marketOrderRemainingQuantity = 0;
            decimal marketOrderFillPrice;
            var     marketOrderStatus = OrderStatus.Filled;

            order.PriceCurrency = SecurityProvider.GetSecurity(order.Symbol).SymbolProperties.QuoteCurrency;
            PopulateOrderRequestParameters(order, requestParams);

            lock (Locker)
            {
                var postOrderResponse = PostOrderAsync(requestParams);
                if (postOrderResponse == null)
                {
                    return(false);
                }
                // Market orders are special, due to the callback not being triggered always, if the order was filled,
                // find fill quantity and price and inform the user
                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);
                }

                marketOrderFillPrice         = Convert.ToDecimal(postOrderResponse.price);
                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)
                {
                    Status       = marketOrderStatus,
                    FillPrice    = marketOrderFillPrice,
                    FillQuantity = marketOrderFillQuantity * Math.Sign(order.Quantity)
                });
            }

            return(true);
        }
Esempio n. 50
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("FxcmBrokerage.CancelOrder(): {0}", order);

            if (!IsConnected)
                throw new InvalidOperationException("FxcmBrokerage.UpdateOrder(): Unable to cancel order while not connected.");

            if (!order.BrokerId.Any())
            {
                // we need the brokerage order id in order to perform a cancellation
                Log.Trace("FxcmBrokerage.CancelOrder(): Unable to cancel order without BrokerId.");
                return false;
            }

            var fxcmOrderId = order.BrokerId[0].ToString();

            ExecutionReport fxcmOrder;
            if (!_openOrders.TryGetValue(fxcmOrderId, out fxcmOrder))
                throw new ArgumentException("FxcmBrokerage.CancelOrder(): FXCM order id not found: " + fxcmOrderId);

            _isOrderUpdateOrCancelRejected = false;
            var orderCancelRequest = MessageGenerator.generateOrderCancelRequest("", fxcmOrder.getOrderID(), fxcmOrder.getSide(), fxcmOrder.getAccount());
            AutoResetEvent autoResetEvent;
            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(orderCancelRequest);
                autoResetEvent = new AutoResetEvent(false);
                _mapRequestsToAutoResetEvents[_currentRequest] = autoResetEvent;
            }
            if (!autoResetEvent.WaitOne(ResponseTimeout))
                throw new TimeoutException(string.Format("FxcmBrokerage.CancelOrder(): Operation took longer than {0} seconds.", (decimal)ResponseTimeout / 1000));

            return !_isOrderUpdateOrCancelRejected;
        }
Esempio n. 51
0
 /// <summary>
 /// Sets the pending order as a clone to prevent object reference nastiness
 /// </summary>
 /// <param name="order">The order to be added to the pending orders dictionary</param>
 /// <returns></returns>
 private void SetPendingOrder(Order order)
 {
     // only save off clones!
     _pending[order.Id] = order.Clone();
 }
        private static Order AssertOrderOpened(bool orderFilled, InteractiveBrokersBrokerage ib, Order order)
        {
            // if the order didn't fill check for it as an open order
            if (!orderFilled)
            {
                // find the right order and return it
                foreach (var openOrder in ib.GetOpenOrders())
                {
                    if (openOrder.BrokerId.Any(id => order.BrokerId.Any(x => x == id)))
                    {
                        return(openOrder);
                    }
                }
                Assert.Fail("The order was not filled and was unable to be located via GetOpenOrders()");
            }

            Assert.Pass("The order was successfully filled!");
            return(null);
        }
Esempio n. 53
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);
        }
Esempio n. 54
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", order.Symbol.Value },
                { "units", Convert.ToInt32(order.AbsoluteQuantity).ToString() }
            };

            PopulateOrderRequestParameters(order, requestParams);

            Log.Trace(order.ToString());


            var priorOrderPositions = GetTradeList(requestParams);

            var postOrderResponse = PostOrderAsync(requestParams);

            if (postOrderResponse != null)
            {
                if (postOrderResponse.tradeOpened != null)
                {
                    order.BrokerId.Add(postOrderResponse.tradeOpened.id);
                }

                if (postOrderResponse.tradeReduced != null)
                {
                    order.BrokerId.Add(postOrderResponse.tradeReduced.id);
                }

                if (postOrderResponse.orderOpened != null)
                {
                    order.BrokerId.Add(postOrderResponse.orderOpened.id);
                }

                const int orderFee = 0;
                OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee)
                {
                    Status = OrderStatus.Submitted
                });
            }
            else
            {
                return(false);
            }

            // we need to determine if there was an existing order and wheter we closed it with market orders.

            if (order.Type == OrderType.Market && order.Direction == OrderDirection.Buy)
            {
                //assume that we are opening a new buy market order
                if (postOrderResponse.tradeOpened != null && postOrderResponse.tradeOpened.id > 0)
                {
                    var tradeOpenedId = postOrderResponse.tradeOpened.id;
                    requestParams = new Dictionary <string, string>();
                    var tradeListResponse = GetTradeList(requestParams);
                    if (tradeListResponse.trades.Any(trade => trade.id == tradeOpenedId))
                    {
                        order.BrokerId.Add(tradeOpenedId);
                        const int orderFee = 0;
                        OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee)
                        {
                            Status = OrderStatus.Filled
                        });
                    }
                }

                if (postOrderResponse.tradesClosed != null)
                {
                    var tradePositionClosedIds = postOrderResponse.tradesClosed.Select(tradesClosed => tradesClosed.id).ToList();
                    var priorOrderPositionIds  = priorOrderPositions.trades.Select(previousTrade => previousTrade.id).ToList();
                    var verifyClosedOrder      = tradePositionClosedIds.Intersect(priorOrderPositionIds).Count() == tradePositionClosedIds.Count();
                    if (verifyClosedOrder)
                    {
                        const int orderFee = 0;
                        OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee)
                        {
                            Status = OrderStatus.Filled
                        });
                    }
                }
            }

            if (order.Type == OrderType.Market && order.Direction == OrderDirection.Sell)
            {
                //assume that we are opening a new buy market order
                if (postOrderResponse.tradeOpened != null && postOrderResponse.tradeOpened.id > 0)
                {
                    var tradeOpenedId = postOrderResponse.tradeOpened.id;
                    requestParams = new Dictionary <string, string>();
                    var tradeListResponse = GetTradeList(requestParams);
                    if (tradeListResponse.trades.Any(trade => trade.id == tradeOpenedId))
                    {
                        order.BrokerId.Add(tradeOpenedId);
                        const int orderFee = 0;
                        OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee)
                        {
                            Status = OrderStatus.Filled
                        });
                    }
                }

                if (postOrderResponse.tradesClosed != null)
                {
                    var tradePositionClosedIds = postOrderResponse.tradesClosed.Select(tradesClosed => tradesClosed.id).ToList();
                    var priorOrderPositionIds  = priorOrderPositions.trades.Select(previousTrade => previousTrade.id).ToList();
                    var verifyClosedOrder      = tradePositionClosedIds.Intersect(priorOrderPositionIds).Count() == tradePositionClosedIds.Count();
                    if (verifyClosedOrder)
                    {
                        const int orderFee = 0;
                        OnOrderEvent(new OrderEvent(order, DateTime.UtcNow, orderFee)
                        {
                            Status = OrderStatus.Filled
                        });
                    }
                }
            }
            return(true);
        }
Esempio n. 55
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));
            }
        }
Esempio n. 56
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("FxcmBrokerage.UpdateOrder(): {0}", order);

            if (!IsConnected)
                throw new InvalidOperationException("FxcmBrokerage.UpdateOrder(): Unable to update order while not connected.");

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

            var fxcmOrderId = order.BrokerId[0].ToString();

            ExecutionReport fxcmOrder;
            if (!_openOrders.TryGetValue(fxcmOrderId, out fxcmOrder))
                throw new ArgumentException("FxcmBrokerage.UpdateOrder(): FXCM order id not found: " + fxcmOrderId);

            double price;
            switch (order.Type)
            {
                case OrderType.Limit:
                    price = (double)((LimitOrder)order).LimitPrice;
                    break;

                case OrderType.StopMarket:
                    price = (double)((StopMarketOrder)order).StopPrice;
                    break;

                default:
                    throw new NotSupportedException("FxcmBrokerage.UpdateOrder(): Invalid order type.");
            }

            _isOrderUpdateOrCancelRejected = false;
            var orderReplaceRequest = MessageGenerator.generateOrderReplaceRequest("", fxcmOrder.getOrderID(), fxcmOrder.getSide(), fxcmOrder.getOrdType(), price, fxcmOrder.getAccount());
            orderReplaceRequest.setInstrument(fxcmOrder.getInstrument());
            orderReplaceRequest.setOrderQty((double)order.AbsoluteQuantity);

            AutoResetEvent autoResetEvent;
            lock (_locker)
            {
                _currentRequest = _gateway.sendMessage(orderReplaceRequest);
                autoResetEvent = new AutoResetEvent(false);
                _mapRequestsToAutoResetEvents[_currentRequest] = autoResetEvent;
            }
            if (!autoResetEvent.WaitOne(ResponseTimeout))
                throw new TimeoutException(string.Format("FxcmBrokerage.UpdateOrder(): Operation took longer than {0} seconds.", (decimal)ResponseTimeout / 1000));

            return !_isOrderUpdateOrCancelRejected;
        }