示例#1
0
        public void SetHoldings_Short_RoundOff()
        {
            var algo = new QCAlgorithm();

            algo.AddSecurity(SecurityType.Forex, "EURUSD");
            algo.SetCash(100000);
            algo.SetBrokerageModel(BrokerageName.FxcmBrokerage);
            algo.Securities[Symbols.EURUSD].TransactionModel = new ConstantFeeTransactionModel(0);
            Security eurusd = algo.Securities[Symbols.EURUSD];

            // Set Price to $26
            Update(eurusd, 26);
            // So -100000/26 = -3846, After Rounding off becomes -3000
            var actual = algo.CalculateOrderQuantity(Symbols.EURUSD, -1m);

            Assert.AreEqual(-3000m, actual);

            var btcusd = algo.AddCrypto("BTCUSD", market: Market.GDAX);

            btcusd.TransactionModel = new ConstantFeeTransactionModel(0);
            // Set Price to $26
            Update(btcusd, 26);
            // So -100000/26 = 3846.153846153846, After Rounding off becomes -3846.15384615, since lot size is 0.00000001
            actual = algo.CalculateOrderQuantity(Symbols.BTCUSD, -1m);
            Assert.AreEqual(-3846.15384615m, actual);
        }
        public void SetBuyingPowerModelSuccess(bool isChild)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            algorithm.SetDateTime(new DateTime(2018, 8, 20, 15, 0, 0));
            algorithm.Transactions.SetOrderProcessor(new FakeOrderProcessor());

            var spy = algorithm.AddEquity("SPY", Resolution.Daily);

            spy.SetMarketPrice(new Tick(algorithm.Time, Symbols.SPY, 100m, 100m));

            // Test two custom buying power models.
            // The first inherits from C# SecurityMarginModel and the other is 100% python
            var code = isChild
                ? CreateCustomBuyingPowerModelFromSecurityMarginModelCode()
                : CreateCustomBuyingPowerModelCode();

            spy.SetBuyingPowerModel(CreateCustomBuyingPowerModel(code));
            Assert.IsAssignableFrom <BuyingPowerModelPythonWrapper>(spy.MarginModel);
            Assert.AreEqual(1, spy.MarginModel.GetLeverage(spy));

            spy.SetLeverage(2);
            Assert.AreEqual(2, spy.MarginModel.GetLeverage(spy));

            var quantity = algorithm.CalculateOrderQuantity(spy.Symbol, 1m);

            Assert.AreEqual(isChild ? 100 : 200, quantity);
        }
        public void HasSufficientBuyingPowerForOrderInvalidTargets(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            // set closed market for simpler math
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));
            Update(futureSecurity, 100, algorithm);
            var model = GetModel(futureSecurity, out _futureMarginModel, algorithm.Portfolio);

            var quantity = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);
            var request  = GetOrderRequest(futureSecurity.Symbol, quantity);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            var result = model.HasSufficientBuyingPowerForOrder(new HasSufficientBuyingPowerForOrderParameters(
                                                                    algorithm.Portfolio,
                                                                    futureSecurity,
                                                                    // we get the maximum target value 1/-1 and add a lot size it shouldn't be a valid order
                                                                    new MarketOrder(futureSecurity.Symbol, quantity + futureSecurity.SymbolProperties.LotSize * Math.Sign(quantity), DateTime.UtcNow)));

            Assert.IsFalse(result.IsSufficient);
        }
        public void ClosingSoonIntradayClosedMarketMargins(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            Update(futureSecurity, 100, algorithm);
            var localTime  = new DateTime(2020, 2, 3);
            var utcTime    = localTime.ConvertToUtc(futureSecurity.Exchange.TimeZone);
            var timeKeeper = new TimeKeeper(utcTime, futureSecurity.Exchange.TimeZone);
            var model      = GetModel(futureSecurity, out _futureMarginModel, algorithm.Portfolio);

            // this is important
            _futureMarginModel.EnableIntradayMargins = true;

            // Open market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(localTime);

            var quantity = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);
            var request  = GetOrderRequest(futureSecurity.Symbol, quantity);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, quantity, DateTime.UtcNow))).IsSufficient);

            // Closing soon market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 3, 15, 50, 0));

            Assert.IsFalse(model.HasSufficientBuyingPowerForOrder(
                               new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                              futureSecurity,
                                                                              new MarketOrder(futureSecurity.Symbol, quantity, DateTime.UtcNow))).IsSufficient);
            Assert.IsTrue(futureSecurity.Exchange.ExchangeOpen);
            Assert.IsTrue(futureSecurity.Exchange.ClosingSoon);

            // Close market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));
            Assert.IsFalse(futureSecurity.Exchange.ExchangeOpen);

            Assert.IsFalse(model.HasSufficientBuyingPowerForOrder(
                               new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                              futureSecurity,
                                                                              new MarketOrder(futureSecurity.Symbol, quantity, DateTime.UtcNow))).IsSufficient);
        }
        public void IntradayVersusOvernightMargins(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);
            var lotSize        = futureSecurity.SymbolProperties.LotSize;

            Update(futureSecurity, 100, algorithm);
            var model = GetModel(futureSecurity, out _futureMarginModel, algorithm.Portfolio);

            // Close market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));

            var quantityClosedMarket = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);

            Assert.AreEqual(quantityClosedMarket.DiscretelyRoundBy(lotSize), quantityClosedMarket,
                            "Calculated order quantity was not whole number multiple of the lot size"
                            );
            var request = GetOrderRequest(futureSecurity.Symbol, quantityClosedMarket);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, quantityClosedMarket, DateTime.UtcNow))).IsSufficient);

            var initialOvernight     = _futureMarginModel.InitialOvernightMarginRequirement;
            var maintenanceOvernight = _futureMarginModel.MaintenanceOvernightMarginRequirement;

            // Open market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 3));

            var fourtyPercentQuantity = (quantityClosedMarket * 0.4m).DiscretelyRoundBy(lotSize);

            futureSecurity.Holdings.SetHoldings(100, fourtyPercentQuantity);

            var halfQuantity = (quantityClosedMarket / 2).DiscretelyRoundBy(lotSize);

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, halfQuantity, DateTime.UtcNow))).IsSufficient);

            Assert.Greater(initialOvernight, _futureMarginModel.InitialIntradayMarginRequirement);
            Assert.Greater(maintenanceOvernight, _futureMarginModel.MaintenanceIntradayMarginRequirement);
        }
示例#6
0
        public void DefaultValueOfSetHoldingsBufferWorksCorrectly()
        {
            var algo = new QCAlgorithm();

            InitializeAndGetFakeOrderProcessor(algo);

            var actual = algo.CalculateOrderQuantity(Symbols.SPY, 1m);

            // 100000 / 20 - 1 due to fee - effect of the target being reduced because of FreePortfolioValuePercentage
            Assert.AreEqual(4986m, actual);
        }
示例#7
0
        public void SettingSetHoldingsBufferWorksCorrectly()
        {
            var algo = new QCAlgorithm();

            algo.Settings.FreePortfolioValuePercentage = 0;
            InitializeAndGetFakeOrderProcessor(algo);

            var actual = algo.CalculateOrderQuantity(Symbols.SPY, 1m);

            // 100000 / 20 - 2 due to fee =
            Assert.AreEqual(4998m, actual);
        }
        public void GetMaximumOrderQuantityForTargetBuyingPower_TwoStep(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            futureSecurity.BuyingPowerModel = GetModel(futureSecurity, out _futureMarginModel, algorithm.Portfolio);
            // set closed market for simpler math
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));
            Update(futureSecurity, 100, algorithm);
            var expectedFinalQuantity = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);

            var quantity = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target / 2);

            futureSecurity.Holdings.SetHoldings(100, quantity);
            algorithm.Portfolio.InvalidateTotalPortfolioValue();

            var quantity2 = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);

            var request = GetOrderRequest(futureSecurity.Symbol, quantity2);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            Assert.IsTrue(futureSecurity.BuyingPowerModel.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, quantity2, DateTime.UtcNow))).IsSufficient);

            // two step operation is the same as 1 step
            Assert.AreEqual(expectedFinalQuantity, quantity + quantity2);
        }
示例#9
0
        public void SetHoldings_Long_ToZero_RoundOff()
        {
            var algo = new QCAlgorithm();

            algo.AddSecurity(SecurityType.Forex, "EURUSD");
            algo.SetCash(10000);
            algo.SetBrokerageModel(BrokerageName.FxcmBrokerage);
            algo.Securities[Symbols.EURUSD].TransactionModel = new ConstantFeeTransactionModel(0);
            Security eurusd = algo.Securities[Symbols.EURUSD];

            // Set Price to $25
            Update(eurusd, 25);
            // So 10000/25 = 400, After Rounding off becomes 0
            var actual = algo.CalculateOrderQuantity(Symbols.EURUSD, 1m);

            Assert.AreEqual(0m, actual);
        }
示例#10
0
        public void SetHoldings_Short_RoundOff()
        {
            var algo = new QCAlgorithm();

            algo.AddSecurity(SecurityType.Forex, "EURUSD");
            algo.SetCash(100000);
            algo.SetBrokerageModel(BrokerageName.FxcmBrokerage);
            algo.Securities[Symbols.EURUSD].TransactionModel = new ConstantFeeTransactionModel(0);
            Security eurusd = algo.Securities[Symbols.EURUSD];

            // Set Price to $26
            Update(eurusd, 26);
            // So -100000/26 = -3846, After Rounding off becomes -3000
            var actual = algo.CalculateOrderQuantity("EURUSD", -1m);

            Assert.AreEqual(-3000m, actual);
        }
        public void IntradayVersusOvernightMargins(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            Update(futureSecurity, 100, algorithm);
            var model = futureSecurity.BuyingPowerModel as FutureMarginModel;

            // Close market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));

            var quantityClosedMarket = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);
            var request = GetOrderRequest(futureSecurity.Symbol, quantityClosedMarket);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, quantityClosedMarket, DateTime.UtcNow))).IsSufficient);

            var initialOvernight     = model.InitialOvernightMarginRequirement;
            var maintenanceOvernight = model.MaintenanceOvernightMarginRequirement;

            // Open market
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 3));

            futureSecurity.Holdings.SetHoldings(100, quantityClosedMarket * 0.4m);

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, quantityClosedMarket / 2, DateTime.UtcNow))).IsSufficient);

            Assert.Greater(initialOvernight, model.InitialIntradayMarginRequirement);
            Assert.Greater(maintenanceOvernight, model.MaintenanceIntradayMarginRequirement);
        }
        public void GetMaximumOrderQuantityForTargetBuyingPower_WithHoldingsInverseDirection(decimal target)
        {
            var algorithm = new QCAlgorithm();

            algorithm.SetFinishedWarmingUp();
            algorithm.SubscriptionManager.SetDataManager(new DataManagerStub(algorithm));
            var orderProcessor = new FakeOrderProcessor();

            algorithm.Transactions.SetOrderProcessor(orderProcessor);

            var ticker         = QuantConnect.Securities.Futures.Financials.EuroDollar;
            var futureSecurity = algorithm.AddFuture(ticker);

            // set closed market for simpler math
            futureSecurity.Exchange.SetLocalDateTimeFrontier(new DateTime(2020, 2, 1));
            futureSecurity.Holdings.SetHoldings(100, 10 * -1 * Math.Sign(target));
            Update(futureSecurity, 100, algorithm);

            var model = GetModel(futureSecurity, out _futureMarginModel, algorithm.Portfolio);

            futureSecurity.BuyingPowerModel = _futureMarginModel;

            var quantity = algorithm.CalculateOrderQuantity(futureSecurity.Symbol, target);

            var expected = (algorithm.Portfolio.TotalPortfolioValue * Math.Abs(target) + Math.Abs(model.GetInitialMarginRequirement(futureSecurity, futureSecurity.Holdings.Quantity)))
                           / _futureMarginModel.InitialOvernightMarginRequirement - 1 * Math.Abs(target); // -1 fees

            expected -= expected % futureSecurity.SymbolProperties.LotSize;
            Log.Trace($"Expected {expected}");

            Assert.AreEqual(expected * Math.Sign(target), quantity);

            var request = GetOrderRequest(futureSecurity.Symbol, quantity);

            request.SetOrderId(0);
            orderProcessor.AddTicket(new OrderTicket(algorithm.Transactions, request));

            Assert.IsTrue(model.HasSufficientBuyingPowerForOrder(
                              new HasSufficientBuyingPowerForOrderParameters(algorithm.Portfolio,
                                                                             futureSecurity,
                                                                             new MarketOrder(futureSecurity.Symbol, expected * Math.Sign(target), DateTime.UtcNow))).IsSufficient);
        }
示例#13
0
        public void Run(Position initialPosition, Position finalPosition, FeeType feeType, PriceMovement priceMovement, int leverage)
        {
            //Console.WriteLine("----------");
            //Console.WriteLine("PARAMETERS");
            //Console.WriteLine("Initial position: " + initialPosition);
            //Console.WriteLine("Final position: " + finalPosition);
            //Console.WriteLine("Fee type: " + feeType);
            //Console.WriteLine("Price movement: " + priceMovement);
            //Console.WriteLine("Leverage: " + leverage);
            //Console.WriteLine("----------");
            //Console.WriteLine();

            var algorithm = new QCAlgorithm();

            var security = algorithm.AddSecurity(_symbol.ID.SecurityType, _symbol.ID.Symbol);

            security.FeeModel = _feeModels[feeType];
            security.SetLeverage(leverage);

            algorithm.SetCash(Cash);

            Update(security, BasePrice);

            decimal        targetPercentage;
            OrderDirection orderDirection;
            MarketOrder    order;
            decimal        orderFee;
            OrderEvent     fill;
            int            orderQuantity;
            decimal        freeMargin;
            decimal        requiredMargin;

            if (initialPosition != Position.Zero)
            {
                targetPercentage = (decimal)initialPosition;
                orderDirection   = initialPosition == Position.Long ? OrderDirection.Buy : OrderDirection.Sell;
                orderQuantity    = algorithm.CalculateOrderQuantity(_symbol, targetPercentage);
                order            = new MarketOrder(_symbol, orderQuantity, DateTime.UtcNow);
                freeMargin       = algorithm.Portfolio.GetMarginRemaining(_symbol, orderDirection);
                requiredMargin   = security.MarginModel.GetInitialMarginRequiredForOrder(security, order);

                //Console.WriteLine("Current price: " + security.Price);
                //Console.WriteLine("Target percentage: " + targetPercentage);
                //Console.WriteLine("Order direction: " + orderDirection);
                //Console.WriteLine("Order quantity: " + orderQuantity);
                //Console.WriteLine("Free margin: " + freeMargin);
                //Console.WriteLine("Required margin: " + requiredMargin);
                //Console.WriteLine();

                Assert.That(Math.Abs(requiredMargin) <= freeMargin);

                orderFee = security.FeeModel.GetOrderFee(security, order);
                fill     = new OrderEvent(order, DateTime.UtcNow, orderFee)
                {
                    FillPrice = security.Price, FillQuantity = orderQuantity
                };
                algorithm.Portfolio.ProcessFill(fill);

                //Console.WriteLine("Portfolio.Cash: " + algorithm.Portfolio.Cash);
                //Console.WriteLine("Portfolio.TotalPortfolioValue: " + algorithm.Portfolio.TotalPortfolioValue);
                //Console.WriteLine();

                if (priceMovement == PriceMovement.RisingSmall)
                {
                    Update(security, HighPrice);
                }
                else if (priceMovement == PriceMovement.FallingSmall)
                {
                    Update(security, LowPrice);
                }
                else if (priceMovement == PriceMovement.RisingLarge)
                {
                    Update(security, VeryHighPrice);
                }
                else if (priceMovement == PriceMovement.FallingLarge)
                {
                    Update(security, VeryLowPrice);
                }
            }

            targetPercentage = (decimal)finalPosition;
            orderDirection   = finalPosition == Position.Long || (finalPosition == Position.Zero && initialPosition == Position.Short) ? OrderDirection.Buy : OrderDirection.Sell;
            orderQuantity    = algorithm.CalculateOrderQuantity(_symbol, targetPercentage);
            order            = new MarketOrder(_symbol, orderQuantity, DateTime.UtcNow);
            freeMargin       = algorithm.Portfolio.GetMarginRemaining(_symbol, orderDirection);
            requiredMargin   = security.MarginModel.GetInitialMarginRequiredForOrder(security, order);

            //Console.WriteLine("Current price: " + security.Price);
            //Console.WriteLine("Target percentage: " + targetPercentage);
            //Console.WriteLine("Order direction: " + orderDirection);
            //Console.WriteLine("Order quantity: " + orderQuantity);
            //Console.WriteLine("Free margin: " + freeMargin);
            //Console.WriteLine("Required margin: " + requiredMargin);
            //Console.WriteLine();

            Assert.That(Math.Abs(requiredMargin) <= freeMargin);

            orderFee = security.FeeModel.GetOrderFee(security, order);
            fill     = new OrderEvent(order, DateTime.UtcNow, orderFee)
            {
                FillPrice = security.Price, FillQuantity = orderQuantity
            };
            algorithm.Portfolio.ProcessFill(fill);

            //Console.WriteLine("Portfolio.Cash: " + algorithm.Portfolio.Cash);
            //Console.WriteLine("Portfolio.TotalPortfolioValue: " + algorithm.Portfolio.TotalPortfolioValue);
            //Console.WriteLine();
        }
 /// <summary>
 /// Calculate Alpha and Beta, the initial number of shares for each security needed to achieve a 50/50 weighting
 /// </summary>
 /// <param name="algorithm"></param>
 private void CalculateAlphaBeta(QCAlgorithm algorithm)
 {
     _alpha = algorithm.CalculateOrderQuantity(_longSymbol, 0.5);
     _beta  = algorithm.CalculateOrderQuantity(_shortSymbol, 0.5);
     algorithm.Log($"{algorithm.Time} :: Alpha: {_alpha} Beta: {_beta}");
 }
        public void Run(object[] parameters)
        {
            Position      initialPosition = (Position)parameters[0];
            Position      finalPosition   = (Position)parameters[1];
            FeeType       feeType         = (FeeType)parameters[2];
            PriceMovement priceMovement   = (PriceMovement)parameters[3];
            int           leverage        = (int)parameters[4];

            //Console.WriteLine("----------");
            //Console.WriteLine("PARAMETERS");
            //Console.WriteLine("Initial position: " + initialPosition);
            //Console.WriteLine("Final position: " + finalPosition);
            //Console.WriteLine("Fee type: " + feeType);
            //Console.WriteLine("Price movement: " + priceMovement);
            //Console.WriteLine("Leverage: " + leverage);
            //Console.WriteLine("----------");
            //Console.WriteLine();

            var algorithm = new QCAlgorithm();

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

            var security = algorithm.AddSecurity(_symbol.ID.SecurityType, _symbol.ID.Symbol);

            security.FeeModel = _feeModels[feeType];
            security.SetLeverage(leverage);

            var buyingPowerModel = new TestSecurityMarginModel(leverage);

            security.BuyingPowerModel = buyingPowerModel;

            algorithm.SetCash(Cash);

            Update(security, BasePrice);

            decimal        targetPercentage;
            OrderDirection orderDirection;
            MarketOrder    order;
            OrderFee       orderFee;
            OrderEvent     fill;
            decimal        orderQuantity;
            decimal        freeMargin;
            decimal        requiredMargin;

            if (initialPosition != Position.Zero)
            {
                targetPercentage = (decimal)initialPosition;
                orderDirection   = initialPosition == Position.Long ? OrderDirection.Buy : OrderDirection.Sell;
                orderQuantity    = algorithm.CalculateOrderQuantity(_symbol, targetPercentage);
                order            = new MarketOrder(_symbol, orderQuantity, DateTime.UtcNow);
                freeMargin       = buyingPowerModel.GetMarginRemaining(algorithm.Portfolio, security, orderDirection);
                requiredMargin   = buyingPowerModel.GetInitialMarginRequiredForOrder(
                    new InitialMarginRequiredForOrderParameters(
                        new IdentityCurrencyConverter(algorithm.Portfolio.CashBook.AccountCurrency), security, order));

                //Console.WriteLine("Current price: " + security.Price);
                //Console.WriteLine("Target percentage: " + targetPercentage);
                //Console.WriteLine("Order direction: " + orderDirection);
                //Console.WriteLine("Order quantity: " + orderQuantity);
                //Console.WriteLine("Free margin: " + freeMargin);
                //Console.WriteLine("Required margin: " + requiredMargin);
                //Console.WriteLine();

                Assert.That(Math.Abs(requiredMargin) <= freeMargin);

                orderFee = security.FeeModel.GetOrderFee(
                    new OrderFeeParameters(security, order));
                fill = new OrderEvent(order, DateTime.UtcNow, orderFee)
                {
                    FillPrice = security.Price, FillQuantity = orderQuantity
                };
                algorithm.Portfolio.ProcessFill(fill);

                //Console.WriteLine("Portfolio.Cash: " + algorithm.Portfolio.Cash);
                //Console.WriteLine("Portfolio.TotalPortfolioValue: " + algorithm.Portfolio.TotalPortfolioValue);
                //Console.WriteLine();

                if (priceMovement == PriceMovement.RisingSmall)
                {
                    Update(security, HighPrice);
                }
                else if (priceMovement == PriceMovement.FallingSmall)
                {
                    Update(security, LowPrice);
                }
                else if (priceMovement == PriceMovement.RisingLarge)
                {
                    Update(security, VeryHighPrice);
                }
                else if (priceMovement == PriceMovement.FallingLarge)
                {
                    Update(security, VeryLowPrice);
                }
            }

            targetPercentage = (decimal)finalPosition;
            orderDirection   = finalPosition == Position.Long || (finalPosition == Position.Zero && initialPosition == Position.Short) ? OrderDirection.Buy : OrderDirection.Sell;
            orderQuantity    = algorithm.CalculateOrderQuantity(_symbol, targetPercentage);
            order            = new MarketOrder(_symbol, orderQuantity, DateTime.UtcNow);
            freeMargin       = buyingPowerModel.GetMarginRemaining(algorithm.Portfolio, security, orderDirection);
            requiredMargin   = buyingPowerModel.GetInitialMarginRequiredForOrder(
                new InitialMarginRequiredForOrderParameters(
                    new IdentityCurrencyConverter(algorithm.Portfolio.CashBook.AccountCurrency), security, order));

            //Console.WriteLine("Current price: " + security.Price);
            //Console.WriteLine("Target percentage: " + targetPercentage);
            //Console.WriteLine("Order direction: " + orderDirection);
            //Console.WriteLine("Order quantity: " + orderQuantity);
            //Console.WriteLine("Free margin: " + freeMargin);
            //Console.WriteLine("Required margin: " + requiredMargin);
            //Console.WriteLine();

            Assert.That(Math.Abs(requiredMargin) <= freeMargin);

            orderFee = security.FeeModel.GetOrderFee(
                new OrderFeeParameters(security, order));
            fill = new OrderEvent(order, DateTime.UtcNow, orderFee)
            {
                FillPrice = security.Price, FillQuantity = orderQuantity
            };
            algorithm.Portfolio.ProcessFill(fill);

            //Console.WriteLine("Portfolio.Cash: " + algorithm.Portfolio.Cash);
            //Console.WriteLine("Portfolio.TotalPortfolioValue: " + algorithm.Portfolio.TotalPortfolioValue);
            //Console.WriteLine();
        }