PEF: Portfolio Efficiency Front

PEF: Portfolio Efficiency Front

29 August 2025, 03:03
Better Trader Every Day
0
58

Buy or rent PEF 2.0 in the MQL5 marketplace


1. Overview

The PEF script is a tool for portfolio optimization. It computes the Pareto Efficient Frontier between portfolio return and risk (either CVaR or Standard Deviation) using Monte Carlo simulations and bootstrapping methods.

The script enables traders and quantitative analysts to:

  • Load historical price data for multiple instruments.

  • Simulate portfolio outcomes with random or custom weight allocations.

  • Estimate performance metrics such as mean return, CVaR, standard deviation, Sharpe ratio.

  • Identify and export the Pareto frontier portfolios to a CSV file for further analysis.

2. Input Parameters

Price Data

  • InstrumentsList : Comma-separated list of symbols (e.g., "XAUUSD, USDJPY, EURUSD" ).

  • historyBars : Number of historical bars to load for each symbol.

  • DataTimeFrame : Timeframe of data (e.g., PERIOD_D1 ).

Simulation Parameters

  • ParetoAxesSelection : Selects which risk metric is used on the horizontal axis:

    • RetVsCVaR : Return vs Conditional Value-at-Risk.

    • RetVsStd : Return vs Standard Deviation.

  • SimuDays : Number of trading days to simulate (e.g., 21.6 ≈ 1 month).

  • SimMethodSelection : Method for simulations:

    • MCBootstraping : Monte Carlo with bootstrapping (resampled returns).

    • MC : Monte Carlo only (using historical return distribution).

  • NumberMCsimulations : Number of portfolio simulations.

  • NumberBootstrapTrials : Number of bootstrap resamples (only for bootstrapping).

  • randMethod : Random number generation method:

    • Parallel : Faster, less random (pre-generated random numbers).

    • Sequential : Slower, more random (generated sequentially).

  • AnnualRiskFreeReturnPct : Annualized risk-free return (%) used in Sharpe ratio.

  • BetaConfidence : Confidence level for CVaR (default 0.95).

  • customWeights : Comma-separated list of custom portfolio weights (optional).

Output Parameters

  • printEqualWeightSet : Show results for equal-weight portfolio.

  • printSepCovCorr : Print covariance and correlation matrices separately.

  • printCovCorr : Print combined covariance-correlation matrix.

  • saveCSVfile : Save Pareto front to a CSV file.

  • AddNonPareto2CSVfile : Include non-Pareto portfolios in CSV.

  • ParetoCSVfilename : Name of the output CSV file.


3. Methodology

  1. Data Collection

    • Historical closing prices are fetched for the selected instruments.

    • Returns are calculated as percentage price changes.

  2. Portfolio Simulations

    • A large number of random weight vectors are generated.

    • Two possible simulation methods:

      • MC (Monte Carlo): Direct simulation from historical return distribution.

      • MCBootstraping: Resampling returns with replacement to account for variability.

  3. Risk & Return Calculation

    • For each weight set, the script computes:

      • Mean Return (%).

      • CVaR (%): Average of the worst (1–β)% outcomes.

      • Standard Deviation (%).

  4. Pareto Frontier Extraction

    • A portfolio is Pareto-optimal if no other portfolio achieves higher return with equal or lower risk.

    • Non-dominated portfolios are selected as the Pareto front.

  5. Sharpe Ratio Optimization

    • The script finds the portfolio with the maximum Sharpe ratio relative to the chosen risk-free rate.


4. Outputs

Expert Tab in MetaTrader5

  • Input parameter summary.

  • Covariance/correlation matrices.

  • Pareto frontier table (risk, return, CVaR/std, weights).

  • Equal-weight portfolio performance.

  • Custom-weight portfolio performance (if provided).

  • Maximum Sharpe ratio portfolio.

CSV Output (if enabled)

  • File saved under MQL5/Files/ with name specified in ParetoCSVfilename .

  • Columns include:

    • Risk (CVaR% or Std%),

    • Mean Return%,

    • Secondary risk metric,

    • Asset weights.


5. Example 1:

This is the result for default input values:



This is the output in the Expert Tab of MetaTrader5. 


The first part of the image above shows simply the input parameters used by PEF.

Then the Covariance and the Correlation matrices are printed for the symbols in the portfolio. The covariance matrix diagonal entries are useful to estimate the relative volatility among symbols (XAUUSD, USDJPY, and EURUSD in this example). Since the diagonal is normalized by the first entry [1,1], it is printed as 1.00 for XAUUSD. The second diagonal entry is 0.4323 for USDJPY, and the third and last diagonal entry is 0.2292 for EURUSD. The way to interpret them is like this: the most volatile of the three symbols is XAUUSD with 1.0; then USDJPY is about 43% as volatile as XAUUSD (43.23% to be precise), and EURUSD is about 23% as volatile as XAUUSD (22.92% to be precise). By looking at this three numbers, you could immediately conclude that a more risky portfolio would have higher weight in XAUUSD while lower in EURUSD, and a lesser risky portfolio would have higher weight in EURUSD while lower in XAUUSD.

The Correlation matrix provides the information about the correlation between symbols. Hence we read the off-diagonal entries to determine their cross-correlation, since the diagonal entries are all 1 (meaning, obviously, 100% correlated with themselves). The XAUUSD/USDJPY correlation is
-0.207; the XAUUSD/EURUSD is 0.218; and the EURUSD/USDJPY is -0.268. All three values are relatively low (i.e. lower than |+/- 0.4|). The useful information that these low values provide is their sign. XAUUSD/USDJPY is negative, meaning that statistically XAUUSD and USDJPY move in opposite direction. XAUUSD/EURUSD is positive, meaning that statistically XAUUSD and EURUSD move in the same direction.

The next matrix printed is a combination of the two first matrices. The diagonal entries from the Covariance and the off-diagonal entries of the correlation matrix. This is simply a quicker way to reach conclusions about volatility and correlation by looking at a single matrix.

Important: all conclusions from reading the Covariance and Correlation matrices are valid only for the length of the data (historyBars) and the period of such data (DataTimeFrame).



Next is the Pareto Front table. In total there are 882 portfolios for this example at this moment of time where the PEF was executed. Below we show just the first 14 portfolios. They are sorted by the mean return % in descending order. The results in this Pareto table are only valid for the simulation days (simudays) provided in the input. The first column is just an ID for the Pareto point. The second column is the standard deviation of returns Stdev% (or CVaR, Conditional Value at Risk) also known as the “Expected Shortfall” for the length of simuDays. CVaR is the average of all losses in the lower xth percentile of the loss distribution. In this example x=5 (100-BetaConfidence*100).

The third column is the mean of the total return in percentage for the length of simuDays. It could be positive or negative.

The rest of columns corresponds to the weight for each symbol in the portfolio which produced the pair Return-vs-risk (risk being Stdev or CVaR) in the same row. All weights in the same row add to 1.


The next image shows the last portfolios plus two more: the equal weight portfolio for comparison (usually not belonging to the Pareto front), and the portfolio that produces the Sharpe Ratio for the given annual risk-free return.






In order to perform the calculation of the Sharpe ratio it is necessary to convert the annual risk-free return to an equivalent risk-free return for the period given by the input simuDays. That equivalent risk-free return is 0.086% in this example.



The CSV file

If requested, the CSV file will be located in the MQL5/Files folder. Here is a screen shot:


Read the CSV file with a spreadsheet software like Excel. Then you can plot the first two columns as a scatter plot x-y which will show graphically the Pareto front, that is the Portfolio Efficiency Front (PEF). In the image below the blue line, which is made of 882 separate points (portfolios) is the Pareto front. The image also include, manually added, Pareto point corresponding to the Sharpe ratio (a red diamond). The red line passes through the Sharpe Pareto point and the equivalent risk-free return percent (0.086% in this example).




If in addition you request to add the entire set of simulations (Pareto and non-Pareto points) using the input variable AddNonPareto2CSVfile (this is not the default), then you can create plots like this below where you can see the entire set of simulations (each point is a portfolio) and the Portfolio Efficiency Front (red points).  This image is not created by PEF automatically, you need to prepare it in your spreadsheet software manually.




Interpreting and Using the Portfolio Efficiency Front

The whole purpose of running PEF is to select a set of weights that balance your risk aversion and return greed. From the image above, there are Stdev values from 1.6 to 4.4 (see the table). For a fixed value of Stdev the best return is given by the red dot above it. Suppose your are a conservative investor and prefer to work with Stdev values below 2.5%. For stdev=2.5% the best portfolio has a mean return of 1.3%. The corresponding Portfolio weights are XAUUSD=0.55, USDJPY=0.13, and EURUSD=0.32.

If you are more risk tolerant, you could go to the rightest point (stdev=4.3, return=2.1%) with weights XAUUSD=1, USDJPY=0, and EURUSD=0, which means you should put all your money on gold. If you are a follower of the Sharpe ratio theory, the “optimum” portfolio would be stdev=2.73, return=1.42%, with weights XAUUSD=0.61, USDJPY=0.11, and EURUSD=0.28.

The most important fact users must understand is:   ALL Pareto front portfolios are valid choices. The selection only depends on the level of risk and you are willing to take. What is not valid is to select points that are not on the Pareto front (black dots in the image above)

And remember:  all conclusions are valid only for the length of the data (historyBars), the period of such data (DataTimeFrame), and the number of days of the projection (SimuDays).





Notes

  • Ensure that the input variables are set according to your portfolio and analysis requirements.

  • Technically, the Sharpe ratio is defined based on volatility (standard deviation). If you use CVaR as the risk metric in the x-axis, you will get a different “optimum” portfolio. We have decided to call this point the “maximum slope” Pareto point instead of the Sharpe ratio Pareto point.

  • PEF will print logs during execution, indicating the progress and any issues encountered.

  • The output CSV file will be saved typically in the MQL5/Files folder.



6. Example 2:

This example is included only to show the use of the covariance and correlation matrices when there is strong correlation and volatility.

Suppose you are interested in the following assets: XAUUSD, USDJPY, GDAXI, SP500, and NDX (Nasdaq).

Suppose you get a combined Covariance/Correlation matrix like this:


From the diagonal covariance entries we conclude: the most volatile symbol is NDX (Nasdaq) with 1.833, and the least one is USDJPY with 0.440. It means that NDX is more than 4 times (1.883/0.44) more volatile than USDJPY. The other three symbols fall in the middle of volatility.

From the off-diagonal correlation entries we conclude: SP500 and NDX are highly and positively correlated (0.953). Since NDX is so volatile, and it is correlated with SP500, an approach could be to drop NDX from the portfolio to reduce volatility, and keep SP500. We ran that case too. Below is the Cov-Corr combined matrix for XAUUSD, USDJPY, GDAXI, SP500:


Now the four volatility values are comparable, except for USDJPY with 0.44 (lower), and the cross-correlations are equal or below of 0.201. This portfolio is better than the portfolio with NDX in terms of volatility and cross-correlation.

Buy or rent PEF 2.0 in the MQL5 marketplace






There are other approaches to determine portfolio weights such as the Risk Parity Portfolio algorithm implemented in RPP .