Пример #1
0
        public void OrderByMarginImpactDoesNotReturnTargetsForWhichUnorderedQuantityIsZeroBecauseOpenOrder()
        {
            var algorithm      = new FakeAlgorithm();
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);
            var symbol = new Symbol(SecurityIdentifier.GenerateEquity(_symbol, Market.USA), _symbol);
            var equity = algorithm.AddEquity(symbol);

            equity.Cache.AddData(new TradeBar(DateTime.UtcNow, symbol, 1, 1, 1, 1, 1));
            var collection = new PortfolioTargetCollection();
            var target     = new PortfolioTarget(symbol, 1);

            collection.Add(target);

            var openOrderRequest = new SubmitOrderRequest(OrderType.Market, symbol.SecurityType, symbol, 1, 0, 0, DateTime.UtcNow, "");

            openOrderRequest.SetOrderId(1);
            var openOrderTicket = new OrderTicket(algorithm.Transactions, openOrderRequest);

            orderProcessor.AddOrder(new MarketOrder(symbol, 1, DateTime.UtcNow));
            orderProcessor.AddTicket(openOrderTicket);

            var targets = collection.OrderByMarginImpact(algorithm);

            Assert.AreEqual(collection.Count, 1);
            Assert.IsTrue(targets.IsNullOrEmpty());
        }
Пример #2
0
        public void PartiallyFilledOrdersAreTakenIntoAccount(Language language)
        {
            var actualOrdersSubmitted = new List <SubmitOrderRequest>();

            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            algorithm.SetPandasConverter();

            var security = algorithm.AddEquity(Symbols.AAPL.Value);

            security.SetMarketPrice(new TradeBar {
                Value = 250
            });

            algorithm.SetFinishedWarmingUp();

            var openOrderRequest = new SubmitOrderRequest(OrderType.Market, SecurityType.Equity, Symbols.AAPL, 100, 0, 0, DateTime.MinValue, "");

            openOrderRequest.SetOrderId(1);
            var openOrderTicket = new OrderTicket(algorithm.Transactions, openOrderRequest);

            openOrderTicket.AddOrderEvent(new OrderEvent(1, Symbols.AAPL, DateTime.MinValue, OrderStatus.PartiallyFilled, OrderDirection.Buy, 250, 70, OrderFee.Zero));

            var orderProcessor = new Mock <IOrderProcessor>();

            orderProcessor.Setup(m => m.Process(It.IsAny <SubmitOrderRequest>()))
            .Returns((SubmitOrderRequest request) => new OrderTicket(algorithm.Transactions, request))
            .Callback((SubmitOrderRequest request) => actualOrdersSubmitted.Add(request));
            orderProcessor.Setup(m => m.GetOpenOrders(It.IsAny <Func <Order, bool> >()))
            .Returns(new List <Order> {
                new MarketOrder(Symbols.AAPL, 100, DateTime.MinValue)
            });
            orderProcessor.Setup(m => m.GetOpenOrderTickets(It.IsAny <Func <OrderTicket, bool> >()))
            .Returns(new List <OrderTicket> {
                openOrderTicket
            });
            algorithm.Transactions.SetOrderProcessor(orderProcessor.Object);

            var model = GetExecutionModel(language);

            algorithm.SetExecution(model);

            var changes = new SecurityChanges(Enumerable.Empty <Security>(), Enumerable.Empty <Security>());

            model.OnSecuritiesChanged(algorithm, changes);

            var targets = new IPortfolioTarget[] { new PortfolioTarget(Symbols.AAPL, 80) };

            model.Execute(algorithm, targets);

            Assert.AreEqual(1, actualOrdersSubmitted.Count);

            // Remaining quantity for partially filled order = 100 - 70 = 30
            // Quantity submitted = 80 - 30 = 50
            Assert.AreEqual(50, actualOrdersSubmitted.Sum(x => x.Quantity));
        }
Пример #3
0
        /// <summary>
        /// Turn order into an order ticket
        /// </summary>
        /// <param name="order">The <see cref="Order"/> being converted</param>
        /// <param name="transactionManager">The transaction manager, <see cref="SecurityTransactionManager"/></param>
        /// <returns></returns>
        public static OrderTicket ToOrderTicket(this Order order, SecurityTransactionManager transactionManager)
        {
            var limitPrice = 0m;
            var stopPrice  = 0m;

            switch (order.Type)
            {
            case OrderType.Limit:
                var limitOrder = order as LimitOrder;
                limitPrice = limitOrder.LimitPrice;
                break;

            case OrderType.StopMarket:
                var stopMarketOrder = order as StopMarketOrder;
                stopPrice = stopMarketOrder.StopPrice;
                break;

            case OrderType.StopLimit:
                var stopLimitOrder = order as StopLimitOrder;
                stopPrice  = stopLimitOrder.StopPrice;
                limitPrice = stopLimitOrder.LimitPrice;
                break;

            case OrderType.OptionExercise:
            case OrderType.Market:
            case OrderType.MarketOnOpen:
            case OrderType.MarketOnClose:
                limitPrice = order.Price;
                stopPrice  = order.Price;
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            var submitOrderRequest = new SubmitOrderRequest(order.Type,
                                                            order.SecurityType,
                                                            order.Symbol,
                                                            order.Quantity,
                                                            stopPrice,
                                                            limitPrice,
                                                            order.Time,
                                                            order.Tag,
                                                            order.Properties);

            submitOrderRequest.SetOrderId(order.Id);

            return(new OrderTicket(transactionManager, submitOrderRequest));
        }
        public void TestInvalidWarmingUp()
        {
            var orderRequest = new SubmitOrderRequest(OrderType.Limit, SecurityType.Equity, Symbols.AAPL, 1000, 0, 1.11m, DateTime.Now, "Pepe");

            orderRequest.SetOrderId(orderRequest.OrderId);
            var ticket = OrderTicket.InvalidWarmingUp(null, orderRequest);

            Assert.AreEqual(ticket.OrderId, orderRequest.OrderId);
            Assert.AreEqual(ticket.Quantity, 1000);
            Assert.AreEqual(ticket.Tag, "Pepe");
            Assert.AreEqual(ticket.Status, OrderStatus.Invalid);
            Assert.AreEqual(ticket.OrderType, OrderType.Limit);
            Assert.AreEqual(ticket.SecurityType, SecurityType.Equity);
            Assert.AreEqual(ticket.Symbol, Symbols.AAPL);
            Assert.AreEqual(ticket.SubmitRequest, orderRequest);
            Assert.AreEqual(ticket.SubmitRequest.Status, OrderRequestStatus.Error);
            Assert.AreEqual(ticket.SubmitRequest.OrderId, orderRequest.OrderId);
            Assert.AreEqual(ticket.SubmitRequest.Quantity, 1000);
            Assert.AreEqual(ticket.SubmitRequest.Tag, "Pepe");
        }
Пример #5
0
        public void GenerateMarginCallOrderTests()
        {
            const int     quantity       = 1000;
            const decimal leverage       = 1m;
            var           orderProcessor = new FakeOrderProcessor();
            var           portfolio      = GetPortfolio(orderProcessor, quantity);

            portfolio.MarginCallModel = new DefaultMarginCallModel(portfolio, null);

            var security = GetSecurity(Symbols.AAPL);

            portfolio.Securities.Add(security);

            var           time     = DateTime.Now;
            const decimal buyPrice = 1m;

            security.SetMarketPrice(new Tick(time, Symbols.AAPL, buyPrice, buyPrice));

            var order = new MarketOrder(Symbols.AAPL, quantity, time)
            {
                Price = buyPrice
            };
            var fill = new OrderEvent(order, DateTime.UtcNow, 0)
            {
                FillPrice = buyPrice, 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));
            Assert.AreEqual(portfolio.Cash, fill.FillPrice * fill.FillQuantity);

            portfolio.ProcessFill(fill);

            Assert.AreEqual(0, portfolio.MarginRemaining);
            Assert.AreEqual(quantity, portfolio.TotalMarginUsed);
            Assert.AreEqual(quantity, portfolio.TotalPortfolioValue);

            // we shouldn't be able to place a trader
            var newOrder = new MarketOrder(Symbols.AAPL, 1, time.AddSeconds(1))
            {
                Price = buyPrice
            };
            var hasSufficientBuyingPower = security.BuyingPowerModel.HasSufficientBuyingPowerForOrder(portfolio, security, newOrder).IsSufficient;

            Assert.IsFalse(hasSufficientBuyingPower);

            // now the stock doubles, so we should have margin remaining
            time = time.AddDays(1);
            const decimal highPrice = buyPrice * 2;

            security.SetMarketPrice(new Tick(time, Symbols.AAPL, highPrice, highPrice));

            Assert.AreEqual(quantity, portfolio.MarginRemaining);
            Assert.AreEqual(quantity, portfolio.TotalMarginUsed);
            Assert.AreEqual(quantity * 2, portfolio.TotalPortfolioValue);

            // we shouldn't be able to place a trader
            var anotherOrder = new MarketOrder(Symbols.AAPL, 1, time.AddSeconds(1))
            {
                Price = highPrice
            };

            hasSufficientBuyingPower = security.BuyingPowerModel.HasSufficientBuyingPowerForOrder(portfolio, security, anotherOrder).IsSufficient;
            Assert.IsTrue(hasSufficientBuyingPower);

            // now the stock plummets, so we should have negative margin remaining
            time = time.AddDays(1);
            const decimal lowPrice = buyPrice / 2;

            security.SetMarketPrice(new Tick(time, Symbols.AAPL, lowPrice, lowPrice));

            Assert.AreEqual(-quantity / 2m, portfolio.MarginRemaining);
            Assert.AreEqual(quantity, portfolio.TotalMarginUsed);
            Assert.AreEqual(quantity / 2m, portfolio.TotalPortfolioValue);

            // this would not cause a margin call due to leverage = 1
            bool issueMarginCallWarning;
            var  marginCallOrders = portfolio.MarginCallModel.GetMarginCallOrders(out issueMarginCallWarning);

            Assert.IsFalse(issueMarginCallWarning);
            Assert.AreEqual(0, marginCallOrders.Count);

            // now change the leverage to test margin call warning and margin call logic
            security.SetLeverage(leverage * 2);

            // Stock price increase by minimum variation
            const decimal newPrice = lowPrice + 0.01m;

            security.SetMarketPrice(new Tick(time, Symbols.AAPL, newPrice, newPrice));

            // this would not cause a margin call, only a margin call warning
            marginCallOrders = portfolio.MarginCallModel.GetMarginCallOrders(out issueMarginCallWarning);
            Assert.IsTrue(issueMarginCallWarning);
            Assert.AreEqual(0, marginCallOrders.Count);

            // Price drops again to previous low, margin call orders will be issued
            security.SetMarketPrice(new Tick(time, Symbols.AAPL, lowPrice, lowPrice));

            order = new MarketOrder(Symbols.AAPL, quantity, time)
            {
                Price = buyPrice
            };
            fill = new OrderEvent(order, DateTime.UtcNow, 0)
            {
                FillPrice = buyPrice, FillQuantity = quantity
            };
            portfolio.ProcessFill(fill);

            Assert.AreEqual(0, portfolio.TotalPortfolioValue);

            marginCallOrders = portfolio.MarginCallModel.GetMarginCallOrders(out issueMarginCallWarning);
            Assert.IsTrue(issueMarginCallWarning);
            Assert.AreEqual(1, marginCallOrders.Count);
        }
Пример #6
0
        public void SendingNewOrderFromOnOrderEvent()
        {
            //Initializes the transaction handler
            var transactionHandler = new BacktestingTransactionHandler();
            var brokerage          = new BacktestingBrokerage(_algorithm);

            transactionHandler.Initialize(_algorithm, brokerage, new BacktestingResultHandler());

            // Creates a market order
            var security = _algorithm.Securities[Ticker];
            var price    = 1.12m;

            security.SetMarketPrice(new Tick(DateTime.UtcNow.AddDays(-1), security.Symbol, price, price, price));
            var orderRequest  = new SubmitOrderRequest(OrderType.Market, security.Type, security.Symbol, 1000, 0, 0, 0, DateTime.UtcNow, "");
            var orderRequest2 = new SubmitOrderRequest(OrderType.Market, security.Type, security.Symbol, -1000, 0, 0, 0, DateTime.UtcNow, "");

            orderRequest.SetOrderId(1);
            orderRequest2.SetOrderId(2);

            // Mock the the order processor
            var orderProcessorMock = new Mock <IOrderProcessor>();

            orderProcessorMock.Setup(m => m.GetOrderTicket(It.Is <int>(i => i == 1))).Returns(new OrderTicket(_algorithm.Transactions, orderRequest));
            orderProcessorMock.Setup(m => m.GetOrderTicket(It.Is <int>(i => i == 2))).Returns(new OrderTicket(_algorithm.Transactions, orderRequest2));
            _algorithm.Transactions.SetOrderProcessor(orderProcessorMock.Object);

            var orderEventCalls = 0;

            brokerage.OrderStatusChanged += (sender, orderEvent) =>
            {
                orderEventCalls++;
                switch (orderEventCalls)
                {
                case 1:
                    Assert.AreEqual(1, orderEvent.OrderId);
                    Assert.AreEqual(OrderStatus.Submitted, orderEvent.Status);

                    // we send a new order request
                    var ticket2 = transactionHandler.Process(orderRequest2);
                    break;

                case 2:
                    Assert.AreEqual(2, orderEvent.OrderId);
                    Assert.AreEqual(OrderStatus.Submitted, orderEvent.Status);
                    break;

                case 3:
                    Assert.AreEqual(1, orderEvent.OrderId);
                    Assert.AreEqual(OrderStatus.Filled, orderEvent.Status);
                    break;

                case 4:
                    Assert.AreEqual(2, orderEvent.OrderId);
                    Assert.AreEqual(OrderStatus.Filled, orderEvent.Status);
                    break;
                }
                Log.Trace($"{orderEvent}");
            };

            var ticket = transactionHandler.Process(orderRequest);

            Assert.IsTrue(orderRequest.Response.IsProcessed);
            Assert.IsTrue(orderRequest.Response.IsSuccess);
            Assert.AreEqual(OrderRequestStatus.Processed, orderRequest.Status);
            Assert.IsTrue(orderRequest2.Response.IsProcessed);
            Assert.IsTrue(orderRequest2.Response.IsSuccess);
            Assert.AreEqual(OrderRequestStatus.Processed, orderRequest2.Status);

            var order1 = transactionHandler.GetOrderById(1);

            Assert.AreEqual(OrderStatus.Filled, order1.Status);
            var order2 = transactionHandler.GetOrderById(2);

            Assert.AreEqual(OrderStatus.Filled, order2.Status);

            // 2 submitted and 2 filled
            Assert.AreEqual(4, orderEventCalls);
        }
        public void OrdersAreSubmittedImmediatelyForTargetsToExecute(
            Language language,
            double[] historicalPrices,
            decimal openOrdersQuantity,
            int expectedOrdersSubmitted,
            decimal expectedTotalQuantity)
        {
            var actualOrdersSubmitted = new List <SubmitOrderRequest>();

            var time            = new DateTime(2018, 8, 2, 16, 0, 0);
            var historyProvider = new Mock <IHistoryProvider>();

            historyProvider.Setup(m => m.GetHistory(It.IsAny <IEnumerable <HistoryRequest> >(), It.IsAny <DateTimeZone>()))
            .Returns(historicalPrices.Select((x, i) =>
                                             new Slice(time.AddMinutes(i),
                                                       new List <BaseData>
            {
                new TradeBar
                {
                    Time   = time.AddMinutes(i),
                    Symbol = Symbols.AAPL,
                    Open   = Convert.ToDecimal(x),
                    High   = Convert.ToDecimal(x),
                    Low    = Convert.ToDecimal(x),
                    Close  = Convert.ToDecimal(x),
                    Volume = 100m
                }
            })));

            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            algorithm.SetPandasConverter();
            algorithm.SetHistoryProvider(historyProvider.Object);
            algorithm.SetDateTime(time.AddMinutes(5));

            var security = algorithm.AddEquity(Symbols.AAPL.Value);

            security.SetMarketPrice(new TradeBar {
                Value = 250
            });

            algorithm.SetFinishedWarmingUp();

            var openOrderRequest = new SubmitOrderRequest(OrderType.Market, SecurityType.Equity, Symbols.AAPL, openOrdersQuantity, 0, 0, DateTime.MinValue, "");

            openOrderRequest.SetOrderId(1);
            var openOrderTicket = new OrderTicket(algorithm.Transactions, openOrderRequest);

            var orderProcessor = new Mock <IOrderProcessor>();

            orderProcessor.Setup(m => m.Process(It.IsAny <SubmitOrderRequest>()))
            .Returns((SubmitOrderRequest request) => new OrderTicket(algorithm.Transactions, request))
            .Callback((OrderRequest request) => actualOrdersSubmitted.Add((SubmitOrderRequest)request));
            orderProcessor.Setup(m => m.GetOpenOrders(It.IsAny <Func <Order, bool> >()))
            .Returns(new List <Order> {
                new MarketOrder(Symbols.AAPL, openOrdersQuantity, DateTime.MinValue)
            });
            orderProcessor.Setup(m => m.GetOpenOrderTickets(It.IsAny <Func <OrderTicket, bool> >()))
            .Returns(new List <OrderTicket> {
                openOrderTicket
            });
            algorithm.Transactions.SetOrderProcessor(orderProcessor.Object);

            var model = GetExecutionModel(language);

            algorithm.SetExecution(model);

            var changes = SecurityChangesTests.CreateNonInternal(new[] { security }, Enumerable.Empty <Security>());

            model.OnSecuritiesChanged(algorithm, changes);

            var targets = new IPortfolioTarget[] { new PortfolioTarget(Symbols.AAPL, 10) };

            model.Execute(algorithm, targets);

            Assert.AreEqual(expectedOrdersSubmitted, actualOrdersSubmitted.Count);
            Assert.AreEqual(expectedTotalQuantity, actualOrdersSubmitted.Sum(x => x.Quantity));

            if (actualOrdersSubmitted.Count == 1)
            {
                var request = actualOrdersSubmitted[0];
                Assert.AreEqual(expectedTotalQuantity, request.Quantity);
                Assert.AreEqual(algorithm.UtcTime, request.Time);
            }
        }
        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);
        }
        public void MarginComputesProperlyWithMultipleSecurities()
        {
            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(1000);
            portfolio.CashBook.Add("EUR", 1000, 1.1m);
            portfolio.CashBook.Add("GBP", -1000, 2.0m);

            var eurCash = portfolio.CashBook["EUR"];
            var gbpCash = portfolio.CashBook["GBP"];
            var usdCash = portfolio.CashBook["USD"];

            var time    = DateTime.Now;
            var config1 = CreateTradeBarDataConfig(SecurityType.Equity, Symbols.AAPL);

            securities.Add(new Security(SecurityExchangeHours, config1, new Cash(CashBook.AccountCurrency, 0, 1m), SymbolProperties.GetDefault(CashBook.AccountCurrency)));
            securities[Symbols.AAPL].SetLeverage(2m);
            securities[Symbols.AAPL].Holdings.SetHoldings(100, 100);
            securities[Symbols.AAPL].SetMarketPrice(new TradeBar {
                Time = time, Value = 100
            });
            //Console.WriteLine("AAPL TMU: " + securities[Symbols.AAPL].MarginModel.GetMaintenanceMargin(securities[Symbols.AAPL]));
            //Console.WriteLine("AAPL Value: " + securities[Symbols.AAPL].Holdings.HoldingsValue);

            //Console.WriteLine();

            var config2 = CreateTradeBarDataConfig(SecurityType.Forex, Symbols.EURUSD);

            securities.Add(new QuantConnect.Securities.Forex.Forex(SecurityExchangeHours, usdCash, config2, SymbolProperties.GetDefault(CashBook.AccountCurrency)));
            securities[Symbols.EURUSD].SetLeverage(100m);
            securities[Symbols.EURUSD].Holdings.SetHoldings(1.1m, 1000);
            securities[Symbols.EURUSD].SetMarketPrice(new TradeBar {
                Time = time, Value = 1.1m
            });
            //Console.WriteLine("EURUSD TMU: " + securities[Symbols.EURUSD].MarginModel.GetMaintenanceMargin(securities[Symbols.EURUSD]));
            //Console.WriteLine("EURUSD Value: " + securities[Symbols.EURUSD].Holdings.HoldingsValue);

            //Console.WriteLine();

            var config3 = CreateTradeBarDataConfig(SecurityType.Forex, Symbols.EURGBP);

            securities.Add(new QuantConnect.Securities.Forex.Forex(SecurityExchangeHours, gbpCash, config3, SymbolProperties.GetDefault(gbpCash.Symbol)));
            securities[Symbols.EURGBP].SetLeverage(100m);
            securities[Symbols.EURGBP].Holdings.SetHoldings(1m, 1000);
            securities[Symbols.EURGBP].SetMarketPrice(new TradeBar {
                Time = time, Value = 1m
            });
            //Console.WriteLine("EURGBP TMU: " + securities[Symbols.EURGBP].MarginModel.GetMaintenanceMargin(securities[Symbols.EURGBP]));
            //Console.WriteLine("EURGBP Value: " + securities[Symbols.EURGBP].Holdings.HoldingsValue);

            //Console.WriteLine();

            //Console.WriteLine(portfolio.CashBook["USD"]);
            //Console.WriteLine(portfolio.CashBook["EUR"]);
            //Console.WriteLine(portfolio.CashBook["GBP"]);
            //Console.WriteLine("CashBook: " + portfolio.CashBook.TotalValueInAccountCurrency);

            //Console.WriteLine();

            //Console.WriteLine("Total Margin Used: " + portfolio.TotalMarginUsed);
            //Console.WriteLine("Total Free Margin: " + portfolio.MarginRemaining);
            //Console.WriteLine("Total Portfolio Value: " + portfolio.TotalPortfolioValue);


            var acceptedOrder = new MarketOrder(Symbols.AAPL, 101, DateTime.Now)
            {
                Price = 100
            };

            orderProcessor.AddOrder(acceptedOrder);
            var request = new SubmitOrderRequest(OrderType.Market, acceptedOrder.SecurityType, acceptedOrder.Symbol, acceptedOrder.Quantity, 0, 0, acceptedOrder.Time, null);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(null, request));
            var sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, acceptedOrder);

            Assert.IsTrue(sufficientCapital);

            var rejectedOrder = new MarketOrder(Symbols.AAPL, 102, DateTime.Now)
            {
                Price = 100
            };

            sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, rejectedOrder);
            Assert.IsFalse(sufficientCapital);
        }
        public void ComputeMarginProperlyAsSecurityPriceFluctuates()
        {
            const decimal leverage       = 1m;
            const int     quantity       = (int)(1000 * 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(quantity);

            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 buyPrice = 1m;

            security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, buyPrice, buyPrice, buyPrice, buyPrice, 1));

            var order = new MarketOrder(Symbols.AAPL, quantity, time)
            {
                Price = buyPrice
            };
            var fill = new OrderEvent(order, DateTime.UtcNow, 0)
            {
                FillPrice = buyPrice, 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));
            Assert.AreEqual(portfolio.CashBook["USD"].Amount, fill.FillPrice * fill.FillQuantity);

            portfolio.ProcessFill(fill);

            Assert.AreEqual(0, portfolio.MarginRemaining);
            Assert.AreEqual(quantity, portfolio.TotalMarginUsed);
            Assert.AreEqual(quantity, portfolio.TotalPortfolioValue);

            // we shouldn't be able to place a trader
            var newOrder = new MarketOrder(Symbols.AAPL, 1, time.AddSeconds(1))
            {
                Price = buyPrice
            };
            bool sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, newOrder);

            Assert.IsFalse(sufficientCapital);

            // now the stock doubles, so we should have margin remaining

            time = time.AddDays(1);
            const decimal highPrice = buyPrice * 2;

            security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, highPrice, highPrice, highPrice, highPrice, 1));

            Assert.AreEqual(quantity, portfolio.MarginRemaining);
            Assert.AreEqual(quantity, portfolio.TotalMarginUsed);
            Assert.AreEqual(quantity * 2, portfolio.TotalPortfolioValue);

            // we shouldn't be able to place a trader
            var anotherOrder = new MarketOrder(Symbols.AAPL, 1, time.AddSeconds(1))
            {
                Price = highPrice
            };

            sufficientCapital = transactions.GetSufficientCapitalForOrder(portfolio, anotherOrder);
            Assert.IsTrue(sufficientCapital);

            // now the stock plummets, so we should have negative margin remaining

            time = time.AddDays(1);
            const decimal lowPrice = buyPrice / 2;

            security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, lowPrice, lowPrice, lowPrice, lowPrice, 1));

            Assert.AreEqual(-quantity / 2m, portfolio.MarginRemaining);
            Assert.AreEqual(quantity, portfolio.TotalMarginUsed);
            Assert.AreEqual(quantity / 2m, portfolio.TotalPortfolioValue);


            // this would not cause a margin call due to leverage = 1
            bool issueMarginCallWarning;
            var  marginCallOrders = portfolio.ScanForMarginCall(out issueMarginCallWarning);

            Assert.IsFalse(issueMarginCallWarning);
            Assert.AreEqual(0, marginCallOrders.Count);

            // now change the leverage to test margin call warning and margin call logic
            security.SetLeverage(leverage * 2);

            // Stock price increase by minimum variation
            const decimal newPrice = lowPrice + 0.01m;

            security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, newPrice, newPrice, newPrice, newPrice, 1));

            // this would not cause a margin call, only a margin call warning
            marginCallOrders = portfolio.ScanForMarginCall(out issueMarginCallWarning);
            Assert.IsTrue(issueMarginCallWarning);
            Assert.AreEqual(0, marginCallOrders.Count);

            // Price drops again to previous low, margin call orders will be issued
            security.SetMarketPrice(new TradeBar(time, Symbols.AAPL, lowPrice, lowPrice, lowPrice, lowPrice, 1));

            order = new MarketOrder(Symbols.AAPL, quantity, time)
            {
                Price = buyPrice
            };
            fill = new OrderEvent(order, DateTime.UtcNow, 0)
            {
                FillPrice = buyPrice, FillQuantity = quantity
            };

            portfolio.ProcessFill(fill);

            Assert.AreEqual(0, portfolio.TotalPortfolioValue);

            marginCallOrders = portfolio.ScanForMarginCall(out issueMarginCallWarning);
            Assert.IsTrue(issueMarginCallWarning);
            Assert.AreNotEqual(0, marginCallOrders.Count);
            Assert.AreEqual(-security.Holdings.Quantity, marginCallOrders[0].Quantity); // we bought twice
            Assert.GreaterOrEqual(-portfolio.MarginRemaining, security.Price * marginCallOrders[0].Quantity);
        }