Risk Management

Key Concepts

Introduction

The Risk Management model seeks to manage risk on the PortfolioTarget collection it receives from the Portfolio Construction model before the targets reach the Execution model. There are many creative ways to manage risk. Some examples of risk management include the following:

  • "Trailing Stop Risk Management Model"
    Create and manage trailing stop-loss orders for open positions.
  • "Option Hedging Risk Management Model"
    Purchase options to hedge large equity exposures.
  • "Sector Exposure Risk Management Model"
    Reduce position sizes when overexposed to sectors or individual assets, keeping the portfolio within diversification requirements.
  • "Flash Crash Detection Risk Management Model"
    Scan for strange market situations that might be precursors to a flash crash and attempt to protect the portfolio when they are detected.

Add Models

To set a Risk Management model, in the Initialize method, call the AddRiskManagement method.

self.AddRiskManagement(NullRiskManagementModel())
AddRiskManagement(new NullRiskManagementModel());

To view all the pre-built Risk Management models, see Supported Models.

Multi-Model Algorithms

To add multiple Risk Management models, in the Initialize method, call the AddRiskManagement method multiple times.

AddRiskManagement(new MaximumDrawdownPercentPerSecurity());
AddRiskManagement(new MaximumSectorExposureRiskManagementModel());
self.AddRiskManagement(MaximumDrawdownPercentPerSecurity())
self.AddRiskManagement(MaximumSectorExposureRiskManagementModel())

If you add multiple Risk Management models, the original collection of PortfolioTarget objects from the Portfolio Construction model is passed to the first Risk Management model. The risk-adjusted targets from the first Risk Management model are passed to the second Risk Management model. The process continues sequentially until all of the Risk Management models have had an opportunity to adjust the targets.

Model Structure

Risk Management models should extend the RiskManagementModel class. Extensions of the RiskManagementModel class must implement the ManageRisk method, which receives an array of PortfolioTarget objects from the Portfolio Construction model and should return an array of risk-adjusted PortfolioTarget objects. The method should only return the adjusted targets, not all of targets.

class MyRiskManagementModel : RiskManagementModel
{
    // Adjust the portfolio targets and return them. If no changes emit nothing.
    public override List<PortfolioTarget> ManageRisk(QCAlgorithm algorithm, PortfolioTarget[] targets)
    {
        return new List<PortfolioTarget>();
    }

    // Optional: Be notified when securities change
    public override void OnSecuritiesChanged(QCAlgorithm algorithm, SecurityChanges changes)
    {
        // Security additions and removals are pushed here.
        // This can be used for setting up algorithm state.
        // changes.AddedSecurities
        // changes.RemovedSecurities
    }
}
class MyRiskManagementModel(RiskManagementModel):
    # Adjust the portfolio targets and return them. If no changes emit nothing.
    def ManageRisk(self, algorithm: QCAlgorithm, targets: List[PortfolioTarget]) -> List[PortfolioTarget]:
        return []

    # Optional: Be notified when securities change
    def OnSecuritiesChanged(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
        # Security additions and removals are pushed here.
        # This can be used for setting up algorithm state.
        # changes.AddedSecurities
        # changes.RemovedSecurities
        pass

The algorithm argument that the methods receive is an instance of the base QCAlgorithm class, not your subclass of it.

To view a full example of a RiskManagementModel subclass, see the MaximumDrawdownPercentPerSecurityMaximumDrawdownPercentPerSecurity in the LEAN GitHub repository.

Track Security Changes

The Universe Selection model may select a dynamic universe of assets, so you should not assume a fixed set of assets in the Risk Management model. When the Universe Selection model adds and removes assets from the universe, it triggers an OnSecuritiesChanged event. In the OnSecuritiesChanged event handler, you can initialize the security-specific state or load any history required for your Risk Management model.

class MyRiskManagementModel : RiskManagementModel
{
    private Dictionary<symbol, symboldata> _symbolDataBySymbol = new Dictionary<symbol, symboldata>();

    public override void OnSecuritiesChanged(QCAlgorithmFramework algorithm, SecurityChanges changes)
    {
        base.OnSecuritiesChanged(algorithm, changes)
        foreach (var security in changes.AddedSecurities)
        {               
            _symbolDataBySymbol[security.Symbol] = new SymbolData(security.Symbol);
        }

        foreach (var security in changes.RemovedSecurities)
        {
            if (_symbolDataBySymbol.ContainsKey(security.Symbol))
            {
                _symbolDataBySymbol.Remove(security.Symbol);
            }
        }
    }

    public class SymbolData 
    {
        private Symbol _symbol;

        public SymbolData(Symbol symbol)
        {
            _symbol = symbol;
            // Store and manage Symbol-specific data
        }
    }
}
class MyRiskManagementModel(RiskManagementModel):
    symbol_data_by_symbol = {}

    def OnSecuritiesChanged(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:
        super().OnSecuritiesChanged(algorithm, changes)
        for security in changes.AddedSecurities:
            self.symbol_data_by_symbol[security.Symbol] = SymbolData(security.Symbol)

        for security in changes.RemovedSecurities:
            if security.Symbol in self.symbol_data_by_symbol:
                self.symbol_data_by_symbol.pop(security.Symbol, None)

class SymbolData:
    def __init__(self, symbol):
        self.symbol = symbol
        # Store and manage Symbol-specific data

Portfolio Target Collection

The PortfolioTargetCollection class is a helper class to manage PortfolioTarget objects. The class manages an internal dictionary that has the security Symbol as the key and a PortfolioTarget as the value.

Add Portfolio Targets

To add a PortfolioTarget to the PortfolioTargetCollection, call the Add method.

_targetsCollection.Add(portfolioTarget);
self.targets_collection.Add(portfolio_target)

To add a list of PortfolioTarget objects, call the AddRange method.

_targetsCollection.AddRange(portfolioTargets);
self.targets_collection.AddRange(portfolio_targets)

Check Membership

To check if a PortfolioTarget exists in the PortfolioTargetCollection, call the Contains method.

var targetInCollection = _targetsCollection.Contains(portfolioTarget);
target_in_collection = self.targets_collection.Contains(portfolio_target)

To check if a Symbol exists in the PortfolioTargetCollection, call the ContainsKey method.

var symbolInCollection = _targetsCollection.ContainsKey(symbol);
symbol_in_collection = self.targets_collection.ContainsKey(symbol)

To get all the Symbol objects, use the Keys property.

var symbols = _targetsCollection.Keys;
symbols = self.targets_collection.Keys

Access Portfolio Targets

To access the PortfolioTarget objects for a Symbol, index the PortfolioTargetCollection with the Symbol.

var portfolioTarget = _targetsCollection[symbol];
portfolio_target = self.targets_collection[symbol]

To iterate through the PortfolioTargetCollection, call the GetEnumerator method.

var enumerator = _targetsCollection.GetEnumerator();
enumerator = self.targets_collection.GetEnumerator()

To get all the PortfolioTarget objects, use the Values property

var portfolioTargets = _targetsCollection.Values;
portfolio_targets = self.targets_collection.Values

Order Portfolio Targets by Margin Impact

To get an enumerable where position reducing orders are executed first and the remaining orders are executed in decreasing order value, call the OrderByMarginImpact method.

foreach (var target in _targetsCollection.OrderByMarginImpact(algorithm))
{
    // Place order
}
for target in self.targets_collection.OrderByMarginImpact(algorithm):
    # Place order

This method won't return targets for securities that have no data yet. This method also won't return targets for which the sum of the current holdings and open orders quantity equals the target quantity.

Remove Portfolio Targets

To remove a PortfolioTarget from the PortfolioTargetCollection, call the Remove method.

removeSuccessful = _targetsCollection.Remove(symbol);
remove_successful = self.targets_collection.Remove(symbol)

To remove all the PortfolioTarget objects, call the Clear method.

_targetsCollection.Clear();
self.targets_collection.Clear()

To remove all the PortfolioTarget objects that have been fulfilled, call the ClearFulfilled method.

_targetsCollection.ClearFulfilled(algorithm);
self.targets_collection.ClearFulfilled(algorithm)

Copy Portfolio Targets

To copy a subset of the PortfolioTarget objects in the PortfolioTargetCollection to an array, call the CopyTo method. The arrayIndex argument is the zero-based index in the array at which copying begins.

_targetsCollection.CopyTo(array, arrayIndex);
self.targets_collection.CopyTo(array, arrayIndex)

You can also see our Videos. You can also get in touch with us via Discord.

Did you find this page helpful?

Contribute to the documentation: