{ "cells": [ { "cell_type": "markdown", "id": "5f2ea2cb", "metadata": {}, "source": [ "
" ] }, { "cell_type": "markdown", "id": "ab6f458d", "metadata": {}, "source": [ "This code analyzes the relationship between Tesla (TSLA) and S&P 500 (SPY) returns using linear regression. It downloads historical price data for TSLA and SPY, calculates daily returns, and plots them. A linear regression model is then used to estimate the alpha and beta of TSLA in relation to SPY. The code also constructs and evaluates a beta-hedged portfolio combining TSLA and SPY returns." ] }, { "cell_type": "code", "execution_count": null, "id": "4e952311", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "from statsmodels import regression\n", "import statsmodels.api as sm\n", "import matplotlib.pyplot as plt\n", "import yfinance as yf" ] }, { "cell_type": "markdown", "id": "60b5a085", "metadata": {}, "source": [ "Download historical price data for TSLA and SPY from Yahoo Finance" ] }, { "cell_type": "code", "execution_count": null, "id": "c84671a0", "metadata": {}, "outputs": [], "source": [ "data = yf.download(\"TSLA, SPY\", start=\"2014-01-01\", end=\"2015-01-01\")" ] }, { "cell_type": "markdown", "id": "81dc42f6", "metadata": {}, "source": [ "Extract adjusted close prices for TSLA and SPY" ] }, { "cell_type": "code", "execution_count": null, "id": "bd0ff214", "metadata": {}, "outputs": [], "source": [ "asset = data[\"Adj Close\"].TSLA\n", "benchmark = data[\"Adj Close\"].SPY" ] }, { "cell_type": "markdown", "id": "b77d7257", "metadata": {}, "source": [ "Calculate daily returns for TSLA and SPY and drop any missing values" ] }, { "cell_type": "code", "execution_count": null, "id": "8c2ec45f", "metadata": {}, "outputs": [], "source": [ "asset_returns = asset.pct_change().dropna()\n", "benchmark_returns = benchmark.pct_change().dropna()" ] }, { "cell_type": "markdown", "id": "4b54ff94", "metadata": {}, "source": [ "Plot daily returns for TSLA and SPY" ] }, { "cell_type": "code", "execution_count": null, "id": "9da3ec4c", "metadata": {}, "outputs": [], "source": [ "asset_returns.plot()\n", "benchmark_returns.plot()\n", "plt.ylabel(\"Daily Return\")\n", "plt.legend()" ] }, { "cell_type": "markdown", "id": "6864d36d", "metadata": {}, "source": [ "Extract daily returns values for linear regression analysis" ] }, { "cell_type": "code", "execution_count": null, "id": "23a6712a", "metadata": { "lines_to_next_cell": 1 }, "outputs": [], "source": [ "X = benchmark_returns.values\n", "Y = asset_returns.values" ] }, { "cell_type": "code", "execution_count": null, "id": "04e42249", "metadata": { "lines_to_next_cell": 1 }, "outputs": [], "source": [ "def linreg(x, y):\n", " \"\"\"Perform linear regression on two arrays.\n", " \n", " This function adds a constant to x, performs linear regression, \n", " and returns the alpha and beta coefficients.\n", " \n", " Parameters\n", " ----------\n", " x : np.ndarray\n", " The independent variable (e.g., benchmark returns).\n", " y : np.ndarray\n", " The dependent variable (e.g., asset returns).\n", " \n", " Returns\n", " -------\n", " alpha : float\n", " The intercept of the regression line.\n", " beta : float\n", " The slope of the regression line.\n", " \"\"\"\n", "\n", " # Add a column of 1s to fit alpha\n", " x = sm.add_constant(x)\n", "\n", " # Fit the OLS regression model to the data\n", " model = regression.linear_model.OLS(y, x).fit()\n", "\n", " # Remove the constant now that we're done\n", " x = x[:, 1]\n", "\n", " return model.params[0], model.params[1]" ] }, { "cell_type": "markdown", "id": "789ba4a8", "metadata": {}, "source": [ "Calculate alpha and beta for TSLA relative to SPY using linear regression" ] }, { "cell_type": "code", "execution_count": null, "id": "ffd2463d", "metadata": {}, "outputs": [], "source": [ "alpha, beta = linreg(X, Y)\n", "print(f\"Alpha: {alpha}\")\n", "print(f\"Beta: {beta}\")" ] }, { "cell_type": "markdown", "id": "4a34f58e", "metadata": {}, "source": [ "Generate a range of X values for plotting the regression line" ] }, { "cell_type": "code", "execution_count": null, "id": "70e5fc38", "metadata": {}, "outputs": [], "source": [ "X2 = np.linspace(X.min(), X.max(), 100)" ] }, { "cell_type": "markdown", "id": "cac07ff2", "metadata": {}, "source": [ "Calculate the predicted Y values (regression line) for the generated X values" ] }, { "cell_type": "code", "execution_count": null, "id": "523900e1", "metadata": {}, "outputs": [], "source": [ "Y_hat = X2 * beta + alpha" ] }, { "cell_type": "markdown", "id": "2d92649d", "metadata": {}, "source": [ "Plot the raw data points (TSLA vs. SPY daily returns)" ] }, { "cell_type": "code", "execution_count": null, "id": "79d7840d", "metadata": {}, "outputs": [], "source": [ "plt.scatter(X, Y, alpha=0.3)\n", "plt.xlabel(\"SPY Daily Return\")\n", "plt.ylabel(\"TSLA Daily Return\")" ] }, { "cell_type": "markdown", "id": "90e244dc", "metadata": {}, "source": [ "Plot the regression line on the scatter plot" ] }, { "cell_type": "code", "execution_count": null, "id": "6ce9f245", "metadata": {}, "outputs": [], "source": [ "plt.plot(X2, Y_hat, 'r', alpha=0.9);" ] }, { "cell_type": "markdown", "id": "7cf8a6a8", "metadata": {}, "source": [ "Construct a beta-hedged portfolio by combining TSLA and SPY returns" ] }, { "cell_type": "code", "execution_count": null, "id": "ada8b88c", "metadata": {}, "outputs": [], "source": [ "portfolio = -1 * beta * benchmark_returns + asset_returns\n", "portfolio.name = \"TSLA + Hedge\"" ] }, { "cell_type": "markdown", "id": "ad5ee872", "metadata": {}, "source": [ "Plot the returns of the beta-hedged portfolio, TSLA, and SPY" ] }, { "cell_type": "code", "execution_count": null, "id": "163b687b", "metadata": {}, "outputs": [], "source": [ "portfolio.plot(alpha=0.9)\n", "benchmark_returns.plot(alpha=0.5)\n", "asset_returns.plot(alpha=0.5)\n", "plt.ylabel(\"Daily Return\")\n", "plt.legend();" ] }, { "cell_type": "markdown", "id": "d8eb7cbd", "metadata": {}, "source": [ "Print the mean and standard deviation of the beta-hedged portfolio and TSLA returns" ] }, { "cell_type": "code", "execution_count": null, "id": "99d31898", "metadata": {}, "outputs": [], "source": [ "print(\"means: \", portfolio.mean(), asset_returns.mean())\n", "print(\"volatilities: \", portfolio.std(), asset_returns.std())" ] }, { "cell_type": "markdown", "id": "cab17da9", "metadata": {}, "source": [ "Extract portfolio values for further linear regression analysis" ] }, { "cell_type": "code", "execution_count": null, "id": "81a44668", "metadata": {}, "outputs": [], "source": [ "P = portfolio.values" ] }, { "cell_type": "markdown", "id": "a926759c", "metadata": {}, "source": [ "Calculate alpha and beta for the beta-hedged portfolio using linear regression" ] }, { "cell_type": "code", "execution_count": null, "id": "383c99d8", "metadata": {}, "outputs": [], "source": [ "alpha, beta = linreg(X, P)\n", "print('alpha: ' + str(alpha))\n", "print('beta: ' + str(beta))" ] }, { "cell_type": "markdown", "id": "3fdca098", "metadata": {}, "source": [ "PyQuant News is where finance practitioners level up with Python for quant finance, algorithmic trading, and market data analysis. Looking to get started? Check out the fastest growing, top-selling course to get started with Python for quant finance. For educational purposes. Not investment advise. Use at your own risk." ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "-all", "main_language": "python", "notebook_metadata_filter": "-all" } }, "nbformat": 4, "nbformat_minor": 5 }