19 using System.Diagnostics.CodeAnalysis;
35 private decimal _initialMarginRequirement;
36 private decimal _maintenanceMarginRequirement;
61 decimal initialMarginRequirement,
62 decimal maintenanceMarginRequirement,
63 decimal requiredFreeBuyingPowerPercent
66 if (initialMarginRequirement < 0 || initialMarginRequirement > 1)
71 if (maintenanceMarginRequirement < 0 || maintenanceMarginRequirement > 1)
76 if (requiredFreeBuyingPowerPercent < 0 || requiredFreeBuyingPowerPercent > 1)
81 _initialMarginRequirement = initialMarginRequirement;
82 _maintenanceMarginRequirement = maintenanceMarginRequirement;
99 if (requiredFreeBuyingPowerPercent < 0 || requiredFreeBuyingPowerPercent > 1)
104 _initialMarginRequirement = 1 / leverage;
105 _maintenanceMarginRequirement = 1 / leverage;
116 return 1 / _initialMarginRequirement;
134 var margin = 1 / leverage;
135 _initialMarginRequirement = margin;
136 _maintenanceMarginRequirement = margin;
155 ConvertToAccountCurrency(fees).Amount;
159 return orderMargin + Math.Sign(orderMargin) * feesInAccountCurrency;
206 else if (holdings.IsShort)
222 return result < 0 ? 0 : result;
234 return security.QuoteCurrency.ConversionRate
235 * security.SymbolProperties.ContractMultiplier
238 * _initialMarginRequirement;
264 var underlying = option.Underlying;
266 if (option.IsAutoExercised(underlying.Close) && underlying.IsTradable)
268 var quantity = option.GetExerciseQuantity(parameters.
Order.
Quantity);
280 var parametersForUnderlying = parameters.
ForUnderlying(newOrder);
282 var freeMargin = underlying.BuyingPowerModel.GetBuyingPower(parametersForUnderlying.Portfolio, parametersForUnderlying.Security, parametersForUnderlying.Order.Direction);
286 var initialMarginRequired = underlying.BuyingPowerModel.GetInitialMarginRequiredForOrder(
299 decimal? freeMarginToUse =
null, decimal? initialMarginRequired =
null)
309 new InitialMarginRequiredForOrderParameters(
315 var initialMarginRequiredForRemainderOfOrder = percentUnfilled * initialMarginRequiredForOrder;
317 if (Math.Abs(initialMarginRequiredForRemainderOfOrder) > freeMargin)
320 initialMarginRequiredForRemainderOfOrder, freeMargin));
341 var targetBuyingPower = signedUsedBuyingPower + parameters.
DeltaBuyingPower;
372 var signedTargetFinalMarginValue =
376 if (signedTargetFinalMarginValue == 0)
390 if (absUnitMargin == 0)
396 var absDifferenceOfMargin = Math.Abs(signedTargetFinalMarginValue - signedCurrentUsedMargin);
400 string reason =
null;
416 var lastOrderQuantity = 0m;
417 decimal orderFees = 0m;
418 decimal signedTargetHoldingsMargin;
419 decimal orderQuantity;
424 orderQuantity =
GetAmountToOrder(parameters.
Security, signedTargetFinalMarginValue, absUnitMargin, out signedTargetHoldingsMargin);
425 if (orderQuantity == 0)
427 string reason =
null;
431 signedTargetFinalMarginValue - signedCurrentUsedMargin);
448 if (lastOrderQuantity == orderQuantity)
453 if (parameters.
Security is
Option.Option option && option.Underlying !=
null)
455 var underlying = option.Underlying;
459 throw new ArgumentException(message);
461 lastOrderQuantity = orderQuantity;
465 while (Math.Abs(signedTargetHoldingsMargin) > Math.Abs(signedTargetFinalMarginValue));
480 public decimal
GetAmountToOrder([NotNull]
Security security, decimal targetMargin, decimal marginForOneUnit, out decimal finalMargin)
482 var lotSize = security.SymbolProperties.LotSize;
487 var orderSize = -security.Holdings.Quantity;
490 orderSize += targetMargin / marginForOneUnit;
493 var roundingMode = targetMargin < 0
495 ? MidpointRounding.ToPositiveInfinity
497 : MidpointRounding.ToNegativeInfinity;
500 orderSize = orderSize.DiscretelyRoundBy(lotSize, roundingMode);
504 orderSize + security.Holdings.Quantity);
509 var marginDifference = finalMargin - targetMargin;
510 while ((targetMargin < 0 && marginDifference < 0) || (targetMargin > 0 && marginDifference > 0))
514 orderSize += targetMargin < 0 ? lotSize : -lotSize;
518 orderSize + security.Holdings.Quantity);
522 var newDifference = finalMargin - targetMargin;
523 if (Math.Abs(newDifference) > Math.Abs(marginDifference) && Math.Sign(newDifference) == Math.Sign(marginDifference))
526 var errorMessage =
"BuyingPowerModel().GetAmountToOrder(): " +
530 if (security is
Option.Option option && option.Underlying !=
null)
535 throw new ArgumentException(errorMessage);
538 marginDifference = newDifference;