예제 #1
0
        /// <summary>
        /// Gets the margin currently alloted to the specified holding.
        /// </summary>
        /// <param name="parameters">An object containing the security</param>
        /// <returns>The maintenance margin required for the option</returns>
        /// <remarks>
        /// We fix the option to 1.5x the maintenance because of its close coupling with the underlying.
        /// The option's contract multiplier is 1x, but might be more sensitive to volatility shocks in the long
        /// run when it comes to calculating the different market scenarios attempting to simulate VaR, resulting
        /// in a margin greater than the underlying's margin.
        /// </remarks>
        public override MaintenanceMargin GetMaintenanceMargin(MaintenanceMarginParameters parameters)
        {
            var underlyingRequirement = base.GetMaintenanceMargin(parameters.ForUnderlying(parameters.Quantity));
            var positionSide          = parameters.Quantity > 0 ? PositionSide.Long : PositionSide.Short;

            return(GetMarginRequirement(_futureOption, underlyingRequirement, positionSide));
        }
예제 #2
0
 /// <summary>
 /// Gets the margin currently allocated to the specified holding
 /// </summary>
 /// <param name="parameters">An object containing the security</param>
 /// <returns>The maintenance margin required for the provided holdings quantity/cost/value</returns>
 public MaintenanceMargin GetMaintenanceMargin(MaintenanceMarginParameters parameters)
 {
     using (Py.GIL())
     {
         return((_model.GetMaintenanceMargin(parameters) as PyObject)
                .GetAndDispose <MaintenanceMargin>());
     }
 }
        /// <summary>
        /// Gets the margin currently allocated to the specified holding
        /// </summary>
        /// <param name="parameters">An object containing the security</param>
        /// <returns>The maintenance margin required for the </returns>
        public override MaintenanceMargin GetMaintenanceMargin(PositionGroupMaintenanceMarginParameters parameters)
        {
            // SecurityPositionGroupBuyingPowerModel models buying power the same as non-grouped, so we can simply sum up
            // the reserved buying power via the security's model. We should really only ever get a single position here,
            // but it's not incorrect to ask the model for what the reserved buying power would be using default modeling
            var buyingPower = 0m;

            foreach (var position in parameters.PositionGroup)
            {
                var security = parameters.Portfolio.Securities[position.Symbol];
                var result   = security.BuyingPowerModel.GetMaintenanceMargin(
                    MaintenanceMarginParameters.ForQuantityAtCurrentPrice(security, position.Quantity)
                    );

                buyingPower += result;
            }

            return(buyingPower);
        }
예제 #4
0
        /// <summary>
        /// Gets the margin currently allotted to the specified holding
        /// </summary>
        /// <param name="parameters">An object containing the security</param>
        /// <returns>The maintenance margin required for the </returns>
        public override MaintenanceMargin GetMaintenanceMargin(MaintenanceMarginParameters parameters)
        {
            var security = parameters.Security;

            if (security?.GetLastData() == null || parameters.Quantity == 0m)
            {
                return(0m);
            }

            var marginReq = GetCurrentMarginRequirements(security);

            if (EnableIntradayMargins &&
                security.Exchange.ExchangeOpen &&
                !security.Exchange.ClosingSoon)
            {
                return(marginReq.MaintenanceIntraday * parameters.AbsoluteQuantity);
            }

            // margin is per contract
            return(marginReq.MaintenanceOvernight * parameters.AbsoluteQuantity);
        }
        public MaintenanceMargin GetMaintenanceMargin(MaintenanceMarginParameters parameters)
        {
            EnsureSecurityExists(parameters.Security);
            var expected = SecurityModel.GetMaintenanceMargin(parameters);

            if (reentry)
            {
                return(expected);
            }

            reentry = true;
            var actual = PositionGroupModel.GetMaintenanceMargin(new PositionGroupMaintenanceMarginParameters(
                                                                     Portfolio, new PositionGroup(PositionGroupModel, new Position(parameters.Security, parameters.Quantity))
                                                                     ));

            Assert.AreEqual(expected.Value, actual.Value,
                            $"{PositionGroupModel.GetType().Name}:{nameof(GetMaintenanceMargin)}"
                            );

            reentry = false;
            return(expected);
        }
 /// <summary>
 /// Gets the margin currently allocated to the specified holding
 /// </summary>
 /// <param name="parameters">An object containing the security</param>
 /// <returns>The maintenance margin required for the provided holdings quantity/cost/value</returns>
 public override MaintenanceMargin GetMaintenanceMargin(MaintenanceMarginParameters parameters)
 {
     return(parameters.AbsoluteQuantity * _marginRequiredPerUnitInAccountCurrency);
 }
예제 #7
0
        /// <summary>
        /// Gets the margin currently allocated to the specified holding
        /// </summary>
        /// <param name="parameters">An object containing the security</param>
        /// <returns>The maintenance margin required for the </returns>
        public override MaintenanceMargin GetMaintenanceMargin(PositionGroupMaintenanceMarginParameters parameters)
        {
            if (_optionStrategy.Name == OptionStrategyDefinitions.CoveredCall.Name)
            {
                // MAX[In-the-money amount + Margin(long stock evaluated at min(mark price, strike(short call))), min(stock value, max(call value, long stock margin))]
                var optionPosition     = parameters.PositionGroup.Positions.FirstOrDefault(position => position.Symbol.SecurityType.IsOption());
                var underlyingPosition = parameters.PositionGroup.Positions.FirstOrDefault(position => !position.Symbol.SecurityType.IsOption());
                var optionSecurity     = (Option)parameters.Portfolio.Securities[optionPosition.Symbol];
                var underlyingSecurity = parameters.Portfolio.Securities[underlyingPosition.Symbol];

                var intrinsicValue   = optionSecurity.GetIntrinsicValue(underlyingSecurity.Price);
                var inTheMoneyAmount = intrinsicValue * optionSecurity.ContractUnitOfTrade * Math.Abs(optionPosition.Quantity);

                var underlyingValue = underlyingSecurity.Holdings.GetQuantityValue(underlyingPosition.Quantity);
                var optionValue     = optionSecurity.Holdings.GetQuantityValue(optionPosition.Quantity);

                // mark price, strike price
                var underlyingPriceToEvaluate   = Math.Min(optionSecurity.Price, optionSecurity.StrikePrice);
                var underlyingHypotheticalValue = underlyingSecurity.Holdings.GetQuantityValue(underlyingPosition.Quantity, underlyingPriceToEvaluate);

                var hypotheticalMarginRequired = underlyingSecurity.BuyingPowerModel.GetMaintenanceMargin(
                    new MaintenanceMarginParameters(underlyingSecurity, underlyingPosition.Quantity, 0, underlyingHypotheticalValue));
                var marginRequired = underlyingSecurity.BuyingPowerModel.GetMaintenanceMargin(
                    new MaintenanceMarginParameters(underlyingSecurity, underlyingPosition.Quantity, 0, underlyingValue));

                var secondOperand     = Math.Min(underlyingValue, Math.Max(optionValue, marginRequired));
                var result            = Math.Max(inTheMoneyAmount + hypotheticalMarginRequired, secondOperand);
                var inAccountCurrency = parameters.Portfolio.CashBook.ConvertToAccountCurrency(result, optionSecurity.QuoteCurrency.Symbol);

                return(new MaintenanceMargin(inAccountCurrency));
            }
            else if (_optionStrategy.Name == OptionStrategyDefinitions.CoveredPut.Name)
            {
                // Initial Stock Margin Requirement + In the Money Amount
                var optionPosition     = parameters.PositionGroup.Positions.FirstOrDefault(position => position.Symbol.SecurityType.IsOption());
                var underlyingPosition = parameters.PositionGroup.Positions.FirstOrDefault(position => !position.Symbol.SecurityType.IsOption());
                var optionSecurity     = (Option)parameters.Portfolio.Securities[optionPosition.Symbol];
                var underlyingSecurity = parameters.Portfolio.Securities[underlyingPosition.Symbol];

                var intrinsicValue   = optionSecurity.GetIntrinsicValue(underlyingSecurity.Price);
                var inTheMoneyAmount = intrinsicValue * optionSecurity.ContractUnitOfTrade * Math.Abs(optionPosition.Quantity);

                var initialMarginRequirement = underlyingSecurity.BuyingPowerModel.GetInitialMarginRequirement(underlyingSecurity, underlyingPosition.Quantity);

                var result            = Math.Abs(initialMarginRequirement) + inTheMoneyAmount;
                var inAccountCurrency = parameters.Portfolio.CashBook.ConvertToAccountCurrency(result, optionSecurity.QuoteCurrency.Symbol);

                return(new MaintenanceMargin(inAccountCurrency));
            }
            else if (_optionStrategy.Name == OptionStrategyDefinitions.BearCallSpread.Name ||
                     _optionStrategy.Name == OptionStrategyDefinitions.BullCallSpread.Name ||
                     _optionStrategy.Name == OptionStrategyDefinitions.CallCalendarSpread.Name)
            {
                var result = GetLongCallShortCallStrikeDifferenceMargin(parameters.PositionGroup, parameters.Portfolio);
                return(new MaintenanceMargin(result));
            }
            else if (_optionStrategy.Name == OptionStrategyDefinitions.BearPutSpread.Name ||
                     _optionStrategy.Name == OptionStrategyDefinitions.BullPutSpread.Name ||
                     _optionStrategy.Name == OptionStrategyDefinitions.PutCalendarSpread.Name)
            {
                var result = GetShortPutLongPutStrikeDifferenceMargin(parameters.PositionGroup, parameters.Portfolio);
                return(new MaintenanceMargin(result));
            }
            else if (_optionStrategy.Name == OptionStrategyDefinitions.Straddle.Name || _optionStrategy.Name == OptionStrategyDefinitions.Strangle.Name)
            {
                // Margined as two long options.
                var callOption   = parameters.PositionGroup.Positions.Single(position => position.Symbol.ID.OptionRight == OptionRight.Call);
                var callSecurity = (Option)parameters.Portfolio.Securities[callOption.Symbol];
                var callMargin   = callSecurity.BuyingPowerModel.GetMaintenanceMargin(MaintenanceMarginParameters.ForQuantityAtCurrentPrice(
                                                                                          callSecurity, callOption.Quantity));

                var putOption   = parameters.PositionGroup.Positions.Single(position => position.Symbol.ID.OptionRight == OptionRight.Put);
                var putSecurity = (Option)parameters.Portfolio.Securities[putOption.Symbol];
                var putMargin   = putSecurity.BuyingPowerModel.GetMaintenanceMargin(MaintenanceMarginParameters.ForQuantityAtCurrentPrice(
                                                                                        putSecurity, putOption.Quantity));

                var result = callMargin.Value + putMargin.Value;
                return(new MaintenanceMargin(result));
            }
            else if (_optionStrategy.Name == OptionStrategyDefinitions.ButterflyCall.Name || _optionStrategy.Name == OptionStrategyDefinitions.ButterflyPut.Name)
            {
                return(new MaintenanceMargin(0));
            }
            else if (_optionStrategy.Name == OptionStrategyDefinitions.ShortButterflyPut.Name || _optionStrategy.Name == OptionStrategyDefinitions.ShortButterflyCall.Name)
            {
                var result = GetMiddleAndLowStrikeDifference(parameters.PositionGroup, parameters.Portfolio);
                return(new MaintenanceMargin(result));
            }
            else if (_optionStrategy.Name == OptionStrategyDefinitions.IronCondor.Name)
            {
                var result = GetShortPutLongPutStrikeDifferenceMargin(parameters.PositionGroup, parameters.Portfolio);
                return(new MaintenanceMargin(result));
            }

            throw new NotImplementedException($"Option strategy {_optionStrategy.Name} margin modeling has yet to be implemented");
        }
 /// <summary>
 /// Gets the margin currently alloted to the specified holding.
 /// </summary>
 /// <param name="parameters">An object containing the security</param>
 /// <returns>The maintenance margin required for the option</returns>
 /// <remarks>
 /// We fix the option to 1.5x the maintenance because of its close coupling with the underlying.
 /// The option's contract multiplier is 1x, but might be more sensitive to volatility shocks in the long
 /// run when it comes to calculating the different market scenarios attempting to simulate VaR, resulting
 /// in a margin greater than the underlying's margin.
 /// </remarks>
 public override MaintenanceMargin GetMaintenanceMargin(MaintenanceMarginParameters parameters)
 {
     return(base.GetMaintenanceMargin(parameters.ForUnderlying(parameters.Quantity)) * FixedMarginMultiplier);
 }
예제 #9
0
        /// <summary>
        /// Gets the margin currently alloted to the specified holding
        /// </summary>
        /// <param name="parameters">An object containing the security</param>
        /// <returns>The maintenance margin required for the provided holdings quantity/cost/value</returns>
        public override MaintenanceMargin GetMaintenanceMargin(MaintenanceMarginParameters parameters)
        {
            var security = parameters.Security;

            return(parameters.AbsoluteHoldingsCost * GetMaintenanceMarginRequirement(security, security.Holdings.HoldingsCost));
        }
예제 #10
0
 /// <summary>
 /// The percentage of the holding's absolute cost that must be held in free cash in order to avoid a margin call
 /// </summary>
 public override MaintenanceMargin GetMaintenanceMargin(MaintenanceMarginParameters parameters)
 {
     return(base.GetMaintenanceMargin(parameters) * GetMarginCorrectionFactor(parameters.Security));
 }