/********************************************************
        * 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;
        }
        /********************************************************
        * 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;
        }
 public override void OnOrderEvent(OrderEvent fill)
 {
     SymbolData sd;
     if (_sd.TryGetValue(fill.Symbol, out sd))
     {
         sd.OnOrderEvent(fill);
     }
 }
 public override void OnOrderEvent(OrderEvent orderEvent)
 {
     if (orderEvent.Status == OrderStatus.Submitted)
     {
         Console.WriteLine(Time + ": Submitted: " + Transactions.GetOrderById(orderEvent.OrderId));
     }
     if (orderEvent.Status.IsFill())
     {
         Console.WriteLine(Time + ": Filled: " + Transactions.GetOrderById(orderEvent.OrderId));
     }
 }
        /// <summary>
        /// Logs the OrderEvent Transaction
        /// </summary>
        /// <param name="orderEvent">the OrderEvent being logged</param>
        /// <param name="includeHeader">Includes the field names</param>
        public OrderTransaction Create(OrderEvent orderEvent, OrderTicket ticket, bool includeHeader = true)
        {
            var security = _algorithm.Securities[ticket.Symbol];

            Order order = _algorithm.Transactions.GetOrderById(orderEvent.OrderId);
            OrderTransaction t = new OrderTransaction();

            // According to Scottrade a Buy is a negative amount (funds flow from my account to the seller's)
            //  However the Quantity filled is a negative number for Sell/Short and a positive for Buy/Long
            //  So multiply by -1 to give order value the correct sign
            decimal orderValue = -1 * ticket.QuantityFilled * ticket.AverageFillPrice;

            if (order != null)
            {
                var orderDateTime = _algorithm.Time;
                DateTime settleDate = orderDateTime.AddDays(orderDateTime.DayOfWeek < DayOfWeek.Wednesday ? 3 : 5);

                // Order Fees are a cost and negative to my account, therefore a negative number
                var orderFees = security.TransactionModel.GetOrderFee(security, order) * -1;

                #region "Create OrderTransaction"

                t.ActionId = orderEvent.Direction.ToString() == "Buy" ? 1 : 13;
                t.ActionNameUS = orderEvent.Direction.ToString();
                t.Amount = orderValue;
                t.Broker = "IB";
                t.CUSIP = "CUSIP";
                t.Commission = orderFees;
                t.Description = string.Format("{0} {1} shares of {2} at ${3}", orderEvent.Direction, ticket.Quantity, orderEvent.Symbol, order.Price);
                t.Direction = orderEvent.Direction;
                t.Exchange = "";
                t.Fees = 0;  // need to calculate based upon difference in Portfolio[symbol].HoldingsValue between buy and sell
                t.Id = 0;
                t.Interest = 0;
                t.Net = orderValue + orderFees;
                t.OrderId = order.Id;
                t.OrderType = ticket.OrderType;
                t.Price = ticket.AverageFillPrice;
                t.Quantity = ticket.Quantity;
                t.RecordType = "Trade";
                t.SettledDate = settleDate;
                t.Symbol = ticket.Symbol.Value;
                t.TaxLotNumber = String.Empty;
                t.TradeDate = orderDateTime;
                t.TradeNumber = 0;
                #endregion
            }
            return t;
        }
        public void LastTradeProfit_FlatToShort()
        {
            var reference = new DateTime(2016, 02, 16, 11, 53, 30);
            SecurityPortfolioManager portfolio;
            var security = InitializeTest(reference, out portfolio);

            var fillPrice = 100m;
            var fillQuantity = -100;
            var orderFee = 1m;
            var orderDirection = fillQuantity > 0 ? OrderDirection.Buy : OrderDirection.Sell;
            var fill = new OrderEvent(1, security.Symbol, reference, OrderStatus.Filled, orderDirection, fillPrice, fillQuantity, orderFee);
            portfolio.ProcessFill(fill);

            // zero since we're from flat
            Assert.AreEqual(0, security.Holdings.LastTradeProfit);
        }
        /// <summary>
        /// Default market fill model for the base security class. Fills at the last traded price.
        /// </summary>
        /// <param name="asset">Security asset we're filling</param>
        /// <param name="order">Order packet to model</param>
        /// <returns>Order fill information detailing the average price and quantity filled.</returns>
        /// <seealso cref="StopMarketFill(Security, StopMarketOrder)"/>
        /// <seealso cref="LimitFill(Security, LimitOrder)"/>
        public virtual OrderEvent MarketFill(Security asset, MarketOrder order)
        {
            //Default order event to return.
            var utcTime = asset.LocalTime.ConvertToUtc(asset.Exchange.TimeZone);
            var orderFee = GetOrderFee(asset, order);
            var fill = new OrderEvent(order, utcTime, orderFee);

            if (order.Status == OrderStatus.Canceled) return fill;

            // make sure the exchange is open before filling
            if (!IsExchangeOpen(asset)) return fill;

            try
            {
                //Order [fill]price for a market order model is the current security price
                fill.FillPrice = asset.Price;
                fill.Status = OrderStatus.Filled;

                //Calculate the model slippage: e.g. 0.01c
                var slip = GetSlippageApproximation(asset, order);

                //Apply slippage
                switch (order.Direction)
                {
                    case OrderDirection.Buy:
                        fill.FillPrice += slip;
                        break;
                    case OrderDirection.Sell:
                        fill.FillPrice -= slip;
                        break;
                }

                // assume the order completely filled
                if (fill.Status == OrderStatus.Filled) fill.FillQuantity = order.Quantity;
            }
            catch (Exception err)
            {
                Log.Error("SecurityTransactionModel.MarketFill(): " + err.Message);
            }

            return fill;
        }
Example #8
0
        /// <summary>
        /// Logs the OrderEvent Transaction
        /// </summary>
        /// <param name="orderEvent">the OrderEvent being logged</param>
        public string ReportTransaction(OrderEvent orderEvent)
        {
            #region Print

            string transmsg = string.Format("Order {0} on not found", orderEvent.OrderId);
            Order order = _algorithm.Transactions.GetOrderById(orderEvent.OrderId);
            decimal orderValue = orderEvent.FillQuantity*orderEvent.FillPrice;

            //if (order != null)
            //{

            //var orderDateTime = order.Time;
            decimal orderFees = 0;
            orderFees = _algorithm.Securities[order.Symbol].TransactionModel.GetOrderFee(_algorithm.Securities[order.Symbol], order);
            int actionid = orderEvent.Direction.ToString() == "Buy" ? 1 : 13;
            transmsg = string.Format(
                "{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12},{13},{14},{15}",
                orderEvent.Symbol,
                orderEvent.FillQuantity,
                orderEvent.FillPrice,
                orderEvent.Direction.ToString(),
                order.Time,
                order.Time.AddDays(4),
                orderValue,
                orderFees,
                orderValue + orderFees,
                "",
                orderEvent.Direction + " share of " + orderEvent.Symbol + "at $" + orderEvent.FillPrice.ToString(),
                actionid,
                order.Id,
                "Trade",
                "taxlot",
                ""
                );
            //  }
            _logHandler.Debug(transmsg);
            return transmsg;

            #endregion
        }
Example #9
0
 /// <summary>
 /// Send a new order event to the browser.
 /// </summary>
 /// <remarks>In backtesting the order events are not sent because it would generate a high load of messaging.</remarks>
 /// <param name="newEvent">New order event details</param>
 public void OrderEvent(OrderEvent newEvent)
 {
     // NOP. Don't do any order event processing for results in backtest mode.
 }
        private void HandleOrderEvent(OrderEvent fill)
        {
            // update the order status
            var order = GetOrderByIdInternal(fill.OrderId);
            if (order == null)
            {
                Log.Error("BrokerageTransactionHandler.HandleOrderEvent(): Unable to locate Order with id " + fill.OrderId);
                return;
            }

            // set the status of our order object based on the fill event
            order.Status = fill.Status;

            // save that the order event took place, we're initializing the list with a capacity of 2 to reduce number of mallocs
            //these hog memory
            //List<OrderEvent> orderEvents = _orderEvents.GetOrAdd(orderEvent.OrderId, i => new List<OrderEvent>(2));
            //orderEvents.Add(orderEvent);

            //Apply the filled order to our portfolio:
            if (fill.Status == OrderStatus.Filled || fill.Status == OrderStatus.PartiallyFilled)
            {
                Log.Debug("BrokerageTransactionHandler.HandleOrderEvent(): " + fill);
                Interlocked.Exchange(ref _lastFillTimeTicks, DateTime.Now.Ticks);

                // check if the fill currency and the order currency match the symbol currency
                var security = _algorithm.Securities[fill.Symbol];
                if (fill.FillPriceCurrency != security.SymbolProperties.QuoteCurrency)
                {
                    Log.Error(string.Format("Currency mismatch: Fill currency: {0}, Symbol currency: {1}", fill.FillPriceCurrency, security.SymbolProperties.QuoteCurrency));
                }
                if (order.PriceCurrency != security.SymbolProperties.QuoteCurrency)
                {
                    Log.Error(string.Format("Currency mismatch: Order currency: {0}, Symbol currency: {1}", order.PriceCurrency, security.SymbolProperties.QuoteCurrency));
                }

                try
                {
                    _algorithm.Portfolio.ProcessFill(fill);

                    var conversionRate = security.QuoteCurrency.ConversionRate;

                    _algorithm.TradeBuilder.ProcessFill(fill, conversionRate);
                }
                catch (Exception err)
                {
                    Log.Error(err);
                    _algorithm.Error(string.Format("Order Error: id: {0}, Error in Portfolio.ProcessFill: {1}", order.Id, err.Message));
                }
            }

            // update the ticket and order after we've processed the fill, but before the event, this way everything is ready for user code
            OrderTicket ticket;
            if (_orderTickets.TryGetValue(fill.OrderId, out ticket))
            {
                ticket.AddOrderEvent(fill);
                order.Price = ticket.AverageFillPrice;
            }
            else
            {
                Log.Error("BrokerageTransactionHandler.HandleOrderEvent(): Unable to resolve ticket: " + fill.OrderId);
            }

            //We have an event! :) Order filled, send it in to be handled by algorithm portfolio.
            if (fill.Status != OrderStatus.None) //order.Status != OrderStatus.Submitted
            {
                //Create new order event:
                _resultHandler.OrderEvent(fill);
                try
                {
                    //Trigger our order event handler
                    _algorithm.OnOrderEvent(fill);
                }
                catch (Exception err)
                {
                    _algorithm.Error("Order Event Handler Error: " + err.Message);
                    // kill the algorithm
                    _algorithm.RunTimeError = err;
                }
            }
        }
Example #11
0
 /// <summary>
 /// Handle order events
 /// </summary>
 /// <param name="orderEvent">the order event</param>
 public override void OnOrderEvent(OrderEvent orderEvent)
 {
     base.OnOrderEvent(orderEvent);
     ProcessOrderEvent(orderEvent);
 }
        /// <summary>
        /// Handles error messages from IB
        /// </summary>
        private void HandleError(object sender, IB.ErrorEventArgs e)
        {
            // https://www.interactivebrokers.com/en/software/api/apiguide/tables/api_message_codes.htm

            // rewrite these messages to be single lined
            e.ErrorMsg = e.ErrorMsg.Replace("\r\n", ". ").Replace("\r", ". ").Replace("\n", ". ");
            Log.Trace(string.Format("InteractiveBrokersBrokerage.HandleError(): Order: {0} ErrorCode: {1} - {2}", e.TickerId, e.ErrorCode, e.ErrorMsg));

            // figure out the message type based on our code collections below
            var brokerageMessageType = BrokerageMessageType.Information;
            if (ErrorCodes.Contains((int) e.ErrorCode))
            {
                brokerageMessageType = BrokerageMessageType.Error;
            }
            else if (WarningCodes.Contains((int) e.ErrorCode))
            {
                brokerageMessageType = BrokerageMessageType.Warning;
            }

            // code 1100 is a connection failure, we'll wait a minute before exploding gracefully
            if ((int) e.ErrorCode == 1100 && !_disconnected1100Fired)
            {
                _disconnected1100Fired = true;

                // begin the try wait logic
                TryWaitForReconnect();
            }
            else if ((int) e.ErrorCode == 1102)
            {
                // we've reconnected
                _disconnected1100Fired = false;
                OnMessage(BrokerageMessageEvent.Reconnected(e.ErrorMsg));
            }

            if (InvalidatingCodes.Contains((int)e.ErrorCode))
            {
                Log.Trace(string.Format("InteractiveBrokersBrokerage.HandleError.InvalidateOrder(): Order: {0} ErrorCode: {1} - {2}", e.TickerId, e.ErrorCode, e.ErrorMsg));

                // invalidate the order
                var order = _orderProvider.GetOrderByBrokerageId(e.TickerId);
                const int orderFee = 0;
                var orderEvent = new OrderEvent(order, DateTime.UtcNow, orderFee) { Status = OrderStatus.Invalid };
                OnOrderEvent(orderEvent);
            }

            OnMessage(new BrokerageMessageEvent(brokerageMessageType, (int) e.ErrorCode, e.ErrorMsg));
        }
 public void OrderEvent(OrderEvent newEvent)
 {
 }
Example #14
0
        /// <summary>
        /// Scans all the outstanding orders and applies the algorithm model fills to generate the order events
        /// </summary>
        public void Scan()
        {
            lock (_needsScanLock)
            {
                // there's usually nothing in here
                if (!_needsScan)
                {
                    return;
                }

                var stillNeedsScan = false;

                // process each pending order to produce fills/fire events
                foreach (var kvp in _pending)
                {
                    var order = kvp.Value;
                    if (order.Status.IsClosed())
                    {
                        // this should never actually happen as we always remove closed orders as they happen
                        _pending.TryRemove(order.Id, out order);
                        continue;
                    }

                    var fill = new OrderEvent(order, Algorithm.UtcTime, 0);

                    Security security;
                    if (!Algorithm.Securities.TryGetValue(order.Symbol, out security))
                    {
                        Log.Error("BacktestingBrokerage.Scan(): Unable to process order: " + order.Id + ". The security no longer exists.");
                        // invalidate the order in the algorithm before removing
                        OnOrderEvent(new OrderEvent(order, Algorithm.UtcTime, 0m){Status = OrderStatus.Invalid});
                        _pending.TryRemove(order.Id, out order);
                        continue;
                    }

                    // check if we would actually be able to fill this
                    if (!Algorithm.BrokerageModel.CanExecuteOrder(security, order))
                    {
                        continue;
                    }

                    // verify sure we have enough cash to perform the fill
                    bool sufficientBuyingPower;
                    try
                    {
                        sufficientBuyingPower = Algorithm.Transactions.GetSufficientCapitalForOrder(Algorithm.Portfolio, order);
                    }
                    catch (Exception err)
                    {
                        // if we threw an error just mark it as invalid and remove the order from our pending list
                        Order pending;
                        _pending.TryRemove(order.Id, out pending);
                        order.Status = OrderStatus.Invalid;
                        OnOrderEvent(new OrderEvent(order, Algorithm.UtcTime, 0, "Error in GetSufficientCapitalForOrder"));

                        Log.Error(err);
                        Algorithm.Error(string.Format("Order Error: id: {0}, Error executing margin models: {1}", order.Id, err.Message));
                        continue;
                    }

                    //Before we check this queued order make sure we have buying power:
                    if (sufficientBuyingPower)
                    {
                        //Model:
                        var model = security.TransactionModel;

                        //Based on the order type: refresh its model to get fill price and quantity
                        try
                        {
                            switch (order.Type)
                            {
                                case OrderType.Limit:
                                    fill = model.LimitFill(security, order as LimitOrder);
                                    break;

                                case OrderType.StopMarket:
                                    fill = model.StopMarketFill(security, order as StopMarketOrder);
                                    break;

                                case OrderType.Market:
                                    fill = model.MarketFill(security, order as MarketOrder);
                                    break;

                                case OrderType.StopLimit:
                                    fill = model.StopLimitFill(security, order as StopLimitOrder);
                                    break;

                                case OrderType.MarketOnOpen:
                                    fill = model.MarketOnOpenFill(security, order as MarketOnOpenOrder);
                                    break;

                                case OrderType.MarketOnClose:
                                    fill = model.MarketOnCloseFill(security, order as MarketOnCloseOrder);
                                    break;
                            }
                        }
                        catch (Exception err)
                        {
                            Log.Error(err);
                            Algorithm.Error(string.Format("Order Error: id: {0}, Transaction model failed to fill for order type: {1} with error: {2}",
                                order.Id, order.Type, err.Message));
                        }
                    }
                    else
                    {
                        //Flag order as invalid and push off queue:
                        order.Status = OrderStatus.Invalid;
                        Algorithm.Error(string.Format("Order Error: id: {0}, Insufficient buying power to complete order (Value:{1}).", order.Id,
                            order.GetValue(security.Price).SmartRounding()));
                    }

                    // change in status or a new fill
                    if (order.Status != fill.Status || fill.FillQuantity != 0)
                    {
                        //If the fill models come back suggesting filled, process the affects on portfolio
                        OnOrderEvent(fill);
                    }

                    if (fill.Status.IsClosed())
                    {
                        _pending.TryRemove(order.Id, out order);
                    }
                    else
                    {
                        stillNeedsScan = true;
                    }
                }
                
                // if we didn't fill then we need to continue to scan
                _needsScan = stillNeedsScan;
            }
        }
        public void SellingShortFromShortAddsToCash()
        {
            var securities = new SecurityManager(TimeKeeper);
            var transactions = new SecurityTransactionManager(securities);
            var portfolio = new SecurityPortfolioManager(securities, transactions);
            portfolio.SetCash(0);

            securities.Add(Symbols.AAPL, new Security(SecurityExchangeHours, CreateTradeBarDataConfig(SecurityType.Equity, Symbols.AAPL), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency)));
            securities[Symbols.AAPL].Holdings.SetHoldings(100, -100);

            var fill = new OrderEvent(1, Symbols.AAPL, DateTime.MinValue,  OrderStatus.Filled, OrderDirection.Sell,  100, -100, 0);
            Assert.AreEqual(-100, securities[Symbols.AAPL].Holdings.Quantity);
            portfolio.ProcessFill(fill);

            Assert.AreEqual(100 * 100, portfolio.Cash);
            Assert.AreEqual(-200, securities[Symbols.AAPL].Holdings.Quantity);
        }
Example #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)
        {
            if (true)
            {
                Order pending;
                if (!_pending.TryGetValue(order.Id, out pending))
                {
                    // can't update something that isn't there
                    return false;
                }

                lock (_needsScanLock)
                {
                    _needsScan = true;
                    SetPendingOrder(order);
                }

                var orderId = order.Id.ToString();
                if (!order.BrokerId.Contains(orderId)) order.BrokerId.Add(orderId);

                // fire off the event that says this order has been updated
                const int orderFee = 0;
                var updated = new OrderEvent(order, Algorithm.UtcTime, orderFee) { Status = OrderStatus.Submitted };
                OnOrderEvent(updated);

                return true;
            }
        }
Example #17
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)
        {
            Order pending;
            if (!_pending.TryRemove(order.Id, out pending))
            {
                // can't cancel something that isn't there
                return false;
            }

            var orderId = order.Id.ToString();
            if (!order.BrokerId.Contains(orderId)) order.BrokerId.Add(order.Id.ToString());

            // fire off the event that says this order has been canceled
            const int orderFee = 0;
            var canceled = new OrderEvent(order, Algorithm.UtcTime, orderFee) { Status = OrderStatus.Canceled };
            OnOrderEvent(canceled);

            return true;
        }
        public void ForexFillUpdatesCashCorrectly()
        {
            var securities = new SecurityManager(TimeKeeper);
            var transactions = new SecurityTransactionManager(securities);
            var portfolio = new SecurityPortfolioManager(securities, transactions);
            portfolio.SetCash(1000);
            portfolio.CashBook.Add("EUR", 0, 1.1000m);

            securities.Add(Symbols.EURUSD, new QuantConnect.Securities.Forex.Forex(SecurityExchangeHours, portfolio.CashBook["USD"], CreateTradeBarDataConfig(SecurityType.Forex, Symbols.EURUSD), SymbolProperties.GetDefault(CashBook.AccountCurrency)));
            var security = securities[Symbols.EURUSD];
            Assert.AreEqual(0, security.Holdings.Quantity);
            Assert.AreEqual(1000, portfolio.Cash);

            var orderFee = security.FeeModel.GetOrderFee(security, new MarketOrder(Symbols.EURUSD, 100, DateTime.MinValue));
            var fill = new OrderEvent(1, Symbols.EURUSD, DateTime.MinValue, OrderStatus.Filled, OrderDirection.Buy, 1.1000m, 100, orderFee);
            portfolio.ProcessFill(fill);
            Assert.AreEqual(100, security.Holdings.Quantity);
            Assert.AreEqual(998, portfolio.Cash);
            Assert.AreEqual(100, portfolio.CashBook["EUR"].Amount);
            Assert.AreEqual(888, portfolio.CashBook["USD"].Amount);
        }
Example #19
0
 /// <summary>
 /// Send a new order event to the browser.
 /// </summary>
 /// <remarks>In backtesting the order events are not sent because it would generate a high load of messaging.</remarks>
 /// <param name="newEvent">New order event details</param>
 public void OrderEvent(OrderEvent newEvent)
 {
     Log.Trace("ConsoleResultHandler.OrderEvent(): id:" + newEvent.OrderId + " >> Status:" + newEvent.Status + " >> Fill Price: " + newEvent.FillPrice.ToString("C") + " >> Fill Quantity: " + newEvent.FillQuantity);
 }
        public void EquitySellAppliesSettlementCorrectly()
        {
            var securityExchangeHours = SecurityExchangeHoursTests.CreateUsEquitySecurityExchangeHours();
            var securities = new SecurityManager(TimeKeeper);
            var transactions = new SecurityTransactionManager(securities);
            var portfolio = new SecurityPortfolioManager(securities, transactions);
            portfolio.SetCash(1000);
            securities.Add(Symbols.AAPL, new QuantConnect.Securities.Equity.Equity(securityExchangeHours, CreateTradeBarDataConfig(SecurityType.Equity, Symbols.AAPL), new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency)));
            var security = securities[Symbols.AAPL];
            security.SettlementModel = new DelayedSettlementModel(3, TimeSpan.FromHours(8));
            Assert.AreEqual(0, security.Holdings.Quantity);
            Assert.AreEqual(1000, portfolio.Cash);
            Assert.AreEqual(0, portfolio.UnsettledCash);

            // Buy on Monday
            var timeUtc = new DateTime(2015, 10, 26, 15, 30, 0);
            var orderFee = security.FeeModel.GetOrderFee(security,new MarketOrder(Symbols.AAPL, 10, timeUtc));
            var fill = new OrderEvent(1, Symbols.AAPL, timeUtc, OrderStatus.Filled, OrderDirection.Buy, 100, 10, orderFee);
            portfolio.ProcessFill(fill);
            Assert.AreEqual(10, security.Holdings.Quantity);
            Assert.AreEqual(-1, portfolio.Cash);
            Assert.AreEqual(0, portfolio.UnsettledCash);

            // Sell on Tuesday, cash unsettled
            timeUtc = timeUtc.AddDays(1);
            orderFee = security.FeeModel.GetOrderFee(security, new MarketOrder(Symbols.AAPL, 10, timeUtc));
            fill = new OrderEvent(2, Symbols.AAPL, timeUtc, OrderStatus.Filled, OrderDirection.Sell, 100, -10, orderFee);
            portfolio.ProcessFill(fill);
            Assert.AreEqual(0, security.Holdings.Quantity);
            Assert.AreEqual(-2, portfolio.Cash);
            Assert.AreEqual(1000, portfolio.UnsettledCash);

            // Thursday, still cash unsettled
            timeUtc = timeUtc.AddDays(2);
            portfolio.ScanForCashSettlement(timeUtc);
            Assert.AreEqual(-2, portfolio.Cash);
            Assert.AreEqual(1000, portfolio.UnsettledCash);

            // Friday at open, cash settled
            var marketOpen = securityExchangeHours.MarketHours[timeUtc.DayOfWeek].GetMarketOpen(TimeSpan.Zero, false);
            Assert.IsTrue(marketOpen.HasValue);
            timeUtc = timeUtc.AddDays(1).Date.Add(marketOpen.Value).ConvertToUtc(securityExchangeHours.TimeZone);
            portfolio.ScanForCashSettlement(timeUtc);
            Assert.AreEqual(998, portfolio.Cash);
            Assert.AreEqual(0, portfolio.UnsettledCash);
        }
Example #21
0
        public override void OnOrderEvent(OrderEvent orderEvent)
        {
            string symbol = orderEvent.Symbol;
            int portfolioPosition = Portfolio[symbol].Quantity;
            var actualTicket = Transactions.GetOrderTickets(t => t.OrderId == orderEvent.OrderId).Single();
            var actualOrder = Transactions.GetOrderById(orderEvent.OrderId);

            switch (orderEvent.Status)
            {
                case OrderStatus.Submitted:
                    Strategy[symbol].Position = StockState.orderSent;
                    Log("New order submitted: " + actualOrder.ToString());
                    break;

                case OrderStatus.PartiallyFilled:
                    Log("Order partially filled: " + actualOrder.ToString());
                    Log("Canceling order");
                    actualTicket.Cancel();
                    //do { }
                    //while (actualTicket.GetMostRecentOrderResponse().IsSuccess);
                    goto case OrderStatus.Filled;

                case OrderStatus.Filled:
                    if (portfolioPosition > 0) Strategy[symbol].Position = StockState.longPosition;
                    else if (portfolioPosition < 0) Strategy[symbol].Position = StockState.shortPosition;
                    else Strategy[symbol].Position = StockState.noInvested;

                    Strategy[symbol].EntryPrice = actualTicket.AverageFillPrice;

                    Log("Order filled: " + actualOrder.ToString());
                    break;

                case OrderStatus.Canceled:
                    Log("Order successfully canceled: " + actualOrder.ToString());
                    break;

                default:
                    break;
            }
        }
        public void ComputeMarginProperlyShortCoverZeroLong()
        {
            const decimal leverage = 2m;
            const int amount = 1000;
            const int quantity = (int)(amount * leverage);
            var securities = new SecurityManager(TimeKeeper);
            var transactions = new SecurityTransactionManager(securities);
            var orderProcessor = new OrderProcessor();
            transactions.SetOrderProcessor(orderProcessor);
            var portfolio = new SecurityPortfolioManager(securities, transactions);
            portfolio.CashBook["USD"].SetAmount(amount);

            var config = CreateTradeBarDataConfig(SecurityType.Equity, Symbols.AAPL);
            securities.Add(new Security(SecurityExchangeHours, config, new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency)));
            var security = securities[Symbols.AAPL];
            security.SetLeverage(leverage);

            var time = DateTime.Now;
            const decimal sellPrice = 1m;
            security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, sellPrice, sellPrice, sellPrice, sellPrice, 1));

            var order = new MarketOrder(Symbols.AAPL, -quantity, time) { Price = sellPrice };
            var fill = new OrderEvent(order, DateTime.UtcNow, 0) { FillPrice = sellPrice, FillQuantity = -quantity };
            orderProcessor.AddOrder(order);
            var request = new SubmitOrderRequest(OrderType.Market, security.Type, security.Symbol, order.Quantity, 0, 0, order.Time, null);
            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(null, request));

            portfolio.ProcessFill(fill);

            // we shouldn't be able to place a new short order
            var newOrder = new MarketOrder(Symbols.AAPL, -1, time.AddSeconds(1)) { Price = sellPrice };
            var sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, newOrder);
            Assert.IsFalse(sufficientCapital);

            // we should be able to place cover to zero
            newOrder = new MarketOrder(Symbols.AAPL, quantity, time.AddSeconds(1)) { Price = sellPrice };
            sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, newOrder);
            Assert.IsTrue(sufficientCapital);

            // now the stock doubles, so we should have negative margin remaining
            time = time.AddDays(1);
            const decimal highPrice = sellPrice * 2;
            security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, highPrice, highPrice, highPrice, highPrice, 1));

            // we still shouldn be able to place cover to zero
            newOrder = new MarketOrder(Symbols.AAPL, quantity, time.AddSeconds(1)) { Price = highPrice };
            sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, newOrder);
            Assert.IsTrue(sufficientCapital);

            // we shouldn't be able to place cover to long
            newOrder = new MarketOrder(Symbols.AAPL, quantity + 1, time.AddSeconds(1)) { Price = highPrice };
            sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, newOrder);
            Assert.IsFalse(sufficientCapital);
        }
        /// <summary>
        /// Handle order events from IB
        /// </summary>
        private void HandleOrderStatusUpdates(object sender, IB.OrderStatusEventArgs update)
        {
            try
            {
                var order = _orderProvider.GetOrderByBrokerageId(update.OrderId);
                if (order == null)
                {
                    Log.Error("InteractiveBrokersBrokerage.HandleOrderStatusUpdates(): Unable to locate order with BrokerageID " + update.OrderId);
                    return;
                }


                var status = ConvertOrderStatus(update.Status);
                if (order.Status == OrderStatus.Filled && update.Filled == 0 && update.Remaining == 0)
                {
                    // we're done with this order, remove from our state
                    int value;
                    _orderFills.TryRemove(order.Id, out value);
                }

                var orderFee = 0m;
                int filledThisTime;
                lock (_orderFillsLock)
                {
                    // lock since we're getting and updating in multiple operations
                    var currentFilled = _orderFills.GetOrAdd(order.Id, 0);
                    if (currentFilled == 0)
                    {
                        // apply order fees on the first fill event TODO: What about partial filled orders that get cancelled?
                        var security = _securityProvider.GetSecurity(order.Symbol);
                        orderFee = security.FeeModel.GetOrderFee(security, order);
                    }
                    filledThisTime = update.Filled - currentFilled;
                    _orderFills.AddOrUpdate(order.Id, currentFilled, (sym, filled) => update.Filled);
                }

                if (status == OrderStatus.Invalid)
                {
                    Log.Error("InteractiveBrokersBrokerage.HandleOrderStatusUpdates(): ERROR -- " + update.OrderId);
                }

                // set status based on filled this time
                if (filledThisTime != 0)
                {
                    status = update.Remaining != 0 ? OrderStatus.PartiallyFilled : OrderStatus.Filled;
                }
                // don't send empty fill events
                else if (status == OrderStatus.PartiallyFilled || status == OrderStatus.Filled)
                {
                    Log.Trace("InteractiveBrokersBrokerage.HandleOrderStatusUpdates(): Ignored zero fill event: OrderId: " + update.OrderId + " Remaining: " + update.Remaining);
                    return;
                }

                // mark sells as negative quantities
                var fillQuantity = order.Direction == OrderDirection.Buy ? filledThisTime : -filledThisTime;
                order.PriceCurrency = _securityProvider.GetSecurity(order.Symbol).SymbolProperties.QuoteCurrency;
                var orderEvent = new OrderEvent(order, DateTime.UtcNow, orderFee, "Interactive Brokers Fill Event")
                {
                    Status = status,
                    FillPrice = update.LastFillPrice,
                    FillQuantity = fillQuantity
                };
                if (update.Remaining != 0)
                {
                    orderEvent.Message += " - " + update.Remaining + " remaining";
                }

                // if we're able to add to our fixed length, unique queue then send the event
                // otherwise it is a duplicate, so skip it
                if (_recentOrderEvents.Add(orderEvent.ToString() + update.Remaining))
                {
                    OnOrderEvent(orderEvent);
                }
            }
            catch(InvalidOperationException err)
            {
                Log.Error("InteractiveBrokersBrokerage.HandleOrderStatusUpdates(): Unable to resolve executions for BrokerageID: " + update.OrderId + " - " + err);
            }
            catch (Exception err)
            {
                Log.Error("InteractiveBrokersBrokerage.HandleOrderStatusUpdates(): " + err);
            }
        }
Example #24
0
 /// <summary>
 /// Create a new instance of the order event packet
 /// </summary>
 public OrderEventPacket(string algorithmId, OrderEvent eventOrder)
     : base(PacketType.OrderEvent)
 {
     AlgorithmId = algorithmId;
     Event = eventOrder;
 }
Example #25
0
        /// <summary>
        /// Local processing of the order event.  It only logs the transaction and orderEvent
        /// </summary>
        /// <param name="orderEvent">OrderEvent - the order event</param>
        private void ProcessOrderEvent(OrderEvent orderEvent)
        {
            //add to the list of order events which is saved to a file when running locally 
            //  I will use this file to test Stefano Raggi's code

            var currentSignalInfo = signalInfos.FirstOrDefault(s => s.Symbol == orderEvent.Symbol);
            orderId = orderEvent.OrderId;

            if (currentSignalInfo != null)
                currentSignalInfo.Status = orderEvent.Status;


            IEnumerable<OrderTicket> tickets = Transactions.GetOrderTickets(t => t.OrderId == orderId);

            switch (orderEvent.Status)
            {
                case OrderStatus.New:
                case OrderStatus.None:
                case OrderStatus.Submitted:
                case OrderStatus.Invalid:
                    break;
                case OrderStatus.PartiallyFilled:
                    if (currentSignalInfo != null)
                    {

                        nEntryPrice = Portfolio[orderEvent.Symbol].HoldStock ? Portfolio[orderEvent.Symbol].AveragePrice : 0;
                        currentSignalInfo.TradeAttempts++;
                        //Log(string.Format("Trade Attempts: {0} OrderId {1}", currentSignalInfo.TradeAttempts, orderEvent.OrderId));
                    }

                    break;
                case OrderStatus.Canceled:
                    if (currentSignalInfo != null)
                    {
                        //Log(string.Format("Order {0} cancelled.", orderEvent.OrderId));
                        currentSignalInfo.IsActive = true;
                        currentSignalInfo.TradeAttempts = 0;
                    }
                    break;
                case OrderStatus.Filled:

                    if (currentSignalInfo != null)
                    {
                        currentSignalInfo.IsActive = true;
                        //if (currentSignalInfo.TradeAttempts > 0)
                        //    Log(string.Format("Order Filled OrderId {0} on attempt {1}", orderEvent.OrderId, currentSignalInfo.TradeAttempts));
                        currentSignalInfo.TradeAttempts = 0;

                    }
                    nEntryPrice = Portfolio[orderEvent.Symbol].HoldStock ? Portfolio[orderEvent.Symbol].AveragePrice : 0;

                    if (tickets != null)
                    {
                        foreach (OrderTicket ticket in tickets)
                        {
                            //int infoId = Convert.ToInt32(ticket.Tag);

                            #region "save the ticket as a OrderTransacton"
                            OrderTransactionFactory transactionFactory = new OrderTransactionFactory((QCAlgorithm)this);
                            OrderTransaction t = transactionFactory.Create(orderEvent, ticket, false);
                            _transactions.Add(t);
                            _orderTransactionProcessor.ProcessTransaction(t);
                            _tradecount++;
                            if (_orderTransactionProcessor.TotalProfit != totalProfit)
                            {
                                tradenet = CalculateTradeProfit(t.Symbol);
                            }
                            totalProfit = _orderTransactionProcessor.TotalProfit;

                            #endregion

                        }
                    }
                    break;
            }
        }
Example #26
0
 /// <summary>
 /// Send a new order event to the browser.
 /// </summary>
 /// <remarks>In backtesting the order events are not sent because it would generate a high load of messaging.</remarks>
 /// <param name="newEvent">New order event details</param>
 public void OrderEvent(OrderEvent newEvent)
 {
     DebugMessage("DesktopResultHandler.OrderEvent(): id:" + newEvent.OrderId + " >> Status:" + newEvent.Status + " >> Fill Price: " + newEvent.FillPrice.ToString("C") + " >> Fill Quantity: " + newEvent.FillQuantity);
 }
        /// <summary>
        /// ExecutionReport message handler
        /// </summary>
        private void OnExecutionReport(ExecutionReport message)
        {
            var orderId = message.getOrderID();
            var orderStatus = message.getFXCMOrdStatus();

            if (orderId != "NONE" && message.getAccount() == _accountId)
            {
                if (_openOrders.ContainsKey(orderId) && OrderIsClosed(orderStatus.getCode()))
                {
                    _openOrders.Remove(orderId);
                }
                else
                {
                    _openOrders[orderId] = message;
                }

                Order order;
                if (_mapFxcmOrderIdsToOrders.TryGetValue(orderId, out order))
                {
                    // existing order
                    if (!OrderIsBeingProcessed(orderStatus.getCode()))
                    {
                        order.PriceCurrency = message.getCurrency();

                        var orderEvent = new OrderEvent(order, DateTime.UtcNow, 0)
                        {
                            Status = ConvertOrderStatus(orderStatus),
                            FillPrice = Convert.ToDecimal(message.getPrice()),
                            FillQuantity = Convert.ToInt32(message.getSide() == SideFactory.BUY ? message.getLastQty() : -message.getLastQty())
                        };

                        // we're catching the first fill so we apply the fees only once
                        if ((int)message.getCumQty() == (int)message.getLastQty() && message.getLastQty() > 0)
                        {
                            var security = _securityProvider.GetSecurity(order.Symbol);
                            orderEvent.OrderFee = security.FeeModel.GetOrderFee(security, order);
                        }

                        _orderEventQueue.Enqueue(orderEvent);
                    }
                }
                else if (_mapRequestsToOrders.TryGetValue(message.getRequestID(), out order))
                {
                    _mapFxcmOrderIdsToOrders[orderId] = order;
                    order.BrokerId.Add(orderId);
                    order.PriceCurrency = message.getCurrency();

                    // new order
                    var orderEvent = new OrderEvent(order, DateTime.UtcNow, 0)
                    {
                        Status = ConvertOrderStatus(orderStatus)
                    };

                    _orderEventQueue.Enqueue(orderEvent);
                }
            }

            if (message.getRequestID() == _currentRequest)
            {
                if (message.isLastRptRequested())
                {
                    if (orderId == "NONE" && orderStatus.getCode() == IFixValueDefs.__Fields.FXCMORDSTATUS_REJECTED)
                    {
                        if (message.getSide() != SideFactory.UNDISCLOSED)
                        {
                            var messageText = message.getFXCMErrorDetails().Replace("\n", "");
                            Log.Trace("FxcmBrokerage.OnExecutionReport(): " + messageText);
                            OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, "OrderSubmitReject", messageText));
                        }

                        _isOrderSubmitRejected = true;
                    }

                    _mapRequestsToAutoResetEvents[_currentRequest].Set();
                    _mapRequestsToAutoResetEvents.Remove(_currentRequest);
                }
            }
        }
Example #28
0
 public override void OnOrderEvent(OrderEvent orderEvent)
 {
     Console.WriteLine(Time + " - " + orderEvent);
 }
Example #29
0
 public override void OnOrderEvent(OrderEvent orderEvent)
 {
     if (orderEvent.Status.IsFill())
     {
         // if we receive a fill cancel the other outstanding order
         Transactions.CancelOpenOrders(orderEvent.Symbol);
     }
 }
Example #30
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)
        {
            if (order.Status == OrderStatus.New)
            {
                lock (_needsScanLock)
                {
                    _needsScan = true;
                    SetPendingOrder(order);
                }

                var orderId = order.Id.ToString();
                if (!order.BrokerId.Contains(orderId)) order.BrokerId.Add(orderId);

                // fire off the event that says this order has been submitted
                const int orderFee = 0;
                var submitted = new OrderEvent(order, Algorithm.UtcTime, orderFee) { Status = OrderStatus.Submitted };
                OnOrderEvent(submitted);

                return true;
            }
            return false;
        }