<jupyter_start><jupyter_text>Value-at-Risk for Stocks: Delta-Normal Approach Lecture Notes by <NAME> (<EMAIL>)MATH 100.2: Topics in Financial Mathematics II \First Semester, S.Y. 2020-2021 \Ateneo de Manila University<jupyter_code>import numpy as np # Numerical Computing
import pandas as pd # Data wrangling
import matplotlib.pyplot as plt # Plotting
from statistics import NormalDist # statistical analysis

%matplotlib inline<jupyter_output><empty_output><jupyter_text>Are stock returns normally distributed?The Delta-Normal Approach assumes that the daily returns $R_t$ are normally distributed with mean 0 and variance $\sigma^2$. Is this a good assumption? Does the assumption of normality understate, properly state, or overstate the frequency of market disasters?Let's look at the TEL data and plot it.<jupyter_code>data_path = "https://raw.githubusercontent.com/ateneomathdept/math100.2_2021Sem1/main/data/lectures/TEL_2018.csv"
TEL_df = pd.read_csv(data_path, index_col="dt")
TEL_df
TEL_df["close"][::-1].plot() #pd.Series
plt.title("PLDT Historical Share Prices (Php)")
plt.show()<jupyter_output><empty_output><jupyter_text>Let $S_t$ denote the value of the stock at time $t$. The one-day continuous return $R_t$ of the stock is given by$$R_t = \ln\left(\frac{P_t}{P_{t-1}}\right).$$<jupyter_code>TEL_df["close"].shift(-1)
# creates a new column that shifts the prices d values up (or -d values down)
TEL_df["previous"] = TEL_df["close"].shift(-1)
TEL_df
def get_return(df):
    return np.log(df["close"]/df["previous"])
TEL_df["return"] = TEL_df.apply(get_return, axis=1)
TEL_df<jupyter_output><empty_output><jupyter_text>Let's fit a normal distribution to the data, and plot the histogram of data against it.<jupyter_code>from scipy.stats import norm # statistical analysis
# Get data, drop the last row with nan value (not a number)
data = TEL_df["return"].dropna()

# Fit a normal distribution to the data:
mu, std = norm.fit(data) # provides MLE of the parameters for the Gaussian curve which has the highest likelihood of fitting our dataset 

# Plot the histogram.
plt.hist(data, bins=40, density=True, alpha=0.6, color='g')

# Plot the PDF
xmin, xmax = plt.xlim() # gets the left and right limits of the x-axis of the current plot
x = np.linspace(xmin, xmax, 100) # array of 100 evenly-spaced numbers in the interval (xmin, xmax)
p = norm.pdf(x, mu, std) # array 
plt.plot(x, p, 'k', linewidth=2) # k for black
title = "Fit results: mu = %.4f,  std = %.4f" % (mu, std)
plt.title(title)

plt.show()<jupyter_output><empty_output><jupyter_text>The distribution looks approximately normal. Furthermore, the resulting MLE for the Gaussian mean is close to 0. Thus, by eyeballing, the normal distribution might be a good fit for the stock returns.However, if we  look to the extreme left and right of the histogram distribution, we can see the famous fat tails. The fat tails mean that extreme events occur more frequently in reality than what a normal distribution would predict. More evidence of that is how the actual distribution of daily TEL returns is skinnier in its center than the normal distribution. The skinny middle and the fat tails imply that the normal distribution might not be the best distribution to describe the stock returns. This fat-tail distribution is common among stock returns calculated from real data. To more accurately model the stock returns, researchers consider 2 regimes — a calm regime where we spend most of the time that is normally distributed (but with a lower volatility) and a regime with high volatility and extreme (sometimes terrible) returns.Nonethless, we cannot neglect that the normal distribution is still a good one to use. Practioners use the normal distribution as starting point for modelling stock returns as this is simple to use and implement. Any time we can model something with normal distributions, it makes life a lot easier. For example, the return of a portfolio consisting of many investments (each with normally distributed returns) is also normally distributed. And to describe an investment, we only need 2 values: the mean (a.k.a. the investment’s expected return) and the standard deviation (a.k.a. the investment’s risk). If we want to be thorough, we should also record the investment’s correlation with our overall portfolio.There are other statistical ways to check normality of the daily returns, and not just to eyeball:1. [QQ plot](https://towardsdatascience.com/what-in-the-world-are-qq-plots-20d0e41dece1)2. [Jarque-Bera Normality test](https://www.statisticshowto.com/jarque-bera-test/)Reference: https://towardsdatascience.com/are-stock-returns-normally-distributed-e0388d71267e  VaR for Stocks: Single-Asset Portfolio Consider a single-asset portfolio consisting of a long position on $N$ shares of a stock with current price $S_0$. Let $\Delta P$ denote the change in portfolio value.The **1-day 99\% VaR** of the portfolio is the number $|V|$ such that $$\mathbb{P}[\Delta P\geq V] = 0.99.$$ This is given by\begin{equation}\text{VaR}_{0.99} = |V| = NS_0\sigma\Phi^{-1}(0.99).\end{equation} **The 1-day 99\% VaR  is 1M pesos.**There is 99% level of confidence that the loss of the portfolio will not exceed 1M pesos over the next trading day.  Exercise 1:A portfolio consists of Php 10,000,000 worth of shares of stock A. Assume that the daily volatility is 2%. What is the portfolio's one-day 99% VaR?<jupyter_code>portval = 10000000 # N*S_0
sigma = 0.02
alpha = 0.99

quantile = NormalDist().inv_cdf(alpha)
var = portval * sigma *quantile
round(var, 4)
quantile<jupyter_output><empty_output><jupyter_text>Exercise 2:Today is February 23, 2018. You are a portfolio risk manager who is assigned to analyze the market risk of a portfolio of 700 PLDT (TEL) shares. What is the portfolio's one-day 99% VaR using the delta-normal approach?<jupyter_code># read the data
TEL_df = pd.read_csv(data_path) 

TEL_df
alpha = 0.99
N = 700
S_0 = TEL_df.loc[0, "close"]
S_0
# creates a new column that shifts the prices d values up (or -d values down)
TEL_df["previous"] = TEL_df["close"].shift(-1)
TEL_df
TEL_df["return"] = TEL_df.apply(get_return, axis=1)
TEL_df
# standard deviation of your stock returns
sigma = TEL_df["return"].std()
# returns the sample standard deviation (denom: N-1)
sigma
quantile = NormalDist().inv_cdf(alpha)
var = N * S_0 * sigma * quantile
print(f"The one-day 99% VaR is Php {round(var, 2)}.")
N * S_0
def one_day_alpha_percent_VaR_single_stock_delta_normal(df, N, alpha):
    
    """Returns the one-day 100(alpha)% VaR of a single stock using Delta Normal Approach.
    
    Parameters
    ----------
    df : pandas.DataFrame
        has two columns: (1) dt [str] and (2) closing price [float]
        assumes the dates are arranged from newest to oldest, and the date today is the date on the first row  
    N : int
        number of shares for the sole stock
    alpha : int
        the value to be used in calculting the 100(alpha)% VaR (e.g. 0.99, 0.95)
    
    Returns
    -------
    float (2 decimal places)
        one-day 100(alpha)% VaR of a single stock using Delta Normal Approach
    """

    S_0 = df.loc[0, "close"]
    
    # creates a new column that shifts the prices d values up (or -d values down)
    df["previous"] = df["close"].shift(-1)
    # get the daily returns
    df["return"] = df.apply(get_return, axis=1)
    
    # standard deviation of your stock returns
    sigma = df["return"].std()
    
    quantile = NormalDist().inv_cdf(alpha)
    var = N * S_0 * sigma * quantile
    
    return round(var, 2)
    
one_day_alpha_percent_VaR_single_stock_delta_normal(TEL_df, N=700, alpha=0.99)<jupyter_output><empty_output><jupyter_text>Today is February 23, 2018. You are a portfolio risk manager who is assigned to analyze the market risk of a portfolio of 1000 PLDT (TEL) shares. What is the portfolio's one-day 95% VaR using the delta-normal approach?<jupyter_code># read the data
TEL_df = pd.read_csv(data_path) 

one_day_alpha_percent_VaR_single_stock_delta_normal(TEL_df, N=1000, alpha=0.95)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.09340931615460853, 'fraction_numerical': 0.023909811694747273, 'mean_word_length': 4.514344262295082, 'pattern_counts': {'":': 0, '<': 31, '<?xml version=': 0, '>': 31, 'https://': 4, 'lorem ipsum': 0, 'www.': 1, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 1, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '7', 'dir': 'jupyter-structured-clean-dedup', 'id': '422030', 'license': 'MIT', 'n_tokens_mistral': 2646, 'n_tokens_neox': 2449, 'n_words': 1003, 'path': 'lectures/1Stocks/20210914_VaRforStocks_DeltaNormalApproach.ipynb', 'repo_name': 'ateneomathdept/math100.2_2021Sem1', 'size': '8103'}