Skip to main content

Portfolio Optimization

Overview

Portfolio optimization is a capability in Merlin that helps allocate capital across multiple trading strategies. Using Modern Portfolio Theory Merlin determines optimal strategy weights to achieve specific objectives such as minimizing volatility, maximizing returns, or maximizing Sharpe.

Merlin uses portfolio optimization methods provided by Q-API, including Mean-Variance Optimization and Kelly Criterion based allocation.

Optimization Process

The portfolio optimization workflow in Merlin consists of these steps:

  1. Data Collection: Gather performance data for all component strategies using MesoSim APIs
  2. Strategy Optimization (optional): Apply SETS models to improve individual strategies when model is present.
  3. Walkforward Testing: Run walkforward optimization to obtain Out Of Sample results
  4. Performance Evaluation: Analyze the results of the optimized portfolio using tearsheets and performance metrics

The optimization process is parallelized for efficiency, with the degree of parallelism controlled by the BACKTESTS_IN_FLIGHT and MODEL_CALLS_IN_FLIGHT environment variables.

Walkforward Analysis

Similar to strategy optimization, portfolio optimization uses walkforward optimization to avoid overfitting.

Optimization Methods

Merlin supports several optimization targets:

Mean-Variance Optimization (MVO)

Based on Modern Portfolio Theory, MVO seeks to maximize expected returns for a given level of risk or minimize risk for a given level of expected return.

Merlin implements two MVO variants:

  • MinVolatility: Minimize portfolio volatility
  • MaxSharpe: Maximize the Sharpe ratio

MVO works best with strategies that have relatively stable statistical properties and follows a quadratic optimization approach.

tip

The MinVolatility target often results higher Out Of Sample Sharpe ratio than MaxSharpe target.

The optimization is done with PyPortfolioOpt. You can find the optimizer Source Code here.

Kelly Criterion

The Kelly Criterion calculates the optimal position sizes to maximize the long-term growth rate of capital, considering both the edge (expected return) and risk of each strategy.

This implementation scales the allocation fractions as such that the overall allocation will be 100%. You can find the optimizer Source Code here

Configuration Parameters

Portfolio optimization is configured through a portfolio config JSON file:

Basic Parameters

ParameterDescription
TargetOptimization method (MeanVarianceMinVolatility, MeanVarianceMaxSharpe, KellyCriterion)
WindowNumber of trading days used for optimizing the portfolio
TopAllocMaximum number of strategies to include in the portfolio
ReweightPeriodNumber of trading days between rebalancing
InitialCashInitial capital for the portfolio

Strategy Configuration

The Strategies section defines component strategies:

ParameterDescription
StrategyDefinitionPath to strategy definition file
ModelCfgPath to model configuration for strategy optimization (optional)
DataCollectionJobIdMesoSim backtest ID for strategy data. If not provided, a new data-collection backtest is ran. (optional)

Example Usage

Command Line

merlin optimize-portfolio configs/portfolios/litefolio.json --start=2017-01-01

Configuration Example

{
"Target": "MeanVarianceMinVolatility",
"Window": 160,
"TopAlloc": 999,
"ReweightPeriod": 5,
"InitialCash": 1000000,
"Strategies": {
"boxcar": {
"StrategyDefinition": "configs/strategies/boxcar-strategy.json",
"ModelCfg": "configs/strategies/boxcar-model-cfg.json",
"DataCollectionJobId": null
},
"0DTE-IC": {
"StrategyDefinition": "configs/strategies/0dte-ic-strategy.json",
"ModelCfg": "configs/strategies/0dte-ic-model-cfg.json",
"DataCollectionJobId": null
},
"chital": {
"StrategyDefinition": "configs/strategies/chital-strategy.json",
"ModelCfg": "configs/strategies/chital-model-cfg.json",
"DataCollectionJobId": null
}
}
}

Strategy Types in the Portfolio

Merlin supports two types of strategies in the portfolio:

  • Unoptimized: Strategies are included as-is without any strategy optimization when ModelCfg is set to null.
  • Optimized: When ModelCfg is provided, strategies are optimized using SETS models before portfolio optimization

During Portfolio Optimization run both types of strategies are ran and evaluated. When the Strategy Optimization yields worse results than the original (vanilla) strategy, the original strategy is used in the portfolio.

Results Analysis

After running the portfolio optimization the results are shown in the screen. The results consist of the allocation based on the best (in terms of Sharpe) portfolio optimization mode as well as the optimization mode specified by the user.

Example run

$ merlin optimize-portfolio configs/portfolios/litefolio.json --start=2017-01-01
Optimized strategy of 0DTE-IC / model_ptsl_pnl will be used (optimized=1.72 vs vanilla=1.63)
Optimized strategy of boxcar / model_ptsl_pnl will be used (optimized=1.36 vs vanilla=0.94)
Vanilla strategy of chital / model_ptsl_pnl will be used (optimized=1.1 vs vanilla=1.84)
Excluded strategies: None
Strategies included in portfolio optimization: 0DTE-IC, boxcar, chital
Portfolio Walkforward Optimization. max window size: 252
walkforward KellyCriterion
walkforward MeanVarianceMinVolatility
Portfolio OOS period: 2023-11-20 00:00:00 - 2025-03-28 00:00:00
equal-weight (2023-11-20 - 2025-03-28) = CAGR: 7.31% MaxDD: -7.46% Sortino 1.78, Sharpe: 1.36
KellyCriterion_5(2023-11-20 - 2025-03-28) = CAGR: -7.33% MaxDD: -14.7% Sortino -0.75, Sharpe: -0.68
KellyCriterion_10(2023-11-20 - 2025-03-28) = CAGR: 3.36% MaxDD: -14.12% Sortino 0.4, Sharpe: 0.32
KellyCriterion_20(2023-11-20 - 2025-03-28) = CAGR: 17.53% MaxDD: -4.04% Sortino 3.73, Sharpe: 1.86
KellyCriterion_40(2023-11-20 - 2025-03-28) = CAGR: 8.51% MaxDD: -5.91% Sortino 1.37, Sharpe: 0.9
KellyCriterion_80(2023-11-20 - 2025-03-28) = CAGR: 5.36% MaxDD: -9.82% Sortino 0.81, Sharpe: 0.58
KellyCriterion_160(2023-11-20 - 2025-03-28) = CAGR: 3.59% MaxDD: -3.66% Sortino 1.91, Sharpe: 1.41
KellyCriterion_252(2023-11-20 - 2025-03-28) = CAGR: 3.51% MaxDD: -3.71% Sortino 1.68, Sharpe: 1.31
MeanVarianceMinVolatility_5(2023-11-20 - 2025-03-28) = CAGR: 16.47% MaxDD: -7.63% Sortino 2.56, Sharpe: 1.84
MeanVarianceMinVolatility_10(2023-11-20 - 2025-03-28) = CAGR: 16.92% MaxDD: -6.02% Sortino 2.82, Sharpe: 2.0
MeanVarianceMinVolatility_20(2023-11-20 - 2025-03-28) = CAGR: 14.09% MaxDD: -7.14% Sortino 2.33, Sharpe: 1.66
MeanVarianceMinVolatility_40(2023-11-20 - 2025-03-28) = CAGR: 12.28% MaxDD: -7.49% Sortino 2.19, Sharpe: 1.55
MeanVarianceMinVolatility_80(2023-11-20 - 2025-03-28) = CAGR: 10.64% MaxDD: -6.34% Sortino 2.27, Sharpe: 1.64
MeanVarianceMinVolatility_160(2023-11-20 - 2025-03-28) = CAGR: 7.9% MaxDD: -5.11% Sortino 2.22, Sharpe: 1.63
MeanVarianceMinVolatility_252(2023-11-20 - 2025-03-28) = CAGR: 6.15% MaxDD: -4.32% Sortino 1.9, Sharpe: 1.41
Best optimization params: ('MeanVarianceMinVolatility', 10) with Sharpe: 2.0
Final folds allocation based on best params: ('MeanVarianceMinVolatility', 10)
{
"0DTE-IC+model-ptsl": 0.33333,
"boxcar+model-ptsl": 0.33333,
"chital": 0.33333
}
Final folds allocation based on Portfolio Target
{
"0DTE-IC+model-ptsl": 0.67063,
"chital": 0.18648,
"boxcar+model-ptsl": 0.1429
}

Run analysis

In the above run the equal-weight allocation should be considered as a baseline, with Sharpe of 1.36.

The Kelly-Criterion based allocation shows mixed results.

The MeanVariance / MinVolatility allocation improves the Sharpe ratio up to 2.0 using the 10 day lookback window.

Last, the last fold's allocation is shown for:

  • The optimization method with the Highest Sharpe
  • The user specified, Portfolio Target method

The last fold's allocation could be considered in live trading.

Results directory

Similar to Strategy Optimization, Merlin generates results from its portfolio optimization processes and stores it in the merlin-results directory under the run specific directory. The directory contains Tearsheets, allocations, and logs for the whole run. Check out the directory for more details.

Portfolio Optimization Modes
Portfolio Optimization - Equal Weight
Portfolio Optimization - Mean Variance Optimization

Next Steps

It's viable to start with a Portfolio that doesn't include any optimized strategies: In those cases strategy files are present, but there are no ModelCfg files created just yet.

Once Model Configurations are created for the individual strategies, the portfolio configuration can be updated to include the model configuration.