/// <summary> /// Helper method to determine if the requested quantity is above the algorithm minimum order margin portfolio percentage /// </summary> /// <param name="portfolioManager">The algorithm's portfolio</param> /// <param name="minimumOrderMarginPortfolioPercentage">Minimum order margin portfolio percentage to ignore bad orders, orders with unrealistic small sizes</param> /// <param name="absFinalOrderMargin">The calculated order margin value</param> /// <remarks>If we are trading with negative margin remaining this method will return true always</remarks> /// <returns>True if this order quantity is above the minimum requested</returns> public static bool AboveMinimumOrderMarginPortfolioPercentage(SecurityPortfolioManager portfolioManager, decimal minimumOrderMarginPortfolioPercentage, decimal absFinalOrderMargin) { var minimumValue = portfolioManager.TotalPortfolioValue * minimumOrderMarginPortfolioPercentage; if (minimumValue > absFinalOrderMargin // if margin remaining is negative allow the order to pass so we can reduce the position && portfolioManager.GetMarginRemaining(portfolioManager.TotalPortfolioValue) > 0) { return(false); } return(true); }
/// <summary> /// Gets the margin cash available for a trade /// </summary> /// <param name="portfolio">The algorithm's portfolio</param> /// <param name="security">The security to be traded</param> /// <param name="direction">The direction of the trade</param> /// <returns>The margin available for the trade</returns> protected virtual decimal GetMarginRemaining( SecurityPortfolioManager portfolio, Security security, OrderDirection direction ) { var totalPortfolioValue = portfolio.TotalPortfolioValue; var result = portfolio.GetMarginRemaining(totalPortfolioValue); if (direction != OrderDirection.Hold) { var holdings = security.Holdings; //If the order is in the same direction as holdings, our remaining cash is our cash //In the opposite direction, our remaining cash is 2 x current value of assets + our cash if (holdings.IsLong) { switch (direction) { case OrderDirection.Sell: result += // portion of margin to close the existing position GetMaintenanceMargin(security) + // portion of margin to open the new position security.Holdings.AbsoluteHoldingsValue * GetInitialMarginRequirement(security); break; } } else if (holdings.IsShort) { switch (direction) { case OrderDirection.Buy: result += // portion of margin to close the existing position GetMaintenanceMargin(security) + // portion of margin to open the new position security.Holdings.AbsoluteHoldingsValue * GetInitialMarginRequirement(security); break; } } } result -= totalPortfolioValue * RequiredFreeBuyingPowerPercent; return(result < 0 ? 0 : result); }