Problem Description
Solution
To implement a rule that always invests a fixed percentage (e.g., 5%) of your portfolio into every new trade signal, the most robust method within the QuantConnect LEAN framework is to define a custom Portfolio Construction Model (PCM).
This approach separates your signal logic (Alpha) from your sizing logic (Portfolio), ensuring that every Insight emitted by your algorithm is automatically converted into a PortfolioTarget of the specific size you desire.
Implementation
Here is the complete code for a custom FixedAllocationPortfolioConstructionModel and how to integrate it into your algorithm.
1. Define the Custom Portfolio Construction Model
from AlgorithmImports import *
class FixedAllocationPortfolioConstructionModel(PortfolioConstructionModel):
"""
Allocates a fixed percentage of the total portfolio value to every active insight.
"""
def __init__(self, percent: float = 0.05):
"""
Args:
percent: The fixed percentage to allocate (0.05 = 5%)
"""
super().__init__()
self.percent = percent
def CreateTargets(self, algorithm, insights):
targets = []
for insight in insights:
# If the signal is Flat, we likely want to liquidate (0% allocation)
if insight.Direction == InsightDirection.Flat:
targets.append(PortfolioTarget.Percent(algorithm, insight.Symbol, 0.0))
continue
# Determine direction multiplier (1 for Long, -1 for Short)
direction = 1 if insight.Direction == InsightDirection.Up else -1
# Calculate the target weight
# Example: Short (-1) * 0.05 = -0.05 (Sell 5% of portfolio)
weight = direction * self.percent
# Create the target
targets.append(PortfolioTarget.Percent(algorithm, insight.Symbol, weight))
return targets
2. Integrate into Your Algorithm
In your main algorithm class, you must set this model during the Initialize method.
class FixedPercentAllocationAlgorithm(QCAlgorithm):
def initialize(self):
self.set_start_date(2020, 1, 1)
self.set_cash(100000)
# Add assets
self.add_equity("SPY", Resolution.DAILY)
self.add_equity("AAPL", Resolution.DAILY)
# 1. Set the Alpha Model (Logic that generates signals/insights)
# Using a standard RsiAlphaModel as an example
self.set_alpha(RsiAlphaModel())
# 2. Set the Custom Portfolio Construction Model
# This enforces the 5% rule for every signal generated by the Alpha model
self.set_portfolio_construction(FixedAllocationPortfolioConstructionModel(percent=0.05))
# 3. Set Execution Model (How to execute the orders)
self.set_execution(ImmediateExecutionModel())
Key Details
PortfolioTarget.Percent: This helper function automatically calculates the number of shares required to reach the target weight based on the currentTotalPortfolioValue.- Direction Handling: The code checks
InsightDirection. If the signal isUp, it allocates +5%. IfDown, it allocates -5% (short). IfFlat, it allocates 0% (liquidates the position). - Independence: This model does not check if you have enough cash. If you generate 25 signals at 5% each, you will be 125% invested (using margin). If you want to prevent leverage, you would need to add logic to check
algorithm.Portfolio.MarginRemaining.
Q&A
Q: Does this work if I manually place orders using self.SetHoldings?
A: No. This model works specifically with the Algorithm Framework (using EmitInsights or Alpha Models). If you are manually placing trades in OnData using self.SetHoldings, you should simply pass the percentage there: self.SetHoldings("SPY", 0.05).
Q: What happens if the price moves and my 5% allocation becomes 6%?
A: The CreateTargets method runs every time new insights are generated or at the rebalance frequency defined in the PCM. If the insight is still active, this model will recalculate the target. If the value has drifted significantly, the Execution model will generate a small rebalancing order to bring it back to 5%.
Q: Can I change the percentage dynamically?
A: Yes. You can modify the self.percent attribute of your model instance, or create logic inside CreateTargets to adjust the weight based on volatility or other factors available in the algorithm object.