/// <summary> /// Manages the algorithm's risk at each time step /// </summary> /// <param name="algorithm">The algorithm instance</param> /// <param name="targets">The current portfolio targets to be assessed for risk</param> public override IEnumerable <IPortfolioTarget> ManageRisk(QCAlgorithmFramework algorithm, IPortfolioTarget[] targets) { var maximumSectorExposureValue = algorithm.Portfolio.TotalPortfolioValue * _maximumSectorExposure; _targetsCollection.AddRange(targets); // Group the securities by their sector var groupBySector = algorithm.UniverseManager.ActiveSecurities .Where(x => x.Value.Fundamentals != null && x.Value.Fundamentals.HasFundamentalData) .GroupBy(x => x.Value.Fundamentals.CompanyReference.IndustryTemplateCode); foreach (var securities in groupBySector) { // Compute the sector absolute holdings value // If the construction model has created a target, we consider that // value to calculate the security absolute holding value var sectorAbsoluteHoldingsValue = 0m; foreach (var security in securities) { var absoluteHoldingsValue = security.Value.Holdings.AbsoluteHoldingsValue; IPortfolioTarget target; if (_targetsCollection.TryGetValue(security.Value.Symbol, out target)) { absoluteHoldingsValue = security.Value.Price * Math.Abs(target.Quantity) * security.Value.SymbolProperties.ContractMultiplier * security.Value.QuoteCurrency.ConversionRate; } sectorAbsoluteHoldingsValue += absoluteHoldingsValue; } // If the ratio between the sector absolute holdings value and the maximum sector exposure value // exceeds the unity, it means we need to reduce each security of that sector by that ratio // Otherwise, it means that the sector exposure is below the maximum and there is nothing to do. var ratio = sectorAbsoluteHoldingsValue / maximumSectorExposureValue; if (ratio > 1) { foreach (var security in securities) { var quantity = security.Value.Holdings.Quantity; var symbol = security.Value.Symbol; IPortfolioTarget target; if (_targetsCollection.TryGetValue(symbol, out target)) { quantity = target.Quantity; } if (quantity != 0) { yield return(new PortfolioTarget(symbol, quantity / ratio)); } } } } }