6 min read
Scenario Analysis: Python Code Snippets for Forecasting Investment Performance
Copy and paste these code snippets to forecast investment performance in any market conditions.
In recent years, high inflation and global conflict busted economist predictions. How well are your funds or portfolios prepared to weather market surprises?
Scenario analysis can help portfolio managers manage risk and refine long-term investment strategies. The process models hypothetical scenarios and shows the potential impact on investments. For those who have already mastered the basics in Python, these advanced techniques offer more ways to assess performance drivers. Copy and paste the Python snippets to run scenario analysis on target funds.
For more real-life case studies and examples, download the style analysis guide.
The Basics of Scenario Analysis
Since factors represent key returns drivers, you can minimally model the hypothetical effects of scenarios on factors, and then combine these with the style exposures of any number of investments to see the scenario investment returns.
Here’s the equation we use to model returns-based style analysis:
𝑟𝑡=𝛼+𝛽1𝑥𝑡1+𝛽2𝑥𝑡2+…+𝛽𝑘𝑥𝑡𝑘+𝜖𝑡
For any time period t, the return of the fund 𝑟𝑡 is modeled as the sum of the product of the fund’s exposure 𝛽𝑘 and the factor premia 𝑥kt for each of the k factors in the model. You can also include an α term to capture management skill beyond simple factor exposures.
Returns-based style analysis gives us the exposures—𝛽s. Think of 𝛼 as 𝛽0. Then, if you have an opinion on the future values of the factor premia 𝑥, you can calculate the expected return on the investment.
Let’s get into some examples.
How to Import Packages and Retrieve Funds Data
To conduct style analyses, you need two core categories of data.
Fund returns: Total return time series for the funds being analyzed.
Style factor data: Exposure and style premia.
While many providers offer historical returns data, here we’ll connect to the Morningstar data Python package to fetch data and statsmodels Python package for regressions.
To use the morningstar_data Python package, start by logging into Analytics Lab to retrieve your authentication token. Access full instructions on the developer site.
INPUT
# testing_morningstar_data.py
import os
import morningstar_data as md
os.environ['MD_AUTH_TOKEN']="paste copied token here"
md.direct.get_morningstar_data_sets()
import pandas as pd
import statsmodels.formula.api as smf
First, fetch the data needed for style analysis of equity funds. Obtain the unique tickers for the funds you plan to analyze. Use the investments() function that searches for matching securities based on a keyword.
In this case, the keyword will be known ticker values. Use the Vanguard Small-Cap Value ETF, or VBR, as an example.
For each ticker, find the top five keyword matches in the Morningstar database and store the top match in a list. Then convert the list to a dataframe for review.
INPUT
mstar_security_info = []
for t in tickers:
matches = md.direct.investments(keyword=t, count=5, only_surviving=True)
mstar_security_info.append(matches.head(1))
security_df = pd.concat(mstar_security_info, axis=0)
security_df
OUTPUT
If you can’t find the perfect matches in the first try, iterate the process. Going forward, use the SecId field.
Next, pull 60 months of returns for these funds. We’re using the Morningstar data package here.
INPUT
fund_returns_raw = md.direct.get_returns(
investments=security_df['SecId'].tolist(),
start_date='2019-06-30',
end_date='2024-05-31'
)
fund_returns_raw.head(3)
Pivot these returns so that you can later join them with the factor premia, using the dates as keys.
INPUT
fund_returns_wide = (
fund_returns_raw
.pivot(
index='Date',
columns='Id',
values='Monthly Return'
)
.div(100)
)
fund_returns_wide.head(3)
OUTPUT
The second ingredient for returns-based style analysis is the set of factor premia. The Fama-French Three-Factor Model incorporates, as the name suggests, three factors:
Small minus big, or excess returns of small-cap companies over large-cap companies.
High minus low, or excess returns of value stocks with a high book-to-price ratio over growth stocks with a low book-to-price ratio.
Market risk premium, or portfolio return less the risk-free rate of return.
The factor premia for this model are available in Prof. Kenneth French's data library. Use the monthly North American three-factor premia.
While you could get this data directly from the website and manipulate it with Pandas, the more convenient option is pandas-datareader.
INPUT
import pandas_datareader.data as web
ff_premia_raw = web.DataReader('North_America_3_Factors', 'famafrench')
Decimalize, make dates match the fund returns format, and rename to avoid hyphens.
INPUT
ff_premia = ff_premia_raw[0].div(100)
ff_premia.index = pd.to_datetime(ff_premia.index.to_timestamp()) + pd.tseries.offsets.MonthEnd()
ff_premia = ff_premia.rename(columns={'Mkt-RF': 'Market'})
ff_premia.head(3)
OUTPUT
How to Run Style Analysis with the Fama-French Model
Now you can combine the fund returns with factor premia and perform the regressions. Interpret the results of the regressions to understand the investment styles these funds pursue.
In the Fama-French model, funds returns in excess of the risk-free rate are the endogenous variable, or the variable determined by its relationship to other variables in the model. Create the two independent variables first.
Fetch the available fund return dates, premia dates, common dates, and risk-free rates.
INPUT
fr_idx = fund_returns_wide.index
ff_idx = ff_premia.index
cd = fr_idx.intersection(ff_idx)
rfr = ff_premia.loc[cd, 'RF']
Now create the excess returns dataframe.
INPUT
fund_returns_excess = fund_returns_wide.sub(rfr, axis=0)
Create a combined dataset.
ff_dataset = fund_returns_excess.join(ff_premia, how='inner', validate='1:1')
ff_dataset.head(3)
OUTPUT
Now perform the regression.
INPUT
vbr_ff = smf.ols(formula="FEUSA04ACH ~ Market + SMB + HML", data=ff_dataset).fit()
Case Study: Fund Style Analysis
As an example, let’s examine the results for the Vanguard Small-Cap Value ETF. If true to its moniker, the fund should show significant positive exposures to both the SMB and HML factors.
INPUT
vbr_ff.summary().tables[1]
OUTPUT
Yes—exposures to SMB and HML are statistically significant and positive. This means the fund is exposed to smaller companies, as measured by market capitalization, and value-oriented companies, as measured by ratio of their book value to market price.
We also see a statistically significant exposure to the market. This should be expected from most funds, however, since the market is the biggest driver of the performance for all stocks and consequently, funds.
Code Snippets for Custom Market Shocks
Next, let’s predict a correction in the broader market with a 20% drop in the market return. What if this correction is driven by large-cap technology stocks that tend to have a growth bent? This hypothetical correction scenario assumes a 2% premium for size and another 3% for value.
To calculate the expected return on the VBR ETF, take the product of these two sets of values. In Python, use numpy for a quick dot product calculation.
INPUT
import numpy as np
betas = np.array([1.0425, 0.6124, 0.4483]).reshape(-1,1)
premia = np.array([-0.20, 0.02, 0.03]).reshape(1,-1)
Expected return is the dot product of the two values.
INPUT
expected_return = premia @ betas
np.round(expected_return[0,0], 4)
OUTPUT
-0.1828
In this hypothetical tech stock correction scenario, the ETF generates an estimated negative 18.28% return. While this is negative (and fictitious), compare it to the overall drop in the market of negative 20%.
In this process, you only have to hypothesize three values: expected market returns and size and value factors. Combining these with returns-based style exposures of any investment, you can calculate the expected return of thousands of funds.
While market stresses and global conflicts affect the overall market, certain sections of the markets tend to perform better than others during these times. Flights to quality work in favor of assets that are perceived to be safe, such as bonds and large-cap stocks with healthy balance sheets. Scenario analysis helps to translate these beliefs to expected fund returns.
Unlock More Code Snippets for Fund Evaluation
With these code snippets, investment teams can make strategic choices about risk mitigation. These tips should give technical users more flexibility to customize analysis and manipulate data their way.
Looking for more ways to use Python for style analysis? The complete guide includes additional case studies, examples, and code snippets.