Fixed Fractional Sizing
Fixed fractional position sizing. A complete hands-on Jupyter notebook with production-ready Python implementation, best practices, and step-by-step walkthrough for risk workflows in quantitative cryptocurrency trading.
Understanding Fixed Fractional Sizing
Introduction to Fixed Fractional Sizing
Fixed fractional sizing is a popular money management strategy used in trading to determine the appropriate position size for each trade. It's a method of risk management that aims to protect a trading account from large drawdowns while still allowing for significant growth.
What is it?
Fixed fractional sizing dictates that a fixed percentage of the trading account's equity should be risked on any single trade. Unlike fixed dollar risk (e.g., risking a flat $100 per trade) or fixed share sizing (e.g., buying 100 shares every time), this method dynamically adjusts the position size based on the current account equity and the predetermined risk per trade.
Why does it matter?
- Dynamic Risk Management: As the account equity grows, the absolute dollar amount risked also increases, allowing for larger profits. Conversely, if the account faces drawdowns, the absolute risk decreases, preventing the account from being wiped out too quickly.
- Compounding Effect: It allows for the power of compounding to work effectively, as profits are reinvested proportionally.
- Survival: By limiting the risk per trade to a small fraction of the capital, it significantly reduces the probability of catastrophic losses.
How it works
At its core, fixed fractional sizing calculates the number of units (shares, contracts, lots) to trade based on a predefined percentage of your total trading capital that you are willing to risk on a single trade, and the stop-loss distance of that trade. The key is to keep the fraction of equity risked constant.
The Core Formula
The calculation for fixed fractional sizing involves determining the maximum acceptable loss for a trade, which is a fixed fraction of the current account equity. This loss is then used in conjunction with the stop-loss distance to calculate the number of units to trade.
The primary formula used is:
$$\text{Position Size (Units)} = \frac{\text{Account Equity} \times \text{Fraction Risked}}{\text{Stop Loss Distance}}$$
Where:
- Account Equity: The current total value of your trading account.
- Fraction Risked: The fixed percentage of your account equity you are willing to risk on one trade (e.g., 0.01 for 1%).
- Stop Loss Distance: The difference between the entry price and the stop-loss price for the trade. This represents the dollar amount you would lose per unit if the stop-loss is hit.
Let's implement a function to calculate this.
import numpy as np
import matplotlib.pyplot as plt
def calculate_position_size(account_equity: float, fraction_risked: float, stop_loss_distance: float) -> float:
"""
Calculates the position size (number of units) using fixed fractional sizing.
Inputs:
- account_equity (float): The current total value of the trading account.
- fraction_risked (float): The fixed percentage of the account equity to risk on one trade (e.g., 0.01 for 1%).
- stop_loss_distance (float): The maximum potential loss per unit for the trade.
Outputs:
- float: The calculated number of units (position size) to trade.
Formula Used:
Position Size = (Account Equity * Fraction Risked) / Stop Loss Distance
Note: The output is typically rounded down to the nearest whole number for practical trading,
but for simulation purposes, we might keep it as a float to show the theoretical impact.
"""
if stop_loss_distance <= 0:
raise ValueError("Stop loss distance must be positive.")
if not (0 < fraction_risked < 1):
raise ValueError("Fraction risked must be between 0 and 1.")
if account_equity <= 0:
raise ValueError("Account equity must be positive.")
dollar_risk_per_trade = account_equity * fraction_risked
position_size = dollar_risk_per_trade / stop_loss_distance
return position_sizeExample Execution
Let's see how the position size changes with different parameters.
# Scenario 1: Initial account, moderate risk
initial_equity_1 = 10000.0
fraction_risked_1 = 0.01 # 1% risk
stop_loss_distance_1 = 0.50 # $0.50 per unit
position_size_1 = calculate_position_size(initial_equity_1, fraction_risked_1, stop_loss_distance_1)
print(f"Scenario 1 (Equity: ${initial_equity_1:.2f}, Risk: {fraction_risked_1*100:.0f}%, SL: ${stop_loss_distance_1:.2f}): Position Size = {position_size_1:.2f} units")
# Scenario 2: Account grows, same risk settings
grown_equity_2 = 15000.0
fraction_risked_2 = 0.01
stop_loss_distance_2 = 0.50
position_size_2 = calculate_position_size(grown_equity_2, fraction_risked_2, stop_loss_distance_2)
print(f"Scenario 2 (Equity: ${grown_equity_2:.2f}, Risk: {fraction_risked_2*100:.0f}%, SL: ${stop_loss_distance_2:.2f}): Position Size = {position_size_2:.2f} units")
# Scenario 3: Account shrinks, same risk settings
shrunk_equity_3 = 8000.0
fraction_risked_3 = 0.01
stop_loss_distance_3 = 0.50
position_size_3 = calculate_position_size(shrunk_equity_3, fraction_risked_3, stop_loss_distance_3)
print(f"Scenario 3 (Equity: ${shrunk_equity_3:.2f}, Risk: {fraction_risked_3*100:.0f}%, SL: ${stop_loss_distance_3:.2f}): Position Size = {position_size_3:.2f} units")
# Scenario 4: Same equity, larger stop loss distance (less units)
initial_equity_4 = 10000.0
fraction_risked_4 = 0.01
stop_loss_distance_4 = 1.00 # $1.00 per unit
position_size_4 = calculate_position_size(initial_equity_4, fraction_risked_4, stop_loss_distance_4)
print(f"Scenario 4 (Equity: ${initial_equity_4:.2f}, Risk: {fraction_risked_4*100:.0f}%, SL: ${stop_loss_distance_4:.2f}): Position Size = {position_size_4:.2f} units")Scenario 1 (Equity: $10000.00, Risk: 1%, SL: $0.50): Position Size = 200.00 units Scenario 2 (Equity: $15000.00, Risk: 1%, SL: $0.50): Position Size = 300.00 units Scenario 3 (Equity: $8000.00, Risk: 1%, SL: $0.50): Position Size = 160.00 units Scenario 4 (Equity: $10000.00, Risk: 1%, SL: $1.00): Position Size = 100.00 units
Interpretation of Results
As observed from the examples:
- When the account equity increases (Scenario 2 vs. Scenario 1), the position size (number of units) also increases, allowing larger potential profits in line with account growth.
- When the account equity decreases (Scenario 3 vs. Scenario 1), the position size automatically shrinks, reducing the absolute dollar risk and helping to preserve capital.
- A larger stop-loss distance for the same account equity and risk fraction (Scenario 4 vs. Scenario 1) results in a smaller position size, as each unit carries more potential risk.
Simulating Portfolio Growth with Fixed Fractional Sizing
To understand the practical implications of fixed fractional sizing, let's simulate a series of trades and observe how the account equity evolves over time. We'll compare it to a fixed unit sizing approach to highlight the benefits.
def simulate_trading(initial_equity: float, fraction_risked: float, num_trades: int, win_rate: float, avg_r_multiple: float, fixed_units: int = None):
"""
Simulates a series of trades and tracks account equity using fixed fractional sizing or fixed unit sizing.
Inputs:
- initial_equity (float): Starting capital.
- fraction_risked (float): Percentage of equity risked per trade (for fixed fractional).
- num_trades (int): Total number of trades to simulate.
- win_rate (float): Probability of a trade being a win (e.g., 0.5 for 50%).
- avg_r_multiple (float): Average reward-to-risk ratio (e.g., 2.0 means wins are 2x losses).
- fixed_units (int, optional): If provided, simulates with a fixed number of units per trade instead of fixed fractional.
Outputs:
- list: A list containing the account equity after each trade.
"""
equity_history = [initial_equity]
current_equity = initial_equity
# Assume a constant stop-loss distance and profit per unit for simplicity in simulation
# For simplicity, let's assume a 'virtual' stop_loss_distance of 1 unit.
# This means 'dollar_risk_per_unit' is effectively 1.
# The actual profit/loss per trade will then be 'position_size * 1' for loss,
# and 'position_size * avg_r_multiple * 1' for win.
for _ in range(num_trades):
if current_equity <= 0: # Account busted
equity_history.append(0.0)
continue
if fixed_units is None:
# Fixed Fractional Sizing
# We use a conceptual stop_loss_distance=1 for calculation of position size
# The actual dollar risk per trade is equity * fraction_risked
# So, position_size = (equity * fraction_risked) / 1
# loss_per_trade = position_size * 1
# win_per_trade = position_size * avg_r_multiple * 1
position_size = calculate_position_size(current_equity, fraction_risked, stop_loss_distance=1.0) # Use 1.0 as a conceptual unit risk
# Ensure position size is at least 1 for any trade to occur, or 0 if equity is too low
position_size = max(1, int(position_size)) if position_size >=1 else 0
if position_size == 0:
equity_history.append(current_equity)
continue
dollar_risk_per_trade = position_size * 1.0 # Conceptual risk per unit is 1.0
dollar_profit_per_trade = position_size * avg_r_multiple * 1.0
else:
# Fixed Unit Sizing
position_size = fixed_units
dollar_risk_per_trade = position_size * 1.0 # Assuming $1 loss per unit for simplicity
dollar_profit_per_trade = position_size * avg_r_multiple * 1.0
is_win = np.random.rand() < win_rate
if is_win:
current_equity += dollar_profit_per_trade
else:
current_equity -= dollar_risk_per_trade
equity_history.append(current_equity)
return equity_historySimulation Parameters
Let's define some common trading parameters for our simulation:
initial_capital = 10000.0
risk_fraction = 0.01 # 1% risk per trade
number_of_trades = 500
probability_of_win = 0.5 # 50% win rate
reward_to_risk = 1.5 # 1.5R trades (win $1.5 for every $1 risked)
fixed_units_per_trade = 100 # For comparison with fixed unit sizingRun Simulations
equity_fixed_fractional = simulate_trading(initial_capital, risk_fraction, number_of_trades, probability_of_win, reward_to_risk)
equity_fixed_units = simulate_trading(initial_capital, 0, number_of_trades, probability_of_win, reward_to_risk, fixed_units=fixed_units_per_trade)
print(f"Final Equity (Fixed Fractional): ${equity_fixed_fractional[-1]:.2f}")
print(f"Final Equity (Fixed Units): ${equity_fixed_units[-1]:.2f}")Final Equity (Fixed Fractional): $34244.50 Final Equity (Fixed Units): $26250.00
Visualization 1: Portfolio Growth Comparison
This visualization compares the growth trajectory of a trading account using fixed fractional sizing versus a fixed unit sizing approach over a series of trades. This helps to illustrate the compounding effect and risk management benefits of fixed fractional sizing.
plt.figure(figsize=(14, 7))
plt.plot(equity_fixed_fractional, label='Fixed Fractional Sizing', color='green', linewidth=2)
plt.plot(equity_fixed_units, label=f'Fixed {fixed_units_per_trade} Units Sizing', color='red', linestyle='--', linewidth=1.5)
plt.title('Portfolio Growth: Fixed Fractional vs. Fixed Unit Sizing')
plt.xlabel('Number of Trades')
plt.ylabel('Account Equity ($)')
plt.grid(True, linestyle='--', alpha=0.7)
plt.axhline(y=initial_capital, color='gray', linestyle=':', label='Initial Capital')
plt.legend()
plt.tight_layout()
plt.show()Interpretation of Visualization 1
The plot clearly shows a significant difference in portfolio growth:
- Fixed Fractional Sizing (Green Line): The equity curve shows a smoother, more resilient growth path. Even with drawdowns, the position size adjusts, reducing the impact of subsequent losses. In winning streaks, the position size increases, accelerating gains due to compounding.
- Fixed Unit Sizing (Red Dashed Line): This approach tends to be more volatile. While it might show sharp gains, it's also susceptible to severe drawdowns, potentially leading to faster account depletion during losing streaks, as the absolute dollar risk remains constant regardless of account size.
Impact of the 'Fraction Risked'
The choice of the fraction_risked (or f factor) is crucial in fixed fractional sizing. A higher fraction means higher risk and potentially higher returns, but also higher volatility and a greater chance of significant drawdowns or even account ruin. A lower fraction leads to slower growth but also lower risk and greater stability.
Let's simulate the effect of different risk fractions.
risk_fractions = [0.005, 0.01, 0.02, 0.03]
# Using the same initial_capital, num_trades, probability_of_win, reward_to_risk
equity_curves_by_fraction = {}
for fraction in risk_fractions:
equity_curves_by_fraction[fraction] = simulate_trading(initial_capital, fraction, number_of_trades, probability_of_win, reward_to_risk)
# Print final equities for comparison
for fraction, curve in equity_curves_by_fraction.items():
print(f"Final Equity (Fraction: {fraction*100:.1f}%): ${curve[-1]:.2f}")Final Equity (Fraction: 0.5%): $19114.50 Final Equity (Fraction: 1.0%): $20800.50 Final Equity (Fraction: 2.0%): $170247.00 Final Equity (Fraction: 3.0%): $151544.50
Visualization 2: Portfolio Growth with Different Risk Fractions
This visualization demonstrates how varying the fraction_risked parameter impacts the overall equity curve, risk, and return of a trading strategy.
plt.figure(figsize=(14, 7))
colors = ['blue', 'green', 'orange', 'red']
for i, (fraction, curve) in enumerate(equity_curves_by_fraction.items()):
plt.plot(curve, label=f'Fraction Risked: {fraction*100:.1f}%', color=colors[i], linewidth=1.5)
plt.title('Portfolio Growth with Different Fixed Risk Fractions')
plt.xlabel('Number of Trades')
plt.ylabel('Account Equity ($)')
plt.grid(True, linestyle='--', alpha=0.7)
plt.axhline(y=initial_capital, color='gray', linestyle=':', label='Initial Capital')
plt.legend()
plt.tight_layout()
plt.show()Interpretation of Visualization 2
This plot clearly illustrates the trade-off between risk and reward when choosing the fraction_risked:
- Higher Fractions (e.g., 2% and 3%): Tend to show steeper growth during winning periods, but also experience more volatile swings and deeper drawdowns. The 3% fraction, while having the highest potential, also shows the largest fluctuations and risks hitting zero if a series of losses occur.
- Lower Fractions (e.g., 0.5% and 1%): Exhibit smoother, more stable growth. The growth rate is slower, but the account is much more resilient to losing streaks. The drawdowns are less severe, increasing the probability of long-term survival.
Choosing an optimal fraction often involves balancing desired growth with acceptable risk tolerance. Many professional traders use fractions between 0.5% and 2% per trade.
Conclusion
Fixed fractional sizing is a powerful money management technique that can significantly influence the longevity and profitability of a trading system. By dynamically adjusting position size based on current account equity and trade-specific risk, it provides inherent risk control and allows for the benefits of compounding.
Key Takeaways:
- Dynamic Risk: It ensures that a constant percentage of your capital is risked, meaning the absolute dollar amount risked scales with your equity.
- Compounding: Profits are naturally reinvested, accelerating growth during winning periods.
- Capital Preservation: During losing periods, the smaller absolute risk helps to mitigate drawdowns and prevent catastrophic losses.
- Importance of
Fraction Risked: The choice of the risk fraction is critical. Too high, and volatility increases, risking ruin; too low, and growth is constrained.
Implementing fixed fractional sizing is a cornerstone of robust trading strategies, moving beyond simple entry/exit rules to ensure long-term account health and growth.