protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider)
        {
            var restClient      = new RestClient("https://api.pro.coinbase.com");
            var webSocketClient = new WebSocketClientWrapper();

            var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, TimeZones.NewYork))
            {
                { Symbol, CreateSecurity(Symbol) }
            };

            var transactions = new SecurityTransactionManager(null, securities);

            transactions.SetOrderProcessor(new FakeOrderProcessor());

            var algorithm = new Mock <IAlgorithm>();

            algorithm.Setup(a => a.Transactions).Returns(transactions);
            algorithm.Setup(a => a.BrokerageModel).Returns(new GDAXBrokerageModel());
            algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions));
            algorithm.Setup(a => a.Securities).Returns(securities);

            var priceProvider = new Mock <IPriceProvider>();

            priceProvider.Setup(a => a.GetLastPrice(It.IsAny <Symbol>())).Returns(1.234m);

            var aggregator = new AggregationManager();

            return(new GDAXBrokerage(Config.Get("gdax-url", "wss://ws-feed.pro.coinbase.com"), webSocketClient, restClient,
                                     Config.Get("gdax-api-key"), Config.Get("gdax-api-secret"), Config.Get("gdax-passphrase"), algorithm.Object,
                                     priceProvider.Object, aggregator));
        }
        /// <summary>
        /// Creates the brokerage under test and connects it
        /// </summary>
        /// <param name="orderProvider"></param>
        /// <param name="securityProvider"></param>
        /// <returns></returns>
        protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider)
        {
            var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, TimeZones.NewYork))
            {
                { Symbol, CreateSecurity(Symbol) }
            };

            var transactions = new SecurityTransactionManager(null, securities);

            transactions.SetOrderProcessor(new FakeOrderProcessor());

            var algorithm = new Mock <IAlgorithm>();

            algorithm.Setup(a => a.Transactions).Returns(transactions);
            algorithm.Setup(a => a.BrokerageModel).Returns(new BitfinexBrokerageModel());
            algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions));

            var priceProvider = new Mock <IPriceProvider>();

            priceProvider.Setup(a => a.GetLastPrice(It.IsAny <Symbol>())).Returns(1.234m);

            return(new BitfinexBrokerage(
                       Config.Get("bitfinex-api-key"),
                       Config.Get("bitfinex-api-secret"),
                       algorithm.Object,
                       priceProvider.Object,
                       new AggregationManager()
                       ));
        }
        /// <summary>
        /// Creates the brokerage under test and connects it
        /// </summary>
        /// <param name="orderProvider"></param>
        /// <param name="securityProvider"></param>
        /// <returns></returns>
        protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider)
        {
            var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, new[] { TimeZones.NewYork }));

            securities.Add(Symbol, CreateSecurity(Symbol));
            var transactions = new SecurityTransactionManager(null, securities);

            transactions.SetOrderProcessor(new FakeOrderProcessor());

            var algorithm = new Mock <IAlgorithm>();

            algorithm.Setup(a => a.Transactions).Returns(transactions);
            algorithm.Setup(a => a.BrokerageModel).Returns(new BitfinexBrokerageModel(AccountType.Margin));
            algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions));

            var priceProvider = new Mock <IPriceProvider>();

            priceProvider.Setup(a => a.GetLastPrice(It.IsAny <Symbol>())).Returns(1.234m);

            return(new BitfinexBrokerage(
                       Config.Get("bitfinex-url", "wss://api.bitfinex.com/ws"),
                       Config.Get("bitfinex-rest", "https://api.bitfinex.com"),
                       Config.Get("bitfinex-api-key"),
                       Config.Get("bitfinex-api-secret"),
                       algorithm.Object,
                       priceProvider.Object
                       ));
        }
示例#4
0
        /// <summary>
        /// Creates the brokerage under test
        /// </summary>
        /// <returns>A connected brokerage instance</returns>
        protected IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider)
        {
            var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, TimeZones.Kolkata))
            {
                { Symbol, CreateSecurity(Symbol) }
            };

            var transactions = new SecurityTransactionManager(null, securities);

            transactions.SetOrderProcessor(new FakeOrderProcessor());

            var algorithm = new Mock <IAlgorithm>();

            algorithm.Setup(a => a.Transactions).Returns(transactions);
            algorithm.Setup(a => a.BrokerageModel).Returns(new ZerodhaBrokerageModel());
            algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions));

            var accessToken    = Config.Get("zerodha-access-token");
            var apiKey         = Config.Get("zerodha-api-key");
            var tradingSegment = Config.Get("zerodha-trading-segment");
            var productType    = Config.Get("zerodha-product-type");
            var zerodha        = new ZerodhaBrokerage(tradingSegment, productType, apiKey, accessToken, algorithm.Object, algorithm.Object.Portfolio, new AggregationManager());

            return(zerodha);
        }
示例#5
0
        /// <summary>
        /// Creates the brokerage under test and connects it
        /// </summary>
        /// <param name="orderProvider"></param>
        /// <param name="securityProvider"></param>
        /// <returns></returns>
        protected override IBrokerage CreateBrokerage(IOrderProvider orderProvider, ISecurityProvider securityProvider)
        {
            var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, TimeZones.NewYork))
            {
                { Symbol, CreateSecurity(Symbol) }
            };

            var transactions = new SecurityTransactionManager(null, securities);

            transactions.SetOrderProcessor(new FakeOrderProcessor());

            var algorithm = new Mock <IAlgorithm>();

            algorithm.Setup(a => a.Transactions).Returns(transactions);
            algorithm.Setup(a => a.BrokerageModel).Returns(new BinanceBrokerageModel());
            algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions));

            var apiKey    = Config.Get("binance-api-key");
            var apiSecret = Config.Get("binance-api-secret");

            _binanceApi = new BinanceRestApiClient(
                new SymbolPropertiesDatabaseSymbolMapper(Market.Binance),
                algorithm.Object?.Portfolio,
                apiKey,
                apiSecret);

            return(new BinanceBrokerage(
                       apiKey,
                       apiSecret,
                       algorithm.Object,
                       new AggregationManager(),
                       null
                       ));
        }
        public void ConnectToUserDataStreamIfAlgorithmNotNullAndApiIsCreated()
        {
            var securities = new SecurityManager(new TimeKeeper(DateTime.UtcNow, TimeZones.NewYork));

            var transactions = new SecurityTransactionManager(null, securities);

            transactions.SetOrderProcessor(new FakeOrderProcessor());

            var algorithm = new Mock <IAlgorithm>();

            algorithm.Setup(a => a.Transactions).Returns(transactions);
            algorithm.Setup(a => a.BrokerageModel).Returns(new BinanceBrokerageModel());
            algorithm.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securities, transactions));

            using var brokerage = CreateBrokerage(algorithm.Object);

            Assert.True(brokerage.IsConnected);

            var _ = brokerage.GetCashBalance();

            Assert.True(brokerage.IsConnected);

            brokerage.Disconnect();

            Assert.False(brokerage.IsConnected);
        }
        public void OptimizerResultHandlerTest()
        {
            var shadow = new Wrapper();

            Type shadowType = shadow.GetType();

            var unit  = new OptimizerResultHandler(shadow);
            var flags = BindingFlags.Instance | BindingFlags.NonPublic;

            var algorithmMock              = new Mock <IAlgorithm>();
            var securityManager            = new SecurityManager(Mock.Of <ITimeKeeper>());
            var securityTransactionManager = new SecurityTransactionManager(algorithmMock.Object, securityManager);
            var orderProcessor             = new Mock <IOrderProcessor>();

            orderProcessor.Setup(o => o.GetOpenOrders(It.IsAny <Func <Order, bool> >())).Returns(new List <Order>());
            securityTransactionManager.SetOrderProcessor(orderProcessor.Object);

            algorithmMock.Setup(a => a.Portfolio).Returns(new SecurityPortfolioManager(securityManager, securityTransactionManager));

            var tradeBuilder = new Mock <ITradeBuilder>();

            tradeBuilder.Setup(t => t.ClosedTrades).Returns(new List <QuantConnect.Statistics.Trade>());
            algorithmMock.Setup(a => a.TradeBuilder).Returns(tradeBuilder.Object);

            unit.SetAlgorithm(algorithmMock.Object, 100);

            shadowType.GetProperty("Algorithm", flags).SetValue(shadow, algorithmMock.Object);

            securityTransactionManager.TransactionRecord.Add(DateTime.Now, 100);
            algorithmMock.Setup(s => s.Transactions).Returns(securityTransactionManager);

            var transactionHandler = new Mock <ITransactionHandler>();

            transactionHandler.Setup(v => v.Orders).Returns(new ConcurrentDictionary <int, Order>());
            shadowType.GetField("TransactionHandler", flags).SetValue(shadow, transactionHandler.Object);

            var startTime = shadowType.BaseType.BaseType.GetRuntimeFields().Single(s => s.Name.Contains("StartTime"));

            startTime.SetValue(shadow, DateTime.Now);

            var messagingHandler = new MessagingWrapper();

            shadowType.GetField("MessagingHandler", flags).SetValue(shadow, messagingHandler);

            unit.SendFinalResult();

            Assert.True((bool)shadowType.BaseType.GetField("ExitTriggered", flags).GetValue(shadow));
            transactionHandler.Verify(v => v.Orders);
            Assert.True(messagingHandler.SendWasCalled);

            Assert.AreEqual(20, unit.FullResults.Count());
        }
示例#8
0
        private SecurityPortfolioManager GetPortfolio(IOrderProcessor orderProcessor, int quantity)
        {
            var securities   = new SecurityManager(new TimeKeeper(DateTime.Now, new[] { TimeZones.NewYork }));
            var transactions = new SecurityTransactionManager(null, securities);

            transactions.SetOrderProcessor(orderProcessor);

            var portfolio = new SecurityPortfolioManager(securities, transactions);

            portfolio.SetCash(quantity);

            return(portfolio);
        }
        private SecurityPortfolioManager GetPortfolio(IOrderProcessor orderProcessor, int quantity, DateTime time)
        {
            var securities   = new SecurityManager(new TimeKeeper(time.ConvertToUtc(TimeZones.NewYork), TimeZones.NewYork));
            var transactions = new SecurityTransactionManager(null, securities);

            transactions.SetOrderProcessor(orderProcessor);

            var portfolio = new SecurityPortfolioManager(securities, transactions);

            portfolio.SetCash(quantity);
            portfolio.MarginCallModel = new TestDefaultMarginCallModel(portfolio, new OrderProperties());

            return(portfolio);
        }
示例#10
0
        public void OptionExercise_NonAccountCurrency()
        {
            var algorithm          = new QCAlgorithm();
            var securities         = new SecurityManager(new TimeKeeper(DateTime.Now, TimeZones.NewYork));
            var transactions       = new SecurityTransactionManager(null, securities);
            var transactionHandler = new BacktestingTransactionHandler();
            var portfolio          = new SecurityPortfolioManager(securities, transactions);

            var EUR = new Cash("EUR", 100 * 192, 10);

            portfolio.CashBook.Add("EUR", EUR);
            portfolio.SetCash("USD", 0, 1);
            algorithm.Securities = securities;
            transactionHandler.Initialize(algorithm, new BacktestingBrokerage(algorithm), _resultHandler);
            transactions.SetOrderProcessor(transactionHandler);

            securities.Add(
                Symbols.SPY,
                new Security(
                    SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork),
                    CreateTradeBarConfig(Symbols.SPY),
                    EUR,
                    SymbolProperties.GetDefault(EUR.Symbol),
                    ErrorCurrencyConverter.Instance,
                    RegisteredSecurityDataTypesProvider.Null,
                    new SecurityCache()
                    )
                );
            securities.Add(
                Symbols.SPY_C_192_Feb19_2016,
                new Option(
                    SecurityExchangeHours.AlwaysOpen(TimeZones.NewYork),
                    CreateTradeBarConfig(Symbols.SPY_C_192_Feb19_2016),
                    EUR,
                    new OptionSymbolProperties(new SymbolProperties("EUR", "EUR", 100, 0.01m, 1)),
                    ErrorCurrencyConverter.Instance,
                    RegisteredSecurityDataTypesProvider.Null
                    )
                );
            securities[Symbols.SPY_C_192_Feb19_2016].Holdings.SetHoldings(1, 1);
            securities[Symbols.SPY].SetMarketPrice(new Tick {
                Value = 200
            });

            transactions.AddOrder(new SubmitOrderRequest(OrderType.OptionExercise, SecurityType.Option, Symbols.SPY_C_192_Feb19_2016, -1, 0, 0, securities.UtcTime, ""));
            var option = (Option)securities[Symbols.SPY_C_192_Feb19_2016];
            var order  = (OptionExerciseOrder)transactions.GetOrders(x => true).First();

            option.Underlying = securities[Symbols.SPY];

            var fills = option.OptionExerciseModel.OptionExercise(option, order).ToList();

            Assert.AreEqual(2, fills.Count);
            Assert.IsFalse(fills[0].IsAssignment);
            Assert.AreEqual("Automatic Exercise", fills[0].Message);
            Assert.AreEqual("Option Exercise", fills[1].Message);

            foreach (var fill in fills)
            {
                portfolio.ProcessFill(fill);
            }

            // now we have long position in SPY with average price equal to strike
            var newUnderlyingHoldings = securities[Symbols.SPY].Holdings;

            // we added 100*192 EUR (strike price) at beginning, all consumed by exercise
            Assert.AreEqual(0, EUR.Amount);
            Assert.AreEqual(0, portfolio.CashBook["USD"].Amount);
            Assert.AreEqual(100, newUnderlyingHoldings.Quantity);
            Assert.AreEqual(192.0, newUnderlyingHoldings.AveragePrice);

            // and long call option position has disappeared
            Assert.AreEqual(0, securities[Symbols.SPY_C_192_Feb19_2016].Holdings.Quantity);
        }
        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);
        }