public void ReducesPositionWhenMarginAboveTargetWhenNegativeFreeMargin(decimal holdings)
        {
            var algorithm = GetAlgorithm();
            var security  = InitAndGetSecurity(algorithm, 0);
            var model     = new SecurityMarginModel();

            security.Holdings.SetHoldings(security.Price, holdings);

            var security2 = InitAndGetSecurity(algorithm, 0, symbol: "AAPL");

            // eat up all our TPV
            security2.Holdings.SetHoldings(security.Price, (algorithm.Portfolio.TotalPortfolioValue / security.Price) * 2);

            var currentSignedUsedMargin = model.GetInitialMarginRequirement(security, security.Holdings.Quantity);
            var totalPortfolioValue     = algorithm.Portfolio.TotalPortfolioValue;
            var sign = Math.Sign(security.Holdings.Quantity) == 0 ? 1 : Math.Sign(security.Holdings.Quantity);
            // we inverse the sign here so that new target is less than current, we expect a reduction
            var newTarget = currentSignedUsedMargin / (totalPortfolioValue) + 0.00001m * sign * -1;

            Assert.IsTrue(0 > algorithm.Portfolio.MarginRemaining);
            var result = model.GetMaximumOrderQuantityForTargetBuyingPower(algorithm.Portfolio, security, newTarget, 0);

            // Reproduces GH issue #5763 a small Reduction in the target should reduce the position
            Assert.AreEqual(1m * sign * -1, result.Quantity);
            Assert.IsFalse(result.IsError);
        }
        public void ReducesPositionWhenMarginAboveTargetBasedOnSetting(decimal holdings, decimal minimumOrderMarginPortfolioPercentage)
        {
            var algorithm = GetAlgorithm();
            var security  = InitAndGetSecurity(algorithm, 0);
            var model     = new SecurityMarginModel();

            security.Holdings.SetHoldings(security.Price, holdings);

            var currentSignedUsedMargin = model.GetInitialMarginRequirement(security, security.Holdings.Quantity);
            var totalPortfolioValue     = algorithm.Portfolio.TotalPortfolioValue;
            var sign = Math.Sign(security.Holdings.Quantity) == 0 ? 1 : Math.Sign(security.Holdings.Quantity);
            // we inverse the sign here so that new target is less than current, we expect a reduction
            var newTarget = currentSignedUsedMargin / (totalPortfolioValue) + 0.00001m * sign * -1;

            var result = model.GetMaximumOrderQuantityForTargetBuyingPower(algorithm.Portfolio, security, newTarget, minimumOrderMarginPortfolioPercentage);

            if (minimumOrderMarginPortfolioPercentage == 0)
            {
                // Reproduces GH issue #5763 a small Reduction in the target should reduce the position
                Assert.AreEqual(1m * sign * -1, result.Quantity);
                Assert.IsFalse(result.IsError);
            }
            else
            {
                Assert.AreEqual(0, result.Quantity);
                Assert.IsFalse(result.IsError);
            }
        }
        public void ReturnsMinimumOrderValueReason(decimal holdings)
        {
            var algorithm = GetAlgorithm();
            var security  = InitAndGetSecurity(algorithm, 0);
            var model     = new SecurityMarginModel();

            security.Holdings.SetHoldings(security.Price, holdings);
            var currentSignedUsedMargin = model.GetInitialMarginRequirement(security, security.Holdings.Quantity);
            var totalPortfolioValue     = algorithm.Portfolio.TotalPortfolioValue;
            var sign = Math.Sign(security.Holdings.Quantity) == 0 ? 1 : Math.Sign(security.Holdings.Quantity);
            // we increase it slightly, should not trigger a new order because it's increasing final margin usage, rounds down
            var newTarget = currentSignedUsedMargin / (totalPortfolioValue) + 0.00001m * sign;

            var result = model.GetMaximumOrderQuantityForTargetBuyingPower(algorithm.Portfolio, security, newTarget, 0);

            Assert.AreEqual(0m, result.Quantity);
            Assert.IsFalse(result.IsError);
            Assert.IsTrue(result.Reason.Contains("The order quantity is less than the lot size of", StringComparison.InvariantCultureIgnoreCase));
        }