Scenario Analysis in Python: Advanced Investment Risk Analysis

Unlocking strategies and risk management through practical simulation techniques

Michael Whittle
Coinmonks
Published in
7 min readApr 9, 2024

--

Licensed Image from Adobe Stock

Before I introduce Scenario Analysis, I want to provide a brief recap of Monte Carlo Simulation, that I covered in my previous article, “Monte Carlo Simulation in Python: Advanced Investment Risk Analysis”.

Monte Carlo Simulation is a mathematical technique that allows you to account for risk in quantitative analysis and decision making. By generating a large number of potential scenarios for a given situation, it leverages randomness and statistical methods to understand the likelihood of various outcomes. This approach is particularly useful in trading and investing, including the volatile and unpredictable markets of cryptocurrencies like Bitcoin. By simulating thousands of different price paths for an asset based on historical volatility and price trends, investors can estimate the probability of reaching specific price levels. This method helps in assessing risk, making informed decisions, and strategising investments by understanding the range of possible outcomes and their likelihoods. In my previous article I provided a practical example in Python that will aid in understanding this concept.

Scenario Analysis, on the other hand, involves creating specific scenarios based on varying assumptions to see how they would potentially impact an investment. Unlike the broad and statistically driven nature of Monte Carlo Simulation, Scenario Analysis allows investors to focus on specific “what if” questions, examining the effects of distinct events such as regulatory changes, technological breakthroughs, or significant market shifts. This is common place for cryptocurrencies, and those who trade crypto will be very familiar with these common events. While both methods are used to evaluate potential future states, Monte Carlo Simulation offers a more comprehensive range of outcomes through its probabilistic approach, whereas Scenario Analysis provides a deeper dive into a smaller number of carefully chosen possibilities.

The choice between these two methodologies depends on the investor’s objectives. Monte Carlo Simulation is preferred when a broad view of potential outcomes is desired, providing a probability distribution of future asset prices. This is invaluable for understanding the overall risk and return profile of investments in highly volatile assets like Bitcoin. Scenario Analysis is more suited when the investor wishes to understand the impact of specific, discrete events or changes in conditions, allowing for targeted strategic planning.

A practical example of using Monte Carlo Simulation in investing in Bitcoin would involve assessing the risk of a significant investment in Bitcoin over a specific timeframe. An investor might simulate thousands of potential future paths for Bitcoin’s price based on its historical volatility and price trends. This simulation could reveal, for example, that there is a 70% chance that the investment’s value will increase by at least 20% over the next year, but also a 30% chance that it will decrease by more than 20%. Armed with this information, the investor can make a more informed decision about whether the potential returns are worth the risk. Additionally, the investor could use Scenario Analysis to understand how specific future events, such as the introduction of stricter cryptocurrency regulations or a major technological advancement in blockchain, might impact Bitcoin’s price and, consequently, the value of their investment.

In my previous article, there was feedback in the comments that the way I calculated the return, that is used as an input, could be improved. I intend to use log returns to calculate the returns which I believe will be more aligned with cryptocurrency and Bitcoin markets.

Demonstrating Scenario Analysis in Python

The first step is to retrieve some historical trading data to work with. I have a subscription with EODHD APIs, and that’s where I retrieve my data for analysis. They also have a Python library called “eodhd” that makes retrieving the data a trivial task. For this demonstration I’m going to retrieve the Bitcoin USD daily data.

python3 -m pip install eodhd -U
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from eodhd import APIClient
API_KEY = "<YOUR_KEY>"api = APIClient(API_KEY)
df = api.get_historical_data("BTC-USD.CC", "d", results=365)
print(df)
Screenshot by Author

For investments like Bitcoin, that can exhibit high volatility and significant price swings, calculating returns using log returns (logarithmic returns), from what I’ve read, and feedback from my previous article, is often considered the best approach. Log returns are advantageous for several reasons:

  1. Logarithmic returns are time additive. This means that the sum of log returns over consecutive periods equals the log return over the entire period, making them useful for analysing returns over time without compounding effects.
  2. They are more suitable for analysing assets with high volatility, such as Bitcoin, because log returns are symmetric. While the percentage change from £100 to £110 is the same as from £110 to £100 in absolute terms (10%), the log return from £100 to £110 is equal in magnitude but opposite in sign to the log return from £110 to £100. This symmetry simplifies calculations and interpretations in statistical models.
  3. Mitigation of the impact of large price fluctuations, which are common in cryptocurrency markets. Log returns reduce the impact of extreme values, making statistical analysis more stable.

Calculating Log Returns

Given the OHLC (Open, High, Low, Close) data I retrieved from EODHD APIs, the daily return is calculated using the closing prices of the asset. For log returns, the calculation from one day’s close to the next is:

Log Return = ln ( Close today / Close yesterday )

Where ln⁡ denotes the natural logarithm.

Something like this should work…

if __name__ == "__main__":
df = get_ohlc_data()

df["close"] = pd.to_numeric(df["close"], errors="coerce")
df.dropna(subset=["close"], inplace=True)
df["close"].fillna(value=df["close"].mean(), inplace=True)

close_prices = df["close"]
log_returns = np.log(close_prices / close_prices.shift(1))

print(log_returns)
Screenshot by Author

We will now want to define our scenarios. I’m going to try a 10% increase and decrease as a starting point.

scenarios = {
"Bullish Scenario": log_returns + np.log(1.10), # 10% increase applied correctly
"Bearish Scenario": log_returns + np.log(0.90), # 10% decrease applied correctly
"Stable Market": log_returns, # No change
}

print(scenarios)
Screenshot by Author
initial_investment = 10000  # Initial investment amount

# Apply scenarios and calculate outcomes
scenario_outcomes = {}
for scenario, returns in scenarios.items():
cumulative_returns = np.exp(returns.cumsum())
final_investment_value = initial_investment * cumulative_returns.iloc[-1]
scenario_outcomes[scenario] = final_investment_value

# Display outcomes
for scenario, outcome in scenario_outcomes.items():
print(f"{scenario}: £{outcome:,.2f}")
Screenshot by Author

Now that Bullish Scenario does look insane! I don’t think I’ve made a miscalculation. The scenario assumes a consistent positive log return, which has been further increased by an equivalent of a 10% daily return. The extremely high final investment value suggests that the compounded effect of applying a 10% daily return has been massively exaggerated. A 10% increase on each day is not realistic and would result in astronomical growth due to compounding, which is what’s reflected here.

It also shows an investment value dropping to £0.00, which suggests that the investment could be completely lost. This could occur if there were a consistent negative return that compounds to reduce the investment value to zero, although this is also unrealistic as it implies the value of Bitcoin dropping to zero and staying there.

This scenario is the baseline and represents what would happen if the daily log returns that we’ve calculated were to occur without any adjustment. It shows a more reasonable final investment value of £23,038.73 from an initial £10,000 investment.

This is my first attempt at this, and I don’t think the 10% increase and decrease looks right to me. I think it would be better to calculate a realistic daily increase or decrease. Maybe something like this would work better…

daily_volatility = 0.02

scenarios = {
"Bullish Scenario": log_returns + daily_volatility, # Add 2% volatility
"Bearish Scenario": log_returns - daily_volatility, # Subtract 2% volatility
"Stable Market": log_returns, # No change
}

It looks better, but probably needs some fine tuning…

Screenshot by Author

The Bullish and Bearish scenarios still look excessive to me, but I think this is closer to the end result we are looking for.

I’ve also only used 365 days of data. Maybe if you use several years of data, it would give a more realistic result taking into consideration multiple bull and bear markets.

plt.figure(figsize=(10, 6))
for scenario, returns in scenarios.items():
investment_value = initial_investment * np.exp(returns.cumsum())
investment_value.plot(label=scenario)
plt.legend()
plt.title("Bitcoin Investment Scenario Analysis with Log Returns")
plt.xlabel("Days")
plt.ylabel("Investment Value")
plt.tight_layout()
plt.savefig("investment_scenarios.png")
plt.show()
Image by Author

I hope you found this article interesting and useful. If you would like to be kept informed, please don’t forget to follow me and sign up to my email notifications.

If you liked this article, I recommend checking out EODHD APIs on Medium. They have some interesting articles.

Michael Whittle

--

--

Michael Whittle
Coinmonks

Solution Architect — CCIE R&S #24223 | Full-Stack / Blockchain / Web3 Developer | Security Specialist | PyCryptoBot Creator