21 using System.Collections.Generic;
41 _optionStrategy = optionStrategy;
51 if (_optionStrategy ==
null)
59 var optionPosition = parameters.
PositionGroup.
Positions.FirstOrDefault(position => position.Symbol.SecurityType.IsOption());
60 var underlyingPosition = parameters.
PositionGroup.
Positions.FirstOrDefault(position => !position.Symbol.SecurityType.IsOption());
64 var absOptionQuantity = Math.Abs(optionPosition.Quantity);
65 var outOfTheMoneyAmount = optionSecurity.OutOfTheMoneyAmount(underlyingSecurity.Price) * optionSecurity.ContractUnitOfTrade * absOptionQuantity;
68 underlyingSecurity, underlyingPosition.Quantity)));
70 var result = Math.Min(0.1m * optionSecurity.StrikePrice * optionSecurity.ContractUnitOfTrade * absOptionQuantity + outOfTheMoneyAmount, underlyingMarginRequired);
78 var optionPosition = parameters.
PositionGroup.
Positions.FirstOrDefault(position => position.Symbol.SecurityType.IsOption());
79 var underlyingPosition = parameters.
PositionGroup.
Positions.FirstOrDefault(position => !position.Symbol.SecurityType.IsOption());
83 var intrinsicValue = optionSecurity.GetIntrinsicValue(underlyingSecurity.Price);
84 var inTheMoneyAmount = intrinsicValue * optionSecurity.ContractUnitOfTrade * Math.Abs(optionPosition.Quantity);
86 var underlyingValue = underlyingSecurity.Holdings.GetQuantityValue(underlyingPosition.Quantity).InAccountCurrency;
87 var optionValue = optionSecurity.Holdings.GetQuantityValue(optionPosition.Quantity).InAccountCurrency;
90 var underlyingPriceToEvaluate = Math.Min(underlyingSecurity.Price, optionSecurity.ScaledStrikePrice);
91 var underlyingHypotheticalValue = underlyingSecurity.Holdings.GetQuantityValue(underlyingPosition.Quantity, underlyingPriceToEvaluate).InAccountCurrency;
93 var hypotheticalMarginRequired = underlyingSecurity.BuyingPowerModel.GetMaintenanceMargin(
95 var marginRequired = underlyingSecurity.BuyingPowerModel.GetMaintenanceMargin(
98 var secondOperand = Math.Min(underlyingValue, Math.Max(optionValue, marginRequired));
99 var result = Math.Max(inTheMoneyAmount + hypotheticalMarginRequired, secondOperand);
107 var optionPosition = parameters.
PositionGroup.
Positions.FirstOrDefault(position => position.Symbol.SecurityType.IsOption());
108 var underlyingPosition = parameters.
PositionGroup.
Positions.FirstOrDefault(position => !position.Symbol.SecurityType.IsOption());
112 var intrinsicValue = optionSecurity.GetIntrinsicValue(underlyingSecurity.Price);
113 var inTheMoneyAmount = intrinsicValue * optionSecurity.ContractUnitOfTrade * Math.Abs(optionPosition.Quantity);
115 var initialMarginRequirement = underlyingSecurity.BuyingPowerModel.GetInitialMarginRequirement(underlyingSecurity, underlyingPosition.Quantity);
117 var result = Math.Abs(initialMarginRequirement) + inTheMoneyAmount;
149 shortCallSecurity, shortCall.Quantity));
167 (option, quantity) => Math.Abs(option.BuyingPowerModel.GetMaintenanceMargin(
186 throw new NotImplementedException($
"Option strategy {_optionStrategy.Name} margin modeling has yet to be implemented");
197 if (_optionStrategy ==
null)
204 var underlyingPosition = parameters.
PositionGroup.
Positions.FirstOrDefault(position => !position.Symbol.SecurityType.IsOption());
207 result = Math.Abs(underlyingSecurity.BuyingPowerModel.GetInitialMarginRequirement(underlyingSecurity, underlyingPosition.Quantity));
213 var optionPosition = parameters.
PositionGroup.
Positions.FirstOrDefault(position => position.Symbol.SecurityType.IsOption());
214 var underlyingPosition = parameters.
PositionGroup.
Positions.FirstOrDefault(position => !position.Symbol.SecurityType.IsOption());
218 var optionValue = Math.Abs(optionSecurity.Holdings.GetQuantityValue(optionPosition.Quantity).InAccountCurrency);
220 var marginRequired = underlyingSecurity.BuyingPowerModel.GetInitialMarginRequirement(underlyingSecurity, underlyingPosition.Quantity);
223 result = optionValue * 0.8m + marginRequired;
236 var margin = security.BuyingPowerModel.GetInitialMarginRequirement(
new InitialMarginParameters(security, option.Quantity));
239 if (optionMargin !=
null)
241 return new OptionInitialMargin(Math.Abs(optionMargin.ValueWithoutPremium), optionMargin.Premium);
261 result = Math.Abs(shortOption.BuyingPowerModel.GetInitialMarginRequirement(shortOption, shortOptionPosition.Quantity));
276 (option, quantity) => Math.Abs(option.BuyingPowerModel.GetInitialMarginRequirement(option, quantity)));
292 throw new NotImplementedException($
"Option strategy {_optionStrategy.Name} margin modeling has yet to be implemented");
297 foreach (var position
in parameters.PositionGroup.Positions.Where(position => position.Symbol.SecurityType.IsOption()))
299 var option = (
Option)parameters.Portfolio.Securities[position.Symbol];
300 premium += option.Holdings.GetQuantityValue(position.Quantity).InAccountCurrency;
319 var feesWithSign = Math.Sign(initialMarginRequired) * feesInAccountCurrency.Amount;
321 return new InitialMargin(feesWithSign + initialMarginRequired);
329 List<IPosition> ordersPositions)
331 var contemplatedMargin = 0m;
332 foreach (var contemplatedGroup
in contemplatedGroups)
336 var initialMargin = contemplatedGroup.BuyingPowerModel.GetInitialMarginRequirement(
344 var ordersGroups = portfolio.Positions.ResolvePositionGroups(
new PositionCollection(ordersPositions));
345 foreach (var orderGroup
in ordersGroups)
347 var initialMargin = orderGroup.BuyingPowerModel.GetInitialMarginRequirement(
351 if (optionInitialMargin !=
null)
355 contemplatedMargin += optionInitialMargin.
Value - optionInitialMargin.ValueWithoutPremium;
359 return contemplatedMargin;
368 return _optionStrategy.Name;
376 var longOption = positionGroup.
Positions.Single(position => position.Symbol.ID.OptionRight ==
OptionRight.Put && position.Quantity > 0);
377 var shortOption = positionGroup.
Positions.Single(position => position.Symbol.ID.OptionRight ==
OptionRight.Put && position.Quantity < 0);
381 var strikeDifference = shortOption.Symbol.ID.StrikePrice - longOption.Symbol.ID.StrikePrice;
383 var result = Math.Max(strikeDifference * optionSecurity.ContractUnitOfTrade * Math.Abs(positionGroup.
Quantity), 0);
394 var longOption = positionGroup.
Positions.Single(position => position.Symbol.ID.OptionRight ==
OptionRight.Call && position.Quantity > 0);
395 var shortOption = positionGroup.
Positions.Single(position => position.Symbol.ID.OptionRight ==
OptionRight.Call && position.Quantity < 0);
398 var strikeDifference = longOption.Symbol.ID.StrikePrice - shortOption.Symbol.ID.StrikePrice;
400 var result = Math.Max(strikeDifference * optionSecurity.ContractUnitOfTrade * Math.Abs(positionGroup.
Quantity), 0);
409 private static decimal GetMiddleAndLowStrikeDifference(
IPositionGroup positionGroup, SecurityPortfolioManager portfolio)
411 var options = positionGroup.
Positions.OrderBy(position => position.Symbol.ID.StrikePrice).ToList();
412 var lowestCallStrike = options[0].Symbol.ID.StrikePrice;
413 var middleCallStrike = options[1].Symbol.ID.StrikePrice;
414 var optionSecurity = (
Option)portfolio.Securities[options[0].Symbol];
416 var strikeDifference = Math.Max((middleCallStrike - lowestCallStrike) * optionSecurity.ContractUnitOfTrade * Math.Abs(positionGroup.
Quantity), 0);
419 return portfolio.CashBook.ConvertToAccountCurrency(strikeDifference, optionSecurity.QuoteCurrency.Symbol);
426 private static decimal GetShortStraddleStrangleMargin(
IPositionGroup positionGroup, SecurityPortfolioManager portfolio,
427 Func<Option, decimal, decimal> getOptionMargin)
429 var callOption = positionGroup.
Positions.Single(position => position.Symbol.ID.OptionRight ==
OptionRight.Call);
430 var callSecurity = (Option)portfolio.Securities[callOption.Symbol];
431 var callMargin = getOptionMargin(callSecurity, callOption.Quantity);
433 var putOption = positionGroup.
Positions.Single(position => position.Symbol.ID.OptionRight ==
OptionRight.Put);
434 var putSecurity = (Option)portfolio.Securities[putOption.Symbol];
435 var putMargin = getOptionMargin(putSecurity, putOption.Quantity);
439 if (putMargin > callMargin)
441 result = putMargin + callSecurity.Price * callSecurity.ContractUnitOfTrade * Math.Abs(callOption.Quantity);
445 result = callMargin + putSecurity.Price * putSecurity.ContractUnitOfTrade * Math.Abs(putOption.Quantity);