Exemplo n.º 1
0
 /// <summary>
 /// Provides a mechanism for derived types to add their own buying power for order checks without needing to
 /// recompute the available buying power. Implementations should return null if all checks pass and should
 /// return an instance of <see cref="HasSufficientBuyingPowerForOrderResult"/> with IsSufficient=false if it
 /// fails.
 /// </summary>
 protected virtual HasSufficientBuyingPowerForOrderResult PassesPositionGroupSpecificBuyingPowerForOrderChecks(
     HasSufficientPositionGroupBuyingPowerForOrderParameters parameters,
     decimal availableBuyingPower
     )
 {
     return(null);
 }
        /// <summary>
        /// Additionally check initial margin requirements if the algorithm only has default position groups
        /// </summary>
        protected override HasSufficientBuyingPowerForOrderResult PassesPositionGroupSpecificBuyingPowerForOrderChecks(
            HasSufficientPositionGroupBuyingPowerForOrderParameters parameters,
            decimal availableBuyingPower
            )
        {
            // only check initial margin requirements when the algorithm is only using default position groups
            if (!parameters.Portfolio.Positions.IsOnlyDefaultGroups)
            {
                return(null);
            }

            var symbol   = parameters.PositionGroup.Single().Symbol;
            var security = parameters.Portfolio.Securities[symbol];

            return(security.BuyingPowerModel.HasSufficientBuyingPowerForOrder(
                       parameters.Portfolio, security, parameters.Order
                       ));
        }
        /// <summary>
        /// Check if there is sufficient buying power for the position group to execute this order.
        /// </summary>
        /// <param name="parameters">An object containing the portfolio, the position group and the order</param>
        /// <returns>Returns buying power information for an order against a position group</returns>
        public override HasSufficientBuyingPowerForOrderResult HasSufficientBuyingPowerForOrder(
            HasSufficientPositionGroupBuyingPowerForOrderParameters parameters
            )
        {
            if (parameters.PositionGroup.Count != 1)
            {
                return(parameters.Error(
                           $"{nameof(SecurityPositionGroupBuyingPowerModel)} only supports position groups containing exactly one position."
                           ));
            }

            var position = parameters.PositionGroup.Single();
            var security = parameters.Portfolio.Securities[position.Symbol];

            return(security.BuyingPowerModel.HasSufficientBuyingPowerForOrder(
                       parameters.Portfolio, security, parameters.Order
                       ));
        }
Exemplo n.º 4
0
        /// <summary>
        /// Check if there is sufficient buying power for the position group to execute this order.
        /// </summary>
        /// <param name="parameters">An object containing the portfolio, the position group and the order</param>
        /// <returns>Returns buying power information for an order against a position group</returns>
        public virtual HasSufficientBuyingPowerForOrderResult HasSufficientBuyingPowerForOrder(
            HasSufficientPositionGroupBuyingPowerForOrderParameters parameters
            )
        {
            // The addition of position groups requires that we not only check initial margin requirements, but also
            // that we confirm that after the changes have been applied and the new groups resolved our maintenance
            // margin is still in a valid range (less than TPV). For this model, we use the security's sufficient buying
            // power impl to confirm initial margin requirements and lean heavily on GetReservedBuyingPowerImpact for
            // help with confirming that our expected maintenance margin is still less than TPV.
            //   1. Confirm we have sufficient buying power to execute the trade using security's BP model
            //   2. Confirm we pass position group specific checks
            //   3. Confirm we haven't exceeded maintenance margin limits via GetReservedBuyingPowerImpact's delta

            // 1. Confirm we meet initial margin requirements, accounting for buffer
            var availableBuyingPower = this.GetPositionGroupBuyingPower(
                parameters.Portfolio, parameters.PositionGroup, parameters.Order.Direction
                );

            // 2. Confirm we pass position group specific checks
            var result = PassesPositionGroupSpecificBuyingPowerForOrderChecks(parameters, availableBuyingPower);

            if (result?.IsSufficient == false)
            {
                return(result);
            }

            // 3. Confirm that the new groupings arising from the change doesn't make maintenance margin exceed TPV
            var args             = new ReservedBuyingPowerImpactParameters(parameters.Portfolio, parameters.PositionGroup, parameters.Order);
            var deltaBuyingPower = GetReservedBuyingPowerImpact(args).Delta;

            if (deltaBuyingPower <= availableBuyingPower)
            {
                return(parameters.Sufficient());
            }

            return(parameters.Insufficient(Invariant(
                                               $"Id: {parameters.Order.Id}, Maintenance Margin Delta: {deltaBuyingPower.Normalize()}, Free Margin: {availableBuyingPower.Value.Normalize()}"
                                               )));
        }