Пример #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PositionGroupMaintenanceMarginParameters"/> class
 /// </summary>
 /// <param name="portfolio">The algorithm's portfolio manager</param>
 /// <param name="positionGroup">The position group</param>
 public PositionGroupMaintenanceMarginParameters(
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup
     )
 {
     Portfolio     = portfolio;
     PositionGroup = positionGroup;
 }
Пример #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PositionGroupInitialMarginParameters"/> class
 /// </summary>
 /// <param name="portfolio">The algorithm's portfolio manager</param>
 /// <param name="positionGroup">The position group</param>
 public PositionGroupInitialMarginParameters(
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup
     )
 {
     Portfolio     = portfolio;
     PositionGroup = positionGroup;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ReservedBuyingPowerForPositionGroupParameters"/> class
 /// </summary>
 /// <param name="portfolio">The algorithm's portfolio manager</param>
 /// <param name="positionGroup">The position group</param>
 public ReservedBuyingPowerForPositionGroupParameters(
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup
     )
 {
     Portfolio     = portfolio;
     PositionGroup = positionGroup;
 }
Пример #4
0
        /// <summary>
        /// Gets a user friendly name for the provided <paramref name="group"/>
        /// </summary>
        public static string GetUserFriendlyName(this IPositionGroup group)
        {
            if (group.Count == 1)
            {
                return(group.Single().Symbol.ToString());
            }

            return(string.Join("|", group.Select(p => p.Symbol.ToString())));
        }
 /// <summary>
 /// Computes the amount of buying power reserved by the provided position group
 /// </summary>
 public static decimal GetReservedBuyingPowerForPositionGroup(
     this IPositionGroupBuyingPowerModel model,
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup
     )
 {
     return(model.GetReservedBuyingPowerForPositionGroup(
                new ReservedBuyingPowerForPositionGroupParameters(portfolio, positionGroup)
                ).AbsoluteUsedBuyingPower);
 }
 /// <summary>
 /// The margin that must be held in order to change positions by the changes defined by the provided position group
 /// </summary>
 public static decimal GetInitialMarginRequirement(
     this IPositionGroupBuyingPowerModel model,
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup
     )
 {
     return(model.GetInitialMarginRequirement(
                new PositionGroupInitialMarginParameters(portfolio, positionGroup)
                ).Value);
 }
 /// <summary>
 /// Gets the margin currently allocated to the specified position group
 /// </summary>
 public static decimal GetMaintenanceMargin(
     this IPositionGroupBuyingPowerModel model,
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup
     )
 {
     return(model.GetMaintenanceMargin(
                new PositionGroupMaintenanceMarginParameters(portfolio, positionGroup)
                ));
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="HasSufficientPositionGroupBuyingPowerForOrderParameters"/> class
 /// </summary>
 /// <param name="portfolio">The algorithm's portfolio manager</param>
 /// <param name="positionGroup">The position group</param>
 /// <param name="order">The order</param>
 public HasSufficientPositionGroupBuyingPowerForOrderParameters(
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup,
     Order order
     )
 {
     Order = order;
     Portfolio = portfolio;
     PositionGroup = positionGroup;
 }
Пример #9
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PositionGroupInitialMarginForOrderParameters"/> class
 /// </summary>
 /// <param name="portfolio">The algorithm's portfolio manager</param>
 /// <param name="positionGroup">The position group</param>
 /// <param name="order">The order</param>
 public PositionGroupInitialMarginForOrderParameters(
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup,
     Order order
     )
 {
     Portfolio     = portfolio;
     PositionGroup = positionGroup;
     Order         = order;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="ReservedBuyingPowerImpactParameters"/> class
 /// </summary>
 /// <param name="portfolio">The algorithm's portfolio manager</param>
 /// <param name="contemplatedChanges">The position changes being contemplated</param>
 /// <param name="order">The order associated with this request</param>
 public ReservedBuyingPowerImpactParameters(
     SecurityPortfolioManager portfolio,
     IPositionGroup contemplatedChanges,
     Order order
     )
 {
     Order               = order;
     Portfolio           = portfolio;
     ContemplatedChanges = contemplatedChanges;
 }
 /// <summary>
 /// Initializes a new instance of the <see cref="PositionGroupBuyingPowerParameters"/> class
 /// </summary>
 /// <param name="portfolio">The algorithm's portfolio manager</param>
 /// <param name="positionGroup">The position group</param>
 /// <param name="direction">The direction to compute buying power in</param>
 public PositionGroupBuyingPowerParameters(
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup,
     OrderDirection direction
     )
 {
     Portfolio     = portfolio;
     Direction     = direction;
     PositionGroup = positionGroup;
 }
 /// <summary>
 /// Gets the total margin required to execute the specified order in units of the account currency including fees
 /// </summary>
 public static decimal GetInitialMarginRequiredForOrder(
     this IPositionGroupBuyingPowerModel model,
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup,
     Order order
     )
 {
     return(model.GetInitialMarginRequiredForOrder(
                new PositionGroupInitialMarginForOrderParameters(portfolio, positionGroup, order)
                ).Value);
 }
 /// <summary>
 /// Gets the buying power available for a position group trade
 /// </summary>
 public static PositionGroupBuyingPower GetPositionGroupBuyingPower(
     this IPositionGroupBuyingPowerModel model,
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup,
     OrderDirection direction
     )
 {
     return(model.GetPositionGroupBuyingPower(new PositionGroupBuyingPowerParameters(
                                                  portfolio, positionGroup, direction
                                                  )));
 }
 /// <summary>
 /// Check if there is sufficient buying power for the position group to execute this order.
 /// </summary>
 public static HasSufficientBuyingPowerForOrderResult HasSufficientBuyingPowerForOrder(
     this IPositionGroupBuyingPowerModel model,
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup,
     Order order
     )
 {
     return(model.HasSufficientBuyingPowerForOrder(new HasSufficientPositionGroupBuyingPowerForOrderParameters(
                                                       portfolio, positionGroup, order
                                                       )));
 }
 /// <summary>
 /// Get the maximum market position group order quantity to obtain a delta in the buying power used by a position group.
 /// The deltas sign defines the position side to apply it to, positive long, negative short.
 /// </summary>
 public static GetMaximumLotsResult GetMaximumLotsForDeltaBuyingPower(
     this IPositionGroupBuyingPowerModel model,
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup,
     decimal deltaBuyingPower
     )
 {
     return(model.GetMaximumLotsForDeltaBuyingPower(new GetMaximumLotsForDeltaBuyingPowerParameters(
                                                        portfolio, positionGroup, deltaBuyingPower
                                                        )));
 }
 /// <summary>
 /// Computes the change in reserved buying power we expect the portfolio to experience if the specified position
 /// group is added to the algorithm's holdings
 /// </summary>
 public static decimal GetChangeInReservedBuyingPower(
     this IPositionGroupBuyingPowerModel model,
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup,
     Order order
     )
 {
     return(model.GetReservedBuyingPowerImpact(
                new ReservedBuyingPowerImpactParameters(portfolio, positionGroup, order)
                ).Delta);
 }
Пример #17
0
        /// <summary>
        /// Creates a new <see cref="IPositionGroup"/> with the specified <paramref name="groupQuantity"/>.
        /// If the quantity provided equals the template's quantity then the template is returned.
        /// </summary>
        /// <param name="template">The group template</param>
        /// <param name="groupQuantity">The quantity of the new group</param>
        /// <returns>A position group with the same position ratios as the template but with the specified group quantity</returns>
        public static IPositionGroup WithQuantity(this IPositionGroup template, decimal groupQuantity)
        {
            if (template.Quantity == groupQuantity)
            {
                return(template);
            }

            var positions = template.ToArray(p => p.WithLots(groupQuantity));

            return(new PositionGroup(template.Key, positions));
        }
Пример #18
0
        /// <summary>
        /// Gets the position in the <paramref name="group"/> matching the provided <param name="symbol"></param>
        /// </summary>
        public static IPosition GetPosition(this IPositionGroup group, Symbol symbol)
        {
            IPosition position;

            if (!group.TryGetPosition(symbol, out position))
            {
                throw new KeyNotFoundException($"No position with symbol '{symbol}' exists in the group: {group}");
            }

            return(position);
        }
Пример #19
0
 /// <summary>
 /// Initializes a new instance of the <see cref="GetMaximumLotsForTargetBuyingPowerParameters"/> class
 /// </summary>
 /// <param name="portfolio">The algorithm's portfolio manager</param>
 /// <param name="positionGroup">The position group</param>
 /// <param name="targetBuyingPower">The target buying power</param>
 /// <param name="silenceNonErrorReasons">True will not return <see cref="GetMaximumLotsResult.Reason"/>
 /// set for non error situation, this is for performance</param>
 public GetMaximumLotsForTargetBuyingPowerParameters(
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup,
     decimal targetBuyingPower,
     bool silenceNonErrorReasons = false
     )
 {
     Portfolio              = portfolio;
     PositionGroup          = positionGroup;
     TargetBuyingPower      = targetBuyingPower;
     SilenceNonErrorReasons = silenceNonErrorReasons;
 }
Пример #20
0
        /// <summary>
        /// Returns the Maximum (Middle Strike - Lowest Strike, 0)
        /// </summary>
        private static decimal GetMiddleAndLowStrikeDifference(IPositionGroup positionGroup, SecurityPortfolioManager portfolio)
        {
            var options          = positionGroup.Positions.OrderBy(position => position.Symbol.ID.StrikePrice).ToList();
            var lowestCallStrike = options[0].Symbol.ID.StrikePrice;
            var middleCallStrike = options[1].Symbol.ID.StrikePrice;
            var optionSecurity   = (Option)portfolio.Securities[options[0].Symbol];

            var strikeDifference = Math.Max((middleCallStrike - lowestCallStrike) * optionSecurity.ContractUnitOfTrade * Math.Abs(positionGroup.Quantity), 0);

            // convert into account currency
            return(portfolio.CashBook.ConvertToAccountCurrency(strikeDifference, optionSecurity.QuoteCurrency.Symbol));
        }
Пример #21
0
        /// <summary>
        /// Returns the Maximum (Strike Long Call - Strike Short Call, 0)
        /// </summary>
        private static decimal GetLongCallShortCallStrikeDifferenceMargin(IPositionGroup positionGroup, SecurityPortfolioManager portfolio)
        {
            var longOption     = positionGroup.Positions.Single(position => position.Symbol.ID.OptionRight == OptionRight.Call && position.Quantity > 0);
            var shortOption    = positionGroup.Positions.Single(position => position.Symbol.ID.OptionRight == OptionRight.Call && position.Quantity < 0);
            var optionSecurity = (Option)portfolio.Securities[longOption.Symbol];

            var strikeDifference = longOption.Symbol.ID.StrikePrice - shortOption.Symbol.ID.StrikePrice;

            var result = Math.Max(strikeDifference * optionSecurity.ContractUnitOfTrade * Math.Abs(positionGroup.Quantity), 0);

            // convert into account currency
            return(portfolio.CashBook.ConvertToAccountCurrency(result, optionSecurity.QuoteCurrency.Symbol));
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="GetMaximumLotsForDeltaBuyingPowerParameters"/> class
 /// </summary>
 /// <param name="portfolio">The algorithm's portfolio manager</param>
 /// <param name="positionGroup">The position group</param>
 /// <param name="deltaBuyingPower">The delta buying power to apply. Sign defines the position side to apply the delta</param>
 /// <param name="minimumOrderMarginPortfolioPercentage">Configurable minimum order margin portfolio percentage to ignore orders with unrealistic small sizes</param>
 /// <param name="silenceNonErrorReasons">True will not return <see cref="GetMaximumLotsResult.Reason"/>
 /// set for non error situation, this is for performance</param>
 public GetMaximumLotsForDeltaBuyingPowerParameters(
     SecurityPortfolioManager portfolio,
     IPositionGroup positionGroup,
     decimal deltaBuyingPower,
     decimal minimumOrderMarginPortfolioPercentage,
     bool silenceNonErrorReasons = false
     )
 {
     Portfolio              = portfolio;
     PositionGroup          = positionGroup;
     DeltaBuyingPower       = deltaBuyingPower;
     SilenceNonErrorReasons = silenceNonErrorReasons;
     MinimumOrderMarginPortfolioPercentage = minimumOrderMarginPortfolioPercentage;
 }
Пример #23
0
        /// <summary>
        /// Gets the position side (long/short/none) of the specified <paramref name="group"/>
        /// </summary>
        public static PositionSide GetPositionSide(this IPositionGroup group)
        {
            if (group.Quantity > 0)
            {
                return(PositionSide.Long);
            }

            if (group.Quantity < 0)
            {
                return(PositionSide.Short);
            }

            return(PositionSide.None);
        }
Пример #24
0
        /// <summary>
        /// Helper function to compute the order fees associated with executing market orders for the specified <paramref name="positionGroup"/>
        /// </summary>
        protected virtual decimal GetOrderFeeInAccountCurrency(SecurityPortfolioManager portfolio, IPositionGroup positionGroup)
        {
            // TODO : Add Order parameter to support Combo order type, pulling the orders per position

            var orderFee = 0m;
            var utcTime  = portfolio.Securities.UtcTime;

            foreach (var position in positionGroup)
            {
                var security         = portfolio.Securities[position.Symbol];
                var order            = new MarketOrder(position.Symbol, position.Quantity, utcTime);
                var positionOrderFee = security.FeeModel.GetOrderFee(new OrderFeeParameters(security, order)).Value;
                orderFee += ToAccountCurrency(portfolio, positionOrderFee);
            }

            return(orderFee);
        }
        /// <summary>
        /// Attempts to group the specified positions into a new <see cref="IPositionGroup"/> using an
        /// appropriate <see cref="IPositionGroupBuyingPowerModel"/> for position groups created via this
        /// resolver.
        /// </summary>
        /// <param name="newPositions">The positions to be grouped</param>
        /// <param name="currentPositions">The currently grouped positions</param>
        /// <param name="group">The grouped positions when this resolver is able to, otherwise null</param>
        /// <returns>True if this resolver can group the specified positions, otherwise false</returns>
        public bool TryGroup(IReadOnlyCollection <IPosition> newPositions, PositionGroupCollection currentPositions, out IPositionGroup group)
        {
            foreach (var resolver in _resolvers)
            {
                if (resolver.TryGroup(newPositions, currentPositions, out group))
                {
                    return(true);
                }
            }

            group = null;
            return(false);
        }
        /// <summary>
        /// Attempts to group the specified positions into a new <see cref="IPositionGroup"/> using an
        /// appropriate <see cref="IPositionGroupBuyingPowerModel"/> for position groups created via this
        /// resolver.
        /// </summary>
        /// <param name="newPositions">The positions to be grouped</param>
        /// <param name="currentPositions">The currently grouped positions</param>
        /// <param name="group">The grouped positions when this resolver is able to, otherwise null</param>
        /// <returns>True if this resolver can group the specified positions, otherwise false</returns>
        public bool TryGroup(IReadOnlyCollection <IPosition> newPositions, PositionGroupCollection currentPositions, out IPositionGroup @group)
        {
            var impactedGroups = GetImpactedGroups(currentPositions, newPositions);
            var positionsToConsiderInNewGroup = impactedGroups.SelectMany(positionGroup => positionGroup.Positions);

            @group = GetPositionGroups(newPositions.Concat(positionsToConsiderInNewGroup)).Where(positionGroup =>
            {
                // from the resolved position groups we will take those which use our buying power model and which are related to the new positions to be executed
                if (positionGroup.BuyingPowerModel.GetType() == typeof(OptionStrategyPositionGroupBuyingPowerModel))
                {
                    return(newPositions.Any(position => positionGroup.TryGetPosition(position.Symbol, out position)));
                }
                return(false);
            }).FirstOrDefault();

            return(@group != null);
        }
Пример #27
0
        /// <summary>
        /// Checks if <paramref name="lastOrderQuantity"/> equals <paramref name="positionGroupQuantity"/> indicating we got the same result on this iteration
        /// meaning we're unable to converge through iteration. This function was split out to support derived types using the same error message as well
        /// as removing the added noise of the check and message creation.
        /// </summary>
        protected static bool UnableToConverge(decimal lastOrderQuantity, decimal positionGroupQuantity, IPositionGroup groupUnit, SecurityPortfolioManager portfolio, decimal target, decimal orderMargin, decimal absUnitMargin, decimal orderFees, out ArgumentException error)
        {
            // determine if we're unable to converge by seeing if quantity estimate hasn't changed
            if (lastOrderQuantity == positionGroupQuantity)
            {
                string message;
                if (groupUnit.Count == 1)
                {
                    // single security group
                    var security = portfolio.Securities[groupUnit.Single().Symbol];
                    message = "GetMaximumPositionGroupOrderQuantityForTargetBuyingPower failed to converge to target order margin " +
                              Invariant($"{target}. Current order margin is {orderMargin}. Order quantity {positionGroupQuantity}. ") +
                              Invariant($"Lot size is {security.SymbolProperties.LotSize}. Order fees {orderFees}. Security symbol ") +
                              $"{security.Symbol}. Margin unit {absUnitMargin}.";
                }
                else
                {
                    message = "GetMaximumPositionGroupOrderQuantityForTargetBuyingPower failed to converge to target order margin " +
                              Invariant($"{target}. Current order margin is {orderMargin}. Order quantity {positionGroupQuantity}. ") +
                              Invariant($"Position Group Unit is {groupUnit.Key}. Order fees {orderFees}. Position Group Name ") +
                              $"{groupUnit.GetUserFriendlyName()}. Margin unit {absUnitMargin}.";
                }

                error = new ArgumentException(message);
                return(true);
            }

            error = null;
            return(false);
        }
        /// <summary>
        /// Attempts to group the specified positions into a new <see cref="IPositionGroup"/> using an
        /// appropriate <see cref="IPositionGroupBuyingPowerModel"/> for position groups created via this
        /// resolver.
        /// </summary>
        /// <param name="newPositions">The positions to be grouped</param>
        /// <param name="currentPositions">The currently grouped positions</param>
        /// <param name="group">The grouped positions when this resolver is able to, otherwise null</param>
        /// <returns>True if this resolver can group the specified positions, otherwise false</returns>
        public bool TryGroup(IReadOnlyCollection <IPosition> newPositions, PositionGroupCollection currentPositions, out IPositionGroup group)
        {
            // we can only create default groupings containing a single security
            if (newPositions.Count != 1)
            {
                group = null;
                return(false);
            }

            var key = new PositionGroupKey(_buyingPowerModel, newPositions);

            group = new PositionGroup(key, newPositions.ToDictionary(p => p.Symbol));
            return(true);
        }