🚀 AI One-Click Generation of quantconnect Strategy Code

QuantConnect Framework Guide: How to Create Your Own Custom Risk Management Model

quantconnect | Published on: 2025/12/11
The following content is generated by EasyQuant .

Problem Description

How do I create a custom risk management model for my portfolio?

Solution

To create a custom risk management model in QuantConnect, you need to define a class that inherits from RiskManagementModel and implements the manage_risk method. This method analyzes the current portfolio state and incoming portfolio targets, returning a list of new targets to adjust positions (usually to reduce risk).

Below is a complete example of a custom Trailing Drawdown Risk Model. This model monitors every open position; if a position's unrealized profit percentage drops below a specific threshold (e.g., -5%), it forces a liquidation.

Custom Risk Management Strategy

# region imports
from AlgorithmImports import *
# endregion

class CustomRiskManagementAlgorithm(QCAlgorithm):

    def initialize(self):
        self.set_start_date(2020, 1, 1)
        self.set_end_date(2023, 1, 1)
        self.set_cash(100000)

        # 1. Add Equities
        self.add_equity("SPY", Resolution.DAILY)
        self.add_equity("QQQ", Resolution.DAILY)
        
        # 2. Set the Custom Risk Management Model
        # We pass 0.05 (5%) as the maximum allowed drawdown per position
        self.set_risk_management(TrailingDrawdownRiskModel(maximum_drawdown_percent=0.05))

    def on_data(self, data: Slice):
        # Simple logic to enter positions for demonstration
        if not self.portfolio.invested:
            self.set_holdings("SPY", 0.5)
            self.set_holdings("QQQ", 0.5)

# ------------------------------------------------------------------------------
# CUSTOM RISK MANAGEMENT MODEL
# ------------------------------------------------------------------------------
class TrailingDrawdownRiskModel(RiskManagementModel):
    """
    Liquidates a position if its unrealized profit percentage drops below 
    the specified maximum drawdown threshold.
    """
    
    def __init__(self, maximum_drawdown_percent=0.05):
        """
        Args:
            maximum_drawdown_percent: The negative return threshold to trigger liquidation (e.g. 0.05 for 5%)
        """
        self.maximum_drawdown_percent = abs(maximum_drawdown_percent)

    def manage_risk(self, algorithm, targets):
        """
        Called by the framework to check for risk.
        
        Args:
            algorithm: The QCAlgorithm instance
            targets: The list of PortfolioTarget objects from the Portfolio Construction Model
            
        Returns:
            A list of PortfolioTarget objects to be executed
        """
        risk_adjusted_targets = []

        # Loop through all securities in the algorithm's universe
        for kvp in algorithm.securities:
            security = kvp.value
            symbol = security.symbol

            # We only care about securities that are currently invested
            if not security.invested:
                continue

            # Calculate the Unrealized Profit Percentage
            # (Current Price - Average Price) / Average Price
            pnl_percent = security.holdings.unrealized_profit_percent

            # Check if the PnL is below our negative threshold (e.g., < -0.05)
            if pnl_percent < -self.maximum_drawdown_percent:
                
                # Log the event for debugging
                algorithm.log(f"RISK ALERT: Liquidating {symbol} | PnL: {pnl_percent:.2%}")
                
                # Create a target to liquidate the position (Quantity = 0)
                risk_adjusted_targets.append(PortfolioTarget(symbol, 0))

        return risk_adjusted_targets

Key Implementation Details

  1. Inheritance: The class must inherit from RiskManagementModel.
  2. manage_risk Method: This is the core entry point.
    • Input: It receives the algorithm instance (giving access to self.portfolio, self.securities, etc.) and targets (the desired trades coming from your Alpha/Portfolio models).
    • Output: It must return a list of PortfolioTarget objects.
  3. Logic: In the example above, we iterate through algorithm.securities. If unrealized_profit_percent violates our limit, we create a PortfolioTarget(symbol, 0). This tells the Execution model to sell everything for that symbol immediately.
  4. Integration: Use self.set_risk_management(YourModel()) in the initialize method of your algorithm.

How It Fits in the Framework

The Risk Management model runs after the Portfolio Construction model but before the Execution model.

  1. Alpha Model: Generates Insights (Predictions).
  2. Portfolio Construction: Converts Insights into Targets (Desired Quantities).
  3. Risk Management: (You are here) Reviews the Portfolio and Targets. It can cancel targets or create new ones to close positions (liquidate).
  4. Execution: Executes the final list of targets.

Q&A: Custom Risk Management in QuantConnect

Q: Can I use multiple risk models at the same time?
A: Yes. Instead of set_risk_management, you can use self.add_risk_management(Model1()) followed by self.add_risk_management(Model2()). The framework will run them sequentially, and if any model triggers a liquidation or adjustment, that target will be passed down.

Q: How do I prevent re-entry after a risk liquidation?
A: The manage_risk method only handles the immediate liquidation. To prevent re-entry, you usually need to maintain a state (e.g., a set of "cooldown" symbols) within your class. In manage_risk, you would check the incoming targets argument and remove any buy targets for symbols that are currently in your cooldown list.

Q: Does manage_risk run on every tick?
A: It runs every time the algorithm processes a "Time Slice." In backtesting, this is determined by your data resolution (e.g., every minute for Resolution.MINUTE). In live trading, it runs in real-time as data arrives.

Q: Can I modify the size of a position instead of liquidating it completely?
A: Yes. Instead of sending a target with quantity 0, you can calculate a reduced quantity. For example, if you want to cut exposure by half, you would return PortfolioTarget(symbol, current_holdings * 0.5).