├── 01_MomentumStrategy_StockAnalysis.ipynb ├── 02_BreakoutStrategy_StockAnalysis.ipynb ├── 03_SmartBeta_PortfolioOptimization.ipynb ├── 04_AlphaResearch_FactorModeling.ipynb ├── 05_PortfolioOptimization_Theory_Reality.ipynb ├── 06_AutocorrelationExplained.ipynb ├── 07_CrossCorrelation_TechStocks.ipynb ├── 08_Ljung_Box_Q_Test.ipynb ├── 09_Profiting_Pair_Trading.ipynb ├── 10_Cointegration_Multiple_Asset_Pairs.ipynb ├── 11_AutomatedDetection_Support_Resistance.ipynb ├── 12_Supercharge_AssetRebalancing.ipynb └── README.md /01_MomentumStrategy_StockAnalysis.ipynb: -------------------------------------------------------------------------------- 1 | {"nbformat":4,"nbformat_minor":0,"metadata":{"colab":{"provenance":[],"authorship_tag":"ABX9TyPM9TbDXxM/5cTCfbRwq8zq"},"kernelspec":{"name":"python3","display_name":"Python 3"},"language_info":{"name":"python"}},"cells":[{"cell_type":"code","execution_count":null,"metadata":{"id":"VLZ7fieiCH4N"},"outputs":[],"source":["# Import necessary libraries\n","import yfinance as yf\n","import pandas as pd\n","from datetime import datetime, timedelta\n","import numpy as np\n","import json\n","import plotly.graph_objects as go"]},{"cell_type":"markdown","source":["# Part 1: Fetching Stock Data"],"metadata":{"id":"4omqdwWVfs2j"}},{"cell_type":"code","source":["def fetch_stock_data(ticker_list, years=5):\n"," end_date = datetime.now()\n"," start_date = end_date - timedelta(days=years * 365)\n"," stock_data = pd.DataFrame()\n","\n"," for ticker in ticker_list:\n"," stock = yf.Ticker(ticker)\n"," hist_data = stock.history(period='1d', start=start_date, end=end_date)\n"," close_data = hist_data['Close'].rename(ticker)\n"," stock_data = pd.merge(stock_data, pd.DataFrame(close_data), left_index=True, right_index=True, how='outer')\n"," return stock_data\n","\n","# Fetch the data\n","ticker_list = ['AAPL', 'AMZN', 'MSFT', 'GOOGL', 'META', 'TSLA', 'NVDA', 'ADBE', 'NFLX', 'INTC']\n","years = 5\n","daily_data = fetch_stock_data(ticker_list, years)\n","\n","daily_data"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":455},"id":"5fO47wT9HQTh","executionInfo":{"status":"ok","timestamp":1694458191987,"user_tz":180,"elapsed":5026,"user":{"displayName":"Hugo","userId":"11126641400007389172"}},"outputId":"f55d5dd2-e74c-4220-cb29-97c47877c956"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":[" AAPL AMZN MSFT GOOGL \\\n","Date \n","2018-09-12 00:00:00-04:00 52.931549 99.500000 105.837601 58.580002 \n","2018-09-13 00:00:00-04:00 54.210121 99.493500 106.974503 59.106998 \n","2018-09-14 00:00:00-04:00 53.594776 98.509499 107.410316 58.898998 \n","2018-09-17 00:00:00-04:00 52.167751 95.401497 106.244987 57.991501 \n","2018-09-18 00:00:00-04:00 52.253948 97.052498 107.258720 58.355499 \n","... ... ... ... ... \n","2023-09-05 00:00:00-04:00 189.699997 137.270004 333.549988 135.770004 \n","2023-09-06 00:00:00-04:00 182.910004 135.360001 332.880005 134.460007 \n","2023-09-07 00:00:00-04:00 177.559998 137.850006 329.910004 135.259995 \n","2023-09-08 00:00:00-04:00 178.179993 138.229996 334.269989 136.380005 \n","2023-09-11 00:00:00-04:00 179.554794 142.520004 337.945007 136.949997 \n","\n"," META TSLA NVDA ADBE \\\n","Date \n","2018-09-12 00:00:00-04:00 162.000000 19.369333 66.468536 267.790009 \n","2018-09-13 00:00:00-04:00 161.360001 19.297333 67.246727 268.519989 \n","2018-09-14 00:00:00-04:00 162.320007 19.680000 68.508194 274.690002 \n","2018-09-17 00:00:00-04:00 160.580002 19.656000 67.888626 268.250000 \n","2018-09-18 00:00:00-04:00 160.300003 18.997334 67.167412 270.790009 \n","... ... ... ... ... \n","2023-09-05 00:00:00-04:00 300.149994 256.489990 485.440033 564.880005 \n","2023-09-06 00:00:00-04:00 299.170013 251.919998 470.609985 561.940002 \n","2023-09-07 00:00:00-04:00 298.670013 251.490005 462.410004 560.460022 \n","2023-09-08 00:00:00-04:00 297.890015 248.500000 455.720001 560.359985 \n","2023-09-11 00:00:00-04:00 307.040009 274.359985 450.220001 564.559998 \n","\n"," NFLX INTC \n","Date \n","2018-09-12 00:00:00-04:00 369.950012 39.068569 \n","2018-09-13 00:00:00-04:00 368.149994 39.625080 \n","2018-09-14 00:00:00-04:00 364.559998 39.598984 \n","2018-09-17 00:00:00-04:00 350.350006 39.494640 \n","2018-09-18 00:00:00-04:00 367.649994 40.085926 \n","... ... ... \n","2023-09-05 00:00:00-04:00 448.679993 36.709999 \n","2023-09-06 00:00:00-04:00 445.760010 36.980000 \n","2023-09-07 00:00:00-04:00 443.140015 38.180000 \n","2023-09-08 00:00:00-04:00 442.799988 38.009998 \n","2023-09-11 00:00:00-04:00 447.609985 38.564999 \n","\n","[1257 rows x 10 columns]"],"text/html":["\n","
\n","
\n","\n","\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
AAPLAMZNMSFTGOOGLMETATSLANVDAADBENFLXINTC
Date
2018-09-12 00:00:00-04:0052.93154999.500000105.83760158.580002162.00000019.36933366.468536267.790009369.95001239.068569
2018-09-13 00:00:00-04:0054.21012199.493500106.97450359.106998161.36000119.29733367.246727268.519989368.14999439.625080
2018-09-14 00:00:00-04:0053.59477698.509499107.41031658.898998162.32000719.68000068.508194274.690002364.55999839.598984
2018-09-17 00:00:00-04:0052.16775195.401497106.24498757.991501160.58000219.65600067.888626268.250000350.35000639.494640
2018-09-18 00:00:00-04:0052.25394897.052498107.25872058.355499160.30000318.99733467.167412270.790009367.64999440.085926
.................................
2023-09-05 00:00:00-04:00189.699997137.270004333.549988135.770004300.149994256.489990485.440033564.880005448.67999336.709999
2023-09-06 00:00:00-04:00182.910004135.360001332.880005134.460007299.170013251.919998470.609985561.940002445.76001036.980000
2023-09-07 00:00:00-04:00177.559998137.850006329.910004135.259995298.670013251.490005462.410004560.460022443.14001538.180000
2023-09-08 00:00:00-04:00178.179993138.229996334.269989136.380005297.890015248.500000455.720001560.359985442.79998838.009998
2023-09-11 00:00:00-04:00179.554794142.520004337.945007136.949997307.040009274.359985450.220001564.559998447.60998538.564999
\n","

1257 rows × 10 columns

\n","
\n","
\n","\n","
\n"," \n","\n"," \n","\n"," \n","
\n","\n","\n","
\n"," \n","\n","\n","\n"," \n","
\n","
\n","
\n"]},"metadata":{},"execution_count":2}]},{"cell_type":"markdown","source":["# Part 2: Momentum Strategy Simulation"],"metadata":{"id":"E1DoymIxf4VR"}},{"cell_type":"code","source":["# Resample data to different frequencies: daily, weekly, monthly\n","def resample_data(data, period):\n"," if period == 'D':\n"," return data\n"," elif period == 'W':\n"," return data.resample('W').last()\n"," elif period == 'M':\n"," return data.resample('M').last()"],"metadata":{"id":"0F6rzaKTCIOm"},"execution_count":null,"outputs":[]},{"cell_type":"code","source":["# Simulate a simple momentum strategy based on log returns\n","def simulate_momentum_strategy(data, initial_amount, top_n, tax_rate, period='M'):\n"," data = resample_data(data, period)\n"," log_returns = np.log(data / data.shift(1))\n"," simulation_details = pd.DataFrame(index=log_returns.index,\n"," columns=['Selected Stocks', 'Profit Before Tax', 'Tax Paid', 'Portfolio Value'])\n"," cash = initial_amount\n","\n"," # Logic to select top stocks and calculate portfolio value\n"," for i in range(0, len(log_returns) - 1):\n"," # Identify the top_n performing stocks based on past log returns\n"," top_stocks = log_returns.iloc[i].sort_values(ascending=False).head(top_n)\n"," # Filter out stocks with negative returns\n"," top_stocks = top_stocks[top_stocks > 0]\n","\n"," if not top_stocks.empty:\n"," simulation_details.loc[log_returns.index[i + 1], 'Selected Stocks'] = json.dumps(top_stocks.index.tolist())\n"," # Calculate the amount to allocate for each stock\n"," num_stocks = len(top_stocks)\n"," allocation_per_stock = cash / num_stocks\n"," # Calculate new portfolio value based on the next day's returns\n"," new_value = sum(allocation_per_stock * np.exp(log_returns.loc[log_returns.index[i + 1], stock]) for stock in top_stocks.index)\n"," # Calculate and deduct tax if there is a profit\n"," profit = new_value - cash\n"," simulation_details.loc[log_returns.index[i + 1], 'Profit Before Tax'] = round(profit, 2)\n","\n"," if profit > 0:\n"," tax = profit * tax_rate\n"," new_value -= tax\n"," simulation_details.loc[log_returns.index[i + 1], 'Tax Paid'] = round(tax, 2)\n"," simulation_details.loc[log_returns.index[i + 1], 'Portfolio Value'] = round(new_value, 2)\n","\n"," else:\n"," # No allocation, so portfolio value remains the same\n"," simulation_details.loc[log_returns.index[i + 1], 'Portfolio Value'] = cash\n"," # Update cash amount for the next round\n"," cash = simulation_details.loc[log_returns.index[i + 1], 'Portfolio Value']\n"," # Assign the initial amount to the first row\n"," simulation_details.loc[log_returns.index[0], 'Portfolio Value'] = initial_amount\n"," return simulation_details\n","\n","# Configuration for the momentum strategy simulation\n","initial_amount = 100000\n","top_n = 3\n","tax_rate = 0.15\n","frequency = 'M'\n","simulation_details = simulate_momentum_strategy(daily_data, initial_amount, top_n, tax_rate, frequency)\n","\n","simulation_details"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":455},"id":"ea2HGhP1REZN","executionInfo":{"status":"ok","timestamp":1694458192317,"user_tz":180,"elapsed":334,"user":{"displayName":"Hugo","userId":"11126641400007389172"}},"outputId":"2e457c54-7f85-4682-8502-6ef255f65866"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":[" Selected Stocks Profit Before Tax \\\n","Date \n","2018-09-30 00:00:00-04:00 NaN NaN \n","2018-10-31 00:00:00-04:00 NaN NaN \n","2018-11-30 00:00:00-05:00 [\"TSLA\"] 3901.34 \n","2018-12-31 00:00:00-05:00 [\"INTC\", \"AMZN\", \"MSFT\"] -8391.44 \n","2019-01-31 00:00:00-05:00 NaN NaN \n","... ... ... \n","2023-05-31 00:00:00-04:00 [\"META\", \"MSFT\", \"GOOGL\"] 44876.21 \n","2023-06-30 00:00:00-04:00 [\"NVDA\", \"TSLA\", \"NFLX\"] 79589.96 \n","2023-07-31 00:00:00-04:00 [\"TSLA\", \"ADBE\", \"NVDA\"] 42972.46 \n","2023-08-31 00:00:00-04:00 [\"ADBE\", \"META\", \"GOOGL\"] -3998.75 \n","2023-09-30 00:00:00-04:00 [\"NVDA\", \"AMZN\", \"GOOGL\"] -9247.26 \n","\n"," Tax Paid Portfolio Value \n","Date \n","2018-09-30 00:00:00-04:00 NaN 100000 \n","2018-10-31 00:00:00-04:00 NaN 100000 \n","2018-11-30 00:00:00-05:00 585.2 103316.14 \n","2018-12-31 00:00:00-05:00 NaN 94924.7 \n","2019-01-31 00:00:00-05:00 NaN 94924.7 \n","... ... ... \n","2023-05-31 00:00:00-04:00 6731.43 462416.15 \n","2023-06-30 00:00:00-04:00 11938.49 530067.61 \n","2023-07-31 00:00:00-04:00 6445.87 566594.2 \n","2023-08-31 00:00:00-04:00 NaN 562595.45 \n","2023-09-30 00:00:00-04:00 NaN 553348.19 \n","\n","[61 rows x 4 columns]"],"text/html":["\n","
\n","
\n","\n","\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
Selected StocksProfit Before TaxTax PaidPortfolio Value
Date
2018-09-30 00:00:00-04:00NaNNaNNaN100000
2018-10-31 00:00:00-04:00NaNNaNNaN100000
2018-11-30 00:00:00-05:00[\"TSLA\"]3901.34585.2103316.14
2018-12-31 00:00:00-05:00[\"INTC\", \"AMZN\", \"MSFT\"]-8391.44NaN94924.7
2019-01-31 00:00:00-05:00NaNNaNNaN94924.7
...............
2023-05-31 00:00:00-04:00[\"META\", \"MSFT\", \"GOOGL\"]44876.216731.43462416.15
2023-06-30 00:00:00-04:00[\"NVDA\", \"TSLA\", \"NFLX\"]79589.9611938.49530067.61
2023-07-31 00:00:00-04:00[\"TSLA\", \"ADBE\", \"NVDA\"]42972.466445.87566594.2
2023-08-31 00:00:00-04:00[\"ADBE\", \"META\", \"GOOGL\"]-3998.75NaN562595.45
2023-09-30 00:00:00-04:00[\"NVDA\", \"AMZN\", \"GOOGL\"]-9247.26NaN553348.19
\n","

61 rows × 4 columns

\n","
\n","
\n","\n","
\n"," \n","\n"," \n","\n"," \n","
\n","\n","\n","
\n"," \n","\n","\n","\n"," \n","
\n","
\n","
\n"]},"metadata":{},"execution_count":4}]},{"cell_type":"markdown","source":["# Part 3: Simulating Individual Stock Investments"],"metadata":{"id":"guemjGAZf_X1"}},{"cell_type":"code","source":["# Simulate how each individual stock would have performed over the same period\n","def track_individual_investments(data, initial_amount, simulation_details, period='W'):\n"," # Resample data based on the specified period\n"," data = resample_data(data, period)\n"," # Calculate returns based on the resampled data\n"," returns = data.pct_change()\n"," # Create a new DataFrame to store individual stock values over time\n"," individual_investments = pd.DataFrame(index=data.index, columns=data.columns)\n"," for stock in data.columns:\n"," # Simulate an investment in each stock\n"," individual_investments[stock] = (1 + returns[stock]).cumprod() * initial_amount\n"," # Include the Portfolio Value from the momentum strategy\n"," individual_investments['Portfolio Value'] = simulation_details['Portfolio Value']\n"," individual_investments['Baseline'] = individual_investments.iloc[:, :-1].T.mean()\n"," # Adjust the first values to match the Initial Amount.\n"," individual_investments.iloc[0, :] = initial_amount\n"," return individual_investments.fillna(0).astype(int)\n","\n","individual_investments_df = track_individual_investments(daily_data, initial_amount, simulation_details, frequency)\n","\n","individual_investments_df"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":455},"id":"wvmfXlyySl-V","executionInfo":{"status":"ok","timestamp":1694458192318,"user_tz":180,"elapsed":12,"user":{"displayName":"Hugo","userId":"11126641400007389172"}},"outputId":"491ce980-6a9a-41c7-e6f2-f31b3b6b9586"},"execution_count":null,"outputs":[{"output_type":"execute_result","data":{"text/plain":[" AAPL AMZN MSFT GOOGL META TSLA \\\n","Date \n","2018-09-30 00:00:00-04:00 100000 100000 100000 100000 100000 100000 \n","2018-10-31 00:00:00-04:00 96952 79780 93389 90348 92295 127401 \n","2018-11-30 00:00:00-05:00 79384 84381 97376 91928 85497 132371 \n","2018-12-31 00:00:00-05:00 70120 74986 89191 86569 79709 125694 \n","2019-01-31 00:00:00-05:00 73988 85807 91703 93273 101355 115957 \n","... ... ... ... ... ... ... \n","2023-05-31 00:00:00-04:00 327496 120399 302420 203582 160963 1155323 \n","2023-06-30 00:00:00-04:00 358389 130164 313609 198329 174498 1483004 \n","2023-07-31 00:00:00-04:00 362971 133479 309355 219902 193724 1515069 \n","2023-08-31 00:00:00-04:00 347587 137803 302479 225618 179916 1462099 \n","2023-09-30 00:00:00-04:00 332203 142306 311878 226911 186695 1554330 \n","\n"," NVDA ADBE NFLX INTC Portfolio Value \\\n","Date \n","2018-09-30 00:00:00-04:00 100000 100000 100000 100000 100000 \n","2018-10-31 00:00:00-04:00 75023 91039 80661 99133 100000 \n","2018-11-30 00:00:00-05:00 58214 92939 76478 104927 103316 \n","2018-12-31 00:00:00-05:00 47553 83808 71541 99863 94924 \n","2019-01-31 00:00:00-05:00 51204 91802 90743 100267 94924 \n","... ... ... ... ... ... \n","2023-05-31 00:00:00-04:00 543134 154765 105639 76183 462416 \n","2023-06-30 00:00:00-04:00 607338 181140 117737 81030 530067 \n","2023-07-31 00:00:00-04:00 670897 202322 117330 86676 566594 \n","2023-08-31 00:00:00-04:00 708599 207201 115916 85455 562595 \n","2023-09-30 00:00:00-04:00 646443 209135 119640 93784 553348 \n","\n"," Baseline \n","Date \n","2018-09-30 00:00:00-04:00 100000 \n","2018-10-31 00:00:00-04:00 92602 \n","2018-11-30 00:00:00-05:00 90350 \n","2018-12-31 00:00:00-05:00 82903 \n","2019-01-31 00:00:00-05:00 89610 \n","... ... \n","2023-05-31 00:00:00-04:00 314990 \n","2023-06-30 00:00:00-04:00 364524 \n","2023-07-31 00:00:00-04:00 381173 \n","2023-08-31 00:00:00-04:00 377267 \n","2023-09-30 00:00:00-04:00 382332 \n","\n","[61 rows x 12 columns]"],"text/html":["\n","
\n","
\n","\n","\n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n"," \n","
AAPLAMZNMSFTGOOGLMETATSLANVDAADBENFLXINTCPortfolio ValueBaseline
Date
2018-09-30 00:00:00-04:00100000100000100000100000100000100000100000100000100000100000100000100000
2018-10-31 00:00:00-04:0096952797809338990348922951274017502391039806619913310000092602
2018-11-30 00:00:00-05:00793848438197376919288549713237158214929397647810492710331690350
2018-12-31 00:00:00-05:007012074986891918656979709125694475538380871541998639492482903
2019-01-31 00:00:00-05:00739888580791703932731013551159575120491802907431002679492489610
.......................................
2023-05-31 00:00:00-04:00327496120399302420203582160963115532354313415476510563976183462416314990
2023-06-30 00:00:00-04:00358389130164313609198329174498148300460733818114011773781030530067364524
2023-07-31 00:00:00-04:00362971133479309355219902193724151506967089720232211733086676566594381173
2023-08-31 00:00:00-04:00347587137803302479225618179916146209970859920720111591685455562595377267
2023-09-30 00:00:00-04:00332203142306311878226911186695155433064644320913511964093784553348382332
\n","

61 rows × 12 columns

\n","
\n","
\n","\n","
\n"," \n","\n"," \n","\n"," \n","
\n","\n","\n","
\n"," \n","\n","\n","\n"," \n","
\n","
\n","
\n"]},"metadata":{},"execution_count":5}]},{"cell_type":"markdown","source":["# Part 4: Calculating Metrics"],"metadata":{"id":"G8fkKospgDgz"}},{"cell_type":"code","source":["from scipy.stats import ttest_1samp\n","\n","def calculate_sharpe_ratio(returns, annual_risk_free_rate=0.01, frequency='D'):\n"," # Adjust the risk-free rate based on the frequency\n"," if frequency == 'D':\n"," adjusted_rfr = (1 + annual_risk_free_rate) ** (1/252) - 1\n"," elif frequency == 'W':\n"," adjusted_rfr = (1 + annual_risk_free_rate) ** (1/52) - 1\n"," elif frequency == 'M':\n"," adjusted_rfr = (1 + annual_risk_free_rate) ** (1/12) - 1\n","\n"," excess_returns = returns - adjusted_rfr\n"," return excess_returns.mean() / excess_returns.std()\n","\n","def t_test_portfolio_returns(portfolio_returns, bench_annual_rate=0.1, frequency='D'):\n"," # Adjust the risk-free rate based on the frequency\n"," if frequency == 'D':\n"," adjusted_rfr = (1 + bench_annual_rate) ** (1/252) - 1\n"," elif frequency == 'W':\n"," adjusted_rfr = (1 + bench_annual_rate) ** (1/52) - 1\n"," elif frequency == 'M':\n"," adjusted_rfr = (1 + bench_annual_rate) ** (1/12) - 1\n","\n"," t_stat, p_value = ttest_1samp(portfolio_returns[1:], adjusted_rfr) # [1:] to exclude the NaN from pct_change\n"," return t_stat, p_value\n","\n","def calculate_metrics(dataframe, initial_amount, bench_annual_rate, frequency='D'):\n"," # Calculate the final and relative values\n"," final_values = dataframe.iloc[-1]\n"," relative_values = final_values / initial_amount - 1 # Subtract 1 to get the growth proportion\n","\n"," # Calculate mean return and Sharpe Ratio\n"," returns = dataframe.pct_change()\n","\n"," if frequency == 'D':\n"," annualization_factor = 252\n"," elif frequency == 'W':\n"," annualization_factor = 52\n"," elif frequency == 'M':\n"," annualization_factor = 12\n","\n"," # Corrected annualization of mean returns\n"," mean_returns = (1 + returns.mean()) ** annualization_factor - 1\n"," sharpes = returns.apply(calculate_sharpe_ratio, annual_risk_free_rate=0.01, frequency=frequency)\n","\n"," # Test if the portfolio returns are greater than the adjusted risk-free rate\n"," portfolio_returns = dataframe['Portfolio Value'].pct_change()\n"," t_stat, p_value = t_test_portfolio_returns(portfolio_returns, bench_annual_rate, frequency=frequency)\n","\n"," return final_values, relative_values, mean_returns, sharpes, t_stat, p_value / 2\n","\n","bench_annual_rate = 0.1\n","\n","# Calculate the metrics\n","final_values, relative_values, mean_returns, sharpes, t_stat, p_value = calculate_metrics(individual_investments_df, initial_amount, bench_annual_rate, frequency)"],"metadata":{"id":"MtSuikszgGTB"},"execution_count":null,"outputs":[]},{"cell_type":"markdown","source":["# Part 5: Visualization"],"metadata":{"id":"ozfr0dhUjweq"}},{"cell_type":"code","source":["import plotly.graph_objects as go\n","from plotly.subplots import make_subplots\n","\n","def plot_combined_charts(dataframe, final_values, relative_values, sharpes, mean_returns):\n"," labels = final_values.index\n"," colors = ['#636EFA', '#EF553B', '#00CC96', '#AB63FA', '#FFA15A']\n","\n"," fig = make_subplots(rows=3, cols=2,\n"," subplot_titles=('Portfolio Value Over Time',\n"," '',\n"," 'Final Investment Values',\n"," 'Relative Investment Growth',\n"," 'Annualized Sharpe Ratios',\n"," 'Annualized Mean Returns'),\n"," vertical_spacing=0.08)\n","\n"," # Portfolio Value line chart\n"," fig.add_trace(go.Scatter(x=dataframe.index,\n"," y=dataframe['Portfolio Value'],\n"," mode='lines',\n"," name='Portfolio Value',\n"," line=dict(color=colors[0], width=2.5)),\n"," row=1, col=1)\n","\n"," # T-test and P-value\n"," significance_text = f\"T-test: {t_stat:.2f}
P-value: {p_value:.5f}\"\n"," if t_stat > 2 and p_value < 0.05:\n"," significance_text += f\"
Significantly different from {bench_annual_rate:.0%} per year!\"\n","\n"," fig.add_annotation(\n"," text=significance_text,\n"," showarrow=False,\n"," xref=\"x2\", yref=\"y2\",\n"," x=0.5, y=0.5,\n"," font=dict(size=15),\n"," bgcolor=\"white\",\n"," align=\"center\"\n"," )\n","\n"," # Final values\n"," fig.add_trace(go.Bar(x=labels,\n"," y=final_values.values,\n"," name='Final Values ($)',\n"," text=[f\"${v:,.2f}\" for v in final_values.values],\n"," textposition='outside',\n"," marker_color=colors[1]),\n"," row=2, col=1)\n","\n"," # Relative Growth\n"," fig.add_trace(go.Bar(x=labels,\n"," y=relative_values.values,\n"," name='Relative Growth',\n"," text=[f\"{v:.2%}\" for v in relative_values.values],\n"," textposition='outside',\n"," marker_color=colors[2]),\n"," row=2, col=2)\n","\n"," # Sharpe Ratios\n"," fig.add_trace(go.Bar(x=labels,\n"," y=sharpes.values,\n"," name='Annualized Sharpe Ratio',\n"," text=[f\"{v:.2f}\" for v in sharpes.values],\n"," textposition='outside',\n"," marker_color=colors[3]),\n"," row=3, col=1)\n","\n"," # Mean Returns\n"," fig.add_trace(go.Bar(x=labels,\n"," y=mean_returns.values,\n"," name='Annualized Mean Returns',\n"," text=[f\"{v:.2%}\" for v in mean_returns.values],\n"," textposition='outside',\n"," marker_color=colors[4]),\n"," row=3, col=2)\n","\n"," # Update layout\n"," fig.update_layout(title_text=\"Investment Results Overview\",\n"," title_font=dict(size=24, color='black', family=\"Arial Black\"),\n"," title_pad=dict(t=10),\n"," showlegend=False,\n"," height=1500,\n"," title_x=0.5,\n"," bargap=0.05,\n"," )\n","\n"," fig.show()\n","\n","plot_combined_charts(individual_investments_df, final_values, relative_values, sharpes, mean_returns)"],"metadata":{"colab":{"base_uri":"https://localhost:8080/","height":1000},"id":"Rw3bg208jil6","executionInfo":{"status":"ok","timestamp":1694458194203,"user_tz":180,"elapsed":755,"user":{"displayName":"Hugo","userId":"11126641400007389172"}},"outputId":"9eb86831-72ca-473e-ac87-0ab47a81dbf1"},"execution_count":null,"outputs":[{"output_type":"display_data","data":{"text/html":["\n","\n","\n","
\n","
\n","\n",""]},"metadata":{}}]}]} -------------------------------------------------------------------------------- /08_Ljung_Box_Q_Test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "provenance": [], 7 | "toc_visible": true 8 | }, 9 | "kernelspec": { 10 | "name": "python3", 11 | "display_name": "Python 3" 12 | }, 13 | "language_info": { 14 | "name": "python" 15 | } 16 | }, 17 | "cells": [ 18 | { 19 | "cell_type": "markdown", 20 | "source": [ 21 | "# Ljung-Box Q-Test" 22 | ], 23 | "metadata": { 24 | "id": "PdOm5IaDUxSm" 25 | } 26 | }, 27 | { 28 | "cell_type": "markdown", 29 | "source": [ 30 | "## Introduction\n", 31 | "In this notebook, we will extend our previous analysis of autocorrelation in financial time series by incorporating the Ljung-Box Q-test. The Ljung-Box Q-test is a statistical test that checks whether any of a group of autocorrelations of a time series are different from zero. This is particularly useful for identifying serial dependencies in stock returns, which has implications for market efficiency and trading strategies." 32 | ], 33 | "metadata": { 34 | "id": "tP7oGzYzx-Ql" 35 | } 36 | }, 37 | { 38 | "cell_type": "markdown", 39 | "source": [ 40 | "## 1. Importing Necessary Libraries" 41 | ], 42 | "metadata": { 43 | "id": "16AVzTJKyDLC" 44 | } 45 | }, 46 | { 47 | "cell_type": "code", 48 | "source": [ 49 | "import yfinance as yf\n", 50 | "import pandas as pd\n", 51 | "import numpy as np\n", 52 | "import matplotlib.pyplot as plt\n", 53 | "from statsmodels.graphics.tsaplots import plot_acf\n", 54 | "from statsmodels.stats.diagnostic import acorr_ljungbox" 55 | ], 56 | "metadata": { 57 | "id": "MgGMf4DaySiw" 58 | }, 59 | "execution_count": 7, 60 | "outputs": [] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "source": [ 65 | "## 2. Obtaining the Financial Asset Data\n", 66 | "\n", 67 | "Let's choose an asset for analysis. In this case, we will use Apple Inc. (AAPL)." 68 | ], 69 | "metadata": { 70 | "id": "mx2BnOjxyWaU" 71 | } 72 | }, 73 | { 74 | "cell_type": "code", 75 | "source": [ 76 | "# Define the asset ticker\n", 77 | "ticker = 'AAPL'\n", 78 | "\n", 79 | "# Download the adjusted closing prices of the asset\n", 80 | "prices = yf.download(ticker)['Adj Close'].tz_localize(None)\n", 81 | "\n", 82 | "# View the last few rows of the data\n", 83 | "prices.tail()" 84 | ], 85 | "metadata": { 86 | "colab": { 87 | "base_uri": "https://localhost:8080/", 88 | "height": 291 89 | }, 90 | "id": "Jgar8T5qyas7", 91 | "outputId": "f2eb68cf-03e3-4721-833e-030652d8f1b6" 92 | }, 93 | "execution_count": 2, 94 | "outputs": [ 95 | { 96 | "output_type": "stream", 97 | "name": "stderr", 98 | "text": [ 99 | "\r[*********************100%***********************] 1 of 1 completed\n" 100 | ] 101 | }, 102 | { 103 | "output_type": "execute_result", 104 | "data": { 105 | "text/plain": [ 106 | "Date\n", 107 | "2024-09-10 220.110001\n", 108 | "2024-09-11 222.660004\n", 109 | "2024-09-12 222.770004\n", 110 | "2024-09-13 222.500000\n", 111 | "2024-09-16 215.929993\n", 112 | "Name: Adj Close, dtype: float64" 113 | ], 114 | "text/html": [ 115 | "
\n", 116 | "\n", 129 | "\n", 130 | " \n", 131 | " \n", 132 | " \n", 133 | " \n", 134 | " \n", 135 | " \n", 136 | " \n", 137 | " \n", 138 | " \n", 139 | " \n", 140 | " \n", 141 | " \n", 142 | " \n", 143 | " \n", 144 | " \n", 145 | " \n", 146 | " \n", 147 | " \n", 148 | " \n", 149 | " \n", 150 | " \n", 151 | " \n", 152 | " \n", 153 | " \n", 154 | " \n", 155 | " \n", 156 | " \n", 157 | " \n", 158 | " \n", 159 | " \n", 160 | " \n", 161 | " \n", 162 | "
Adj Close
Date
2024-09-10220.110001
2024-09-11222.660004
2024-09-12222.770004
2024-09-13222.500000
2024-09-16215.929993
\n", 163 | "

" 164 | ] 165 | }, 166 | "metadata": {}, 167 | "execution_count": 2 168 | } 169 | ] 170 | }, 171 | { 172 | "cell_type": "markdown", 173 | "source": [ 174 | "## 3. Calculating Daily Returns\n", 175 | "To analyze autocorrelation, we will calculate the daily returns of the asset." 176 | ], 177 | "metadata": { 178 | "id": "CX2Rmfsqyq_I" 179 | } 180 | }, 181 | { 182 | "cell_type": "code", 183 | "source": [ 184 | "# Calculate daily returns\n", 185 | "returns = prices.pct_change().dropna()\n", 186 | "\n", 187 | "# View the first few rows of the returns\n", 188 | "returns.head()" 189 | ], 190 | "metadata": { 191 | "colab": { 192 | "base_uri": "https://localhost:8080/", 193 | "height": 272 194 | }, 195 | "id": "Pku33-q0ysw8", 196 | "outputId": "c1df4257-53bd-4854-ad9a-05a538b10b8d" 197 | }, 198 | "execution_count": 11, 199 | "outputs": [ 200 | { 201 | "output_type": "execute_result", 202 | "data": { 203 | "text/plain": [ 204 | "Date\n", 205 | "1980-12-15 -0.053581\n", 206 | "1980-12-16 -0.076231\n", 207 | "1980-12-17 0.024450\n", 208 | "1980-12-18 0.028580\n", 209 | "1980-12-19 0.059238\n", 210 | "Name: Adj Close, dtype: float64" 211 | ], 212 | "text/html": [ 213 | "
\n", 214 | "\n", 227 | "\n", 228 | " \n", 229 | " \n", 230 | " \n", 231 | " \n", 232 | " \n", 233 | " \n", 234 | " \n", 235 | " \n", 236 | " \n", 237 | " \n", 238 | " \n", 239 | " \n", 240 | " \n", 241 | " \n", 242 | " \n", 243 | " \n", 244 | " \n", 245 | " \n", 246 | " \n", 247 | " \n", 248 | " \n", 249 | " \n", 250 | " \n", 251 | " \n", 252 | " \n", 253 | " \n", 254 | " \n", 255 | " \n", 256 | " \n", 257 | " \n", 258 | " \n", 259 | " \n", 260 | "
Adj Close
Date
1980-12-15-0.053581
1980-12-16-0.076231
1980-12-170.024450
1980-12-180.028580
1980-12-190.059238
\n", 261 | "

" 262 | ] 263 | }, 264 | "metadata": {}, 265 | "execution_count": 11 266 | } 267 | ] 268 | }, 269 | { 270 | "cell_type": "markdown", 271 | "source": [ 272 | "## 4. Autocorrelation Analysis Over Different Time Periods\n", 273 | "We will analyze the autocorrelation of returns over the last 12 months, 6 months, and 3 months.\n", 274 | "\n", 275 | "First, we will define the time periods." 276 | ], 277 | "metadata": { 278 | "id": "xclahdGmyxvt" 279 | } 280 | }, 281 | { 282 | "cell_type": "code", 283 | "source": [ 284 | "# Get the current date\n", 285 | "end_date = returns.index.max()\n", 286 | "\n", 287 | "# Define periods\n", 288 | "periods = {\n", 289 | " 'Last 12 Months': end_date - pd.DateOffset(months=12),\n", 290 | " 'Last 6 Months': end_date - pd.DateOffset(months=6),\n", 291 | " 'Last 3 Months': end_date - pd.DateOffset(months=3)\n", 292 | "}" 293 | ], 294 | "metadata": { 295 | "id": "u3VSV5531Ifo" 296 | }, 297 | "execution_count": 4, 298 | "outputs": [] 299 | }, 300 | { 301 | "cell_type": "markdown", 302 | "source": [ 303 | "### 4.1. Plotting the Autocorrelation Function\n", 304 | "We will plot the autocorrelation functions for each period in subplots." 305 | ], 306 | "metadata": { 307 | "id": "-b4FUpIJy1Bl" 308 | } 309 | }, 310 | { 311 | "cell_type": "code", 312 | "source": [ 313 | "# Define the number of lags\n", 314 | "num_lags = 30\n", 315 | "\n", 316 | "# Create subplots\n", 317 | "fig, axes = plt.subplots(1, 3, figsize=(18, 5))\n", 318 | "\n", 319 | "# Iterate over periods and axes\n", 320 | "for ax, (title, start_date) in zip(axes, periods.items()):\n", 321 | " # Slice the returns for the given period\n", 322 | " period_returns = returns.loc[start_date:end_date]\n", 323 | "\n", 324 | " # Plot the autocorrelation function\n", 325 | " plot_acf(period_returns, lags=num_lags, ax=ax)\n", 326 | " ax.set_title(f'Autocorrelation Function\\n{title}')\n", 327 | " ax.set_xlabel('Lags')\n", 328 | " ax.set_ylabel('Autocorrelation')\n", 329 | "\n", 330 | "plt.tight_layout()\n", 331 | "plt.show()" 332 | ], 333 | "metadata": { 334 | "colab": { 335 | "base_uri": "https://localhost:8080/", 336 | "height": 454 337 | }, 338 | "id": "0dUIyGD0y3Ts", 339 | "outputId": "71de4871-a8e7-4eaa-dc5b-624dbcf441e3" 340 | }, 341 | "execution_count": 5, 342 | "outputs": [ 343 | { 344 | "output_type": "display_data", 345 | "data": { 346 | "text/plain": [ 347 | "
" 348 | ], 349 | "image/png": "iVBORw0KGgoAAAANSUhEUgAABv4AAAHpCAYAAABKh0uFAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjcuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/bCgiHAAAACXBIWXMAAA9hAAAPYQGoP6dpAACOFElEQVR4nOzdd3wUdf7H8fcmpNASWkJAI1VpgvgLgnhKkUhQFFFEUTyKCooip+gp3J0g6InYDj1RPA/BgsJhwYKiiCCnIih2RE6a1AASSQiBhGS/vz9ilizZDduS3Zl9PR/sI9mp35kNM++dzxSHMcYIAAAAAAAAAAAAgKXFhLsBAAAAAAAAAAAAAIJH4Q8AAAAAAAAAAACwAQp/AAAAAAAAAAAAgA1Q+AMAAAAAAAAAAABsgMIfAAAAAAAAAAAAYAMU/gAAAAAAAAAAAAAboPAHAAAAAAAAAAAA2ACFPwAAAAAAAAAAAMAGKPwBAAAAAAAAAAAANkDhD0DUWLFihRwOh1asWBHS6TocDt17770hnaZdVdVnAAAAqh5ZKvzIUgAAWBdZKvzIUogWFP4AC3rqqafkcDjUrVu3oKf17rvvEg58EInr6d5775XD4fD4mjVrVljb9tRTT2nu3LlhbQMAAN6QpapfJK4nshQAAIEhS1W/SFxPZCkgctUIdwMA+G/evHlq3ry51qxZo40bN6p169YBT+vdd9/VzJkzIy48RJrK1tPhw4dVo0b4NqdPP/206tSp49YtFOE7GE899ZQaNWqkESNGuHXv0aOHDh8+rPj4+PA0DAAAkaXCgSzlH7IUACCSkaWqH1nKP2QpRDsKf4DFbNmyRZ999plef/113XjjjZo3b54mT54c7mZVqYKCAtWqVatC9+LiYjmdzrDvrBMTE8M6/yuuuEKNGjUKaxt8FRMTE/b1BQCIbmSpY8hSpchSAAD4jix1DFmqFFkKiDzc6hOwmHnz5ql+/frq37+/rrjiCs2bN6/CMN7uV71161Y5HA7Xpe4jRozQzJkzJcntcvwyhw4d0h133KH09HQlJCSoTZs2euSRR2SMqTDPl156SV27dlWtWrVUv3599ejRQx988IHbME899ZQ6dOighIQENW3aVLfccosOHDjgNkyvXr10+umna+3aterRo4dq1aqlv/zlL662P/LII5oxY4ZatWqlhIQE/fjjj5Kkn376SVdccYUaNGigxMREdenSRW+99dYJ1+d///tfDR48WKeccooSEhKUnp6u22+/XYcPH3YNc6L15Ole6l9//bUuvPBCJSUlqU6dOurTp48+//xzt2Hmzp0rh8OhTz/9VOPHj1dKSopq166tyy67TPv27Tth20/k+M+7vOPbXHZ7ho0bN2rEiBGqV6+ekpOTNXLkSBUUFFQYv7LPu3nz5lq3bp0+/vhj17rq1auXJO9/mwsXLlRGRoZq1qypRo0a6dprr9XOnTvdhhkxYoTq1KmjnTt3auDAgapTp45SUlJ05513qqSkJKh1BQCIHmQpspSvyFIAAFREliJL+YosBYQPV/wBFjNv3jxdfvnlio+P19VXX62nn35aX3zxhc466yy/p3XjjTdq165dWrp0qV588UW3fsYYDRgwQMuXL9f111+vzp076/3339ef//xn7dy5U//4xz9cw06ZMkX33nuvzjnnHE2dOlXx8fFavXq1PvroI/Xt21dS6Q58ypQpyszM1JgxY7RhwwZX2z/99FPFxcW5prd//35deOGFGjJkiK699lo1btzY1W/OnDk6cuSIRo8erYSEBDVo0EDr1q3TH/7wB5100kmaMGGCateurf/85z8aOHCgXnvtNV122WVe18HChQtVUFCgMWPGqGHDhlqzZo3++c9/aseOHVq4cOEJ15Mn69at03nnnaekpCTdddddiouL0zPPPKNevXrp448/rnC7g1tvvVX169fX5MmTtXXrVs2YMUNjx47VggULTjgvScrJyXF7Hxsbq/r16/s07vGuvPJKtWjRQtOmTdNXX32lf//730pNTdX06dNdw5zo854xY4ZuvfVW1alTR3/9618lye0zPN7cuXM1cuRInXXWWZo2bZr27Nmjxx9/XJ9++qm+/vpr1atXzzVsSUmJsrKy1K1bNz3yyCP68MMP9eijj6pVq1YaM2ZMQMsMAIguZCmy1PHIUmQpAIDvyFJkqeORpchSiEAGgGV8+eWXRpJZunSpMcYYp9NpTj75ZPOnP/3Jbbjly5cbSWb58uVu3bds2WIkmTlz5ri63XLLLcbTpmDRokVGkrn//vvdul9xxRXG4XCYjRs3GmOM+fnnn01MTIy57LLLTElJiduwTqfTGGPM3r17TXx8vOnbt6/bME8++aSRZJ577jlXt549expJZtasWR7bnpSUZPbu3evWr0+fPqZjx47myJEjbvM+55xzzKmnnlrpeikoKKiw7NOmTTMOh8P88ssvJ1xPxhgjyUyePNn1fuDAgSY+Pt5s2rTJ1W3Xrl2mbt26pkePHq5uc+bMMZJMZmama10ZY8ztt99uYmNjzYEDBzzOr8zkyZONpAqvZs2aGWM8f97e2lw2reuuu85tuMsuu8w0bNjQ9d6Xz9sYYzp06GB69uxZYb7HfwZFRUUmNTXVnH766ebw4cOu4d555x0jyUyaNMnVbfjw4UaSmTp1qts0zzzzTJORkeFxHQEAUB5ZiixVHlmqFFkKAOArshRZqjyyVCmyFCIRt/oELGTevHlq3LixevfuLan0svirrrpK8+fPD/kl5e+++65iY2M1btw4t+533HGHjDF67733JEmLFi2S0+nUpEmTFBPjvkkpu+3Ahx9+qKKiIt12221uw4waNUpJSUlavHix23gJCQkaOXKkx3YNGjRIKSkprvc5OTn66KOPdOWVV+rgwYP69ddf9euvv2r//v3KysrSzz//XOHS/PJq1qzp+v3QoUP69ddfdc4558gYo6+//rqyVeRRSUmJPvjgAw0cOFAtW7Z0dW/SpImuueYaffLJJ8rLy3MbZ/To0W63aDjvvPNUUlKiX375xad5vvbaa1q6dKnr5ek2G7666aab3N6fd9552r9/v6vNvnze/vjyyy+1d+9e3XzzzW73WO/fv7/atm1b4W/DWxs3b97s97wBANGHLEWW8oQsRZYCAPiGLEWW8oQsRZZC5OFWn4BFlJSUaP78+erdu7e2bNni6t6tWzc9+uijWrZsmev2BaHwyy+/qGnTpqpbt65b93bt2rn6S9KmTZsUExOj9u3bVzotSWrTpo1b9/j4eLVs2bJCkDjppJO8Phi5RYsWbu83btwoY4zuuece3XPPPR7H2bt3r0466SSP/bZt26ZJkybprbfe0m+//ebWLzc31+syebNv3z4VFBRUWFapdN05nU5t375dHTp0cHU/5ZRT3IYrux3C8e3xpkePHiF7iHJlbUlKSvLp8/aHt78NSWrbtq0++eQTt26JiYluAbusjb6uKwBA9CJLlSJLVUSWIksBAE6MLFWKLFURWYoshchD4Q+wiI8++ki7d+/W/PnzNX/+/Ar9582b5wpY3s5wscqDZsuf7XSifk6nU5J05513Kisry+M4rVu39ti9pKREF1xwgXJycnT33Xerbdu2ql27tnbu3KkRI0a4pl3VYmNjPXY3Hh5W7Y9A/g6qqi2h4q19AACcCFnKcz+ylHdkKQAAjiFLee5HlvKOLAWED4U/wCLmzZun1NRUzZw5s0K/119/XW+88YZmzZqlmjVrus6GOXDggNtwni7R97YTbtasmT788EMdPHjQ7eyqn376ydVfklq1aiWn06kff/xRnTt39jotSdqwYYPbbQaKioq0ZcsWZWZmelnqEyubXlxcnN/T+f777/W///1Pzz//vIYNG+bqvnTp0grD+nq7gJSUFNWqVUsbNmyo0O+nn35STEyM0tPT/WpnoPz5O/CVL5+35Pv6Kv+3cf7557v127Bhg6s/AADBIkt5RpbyjiwFAMAxZCnPyFLekaWA8OEZf4AFHD58WK+//rouvvhiXXHFFRVeY8eO1cGDB/XWW29JKt1pxcbGauXKlW7TeeqppypMu3bt2pIq7oQvuugilZSU6Mknn3Tr/o9//EMOh0MXXnihJGngwIGKiYnR1KlTK5yJVHY2TmZmpuLj4/XEE0+4naEze/Zs5ebmqn///gGslVKpqanq1auXnnnmGe3evbtC/3379nkdt+wsnfJtMsbo8ccfrzCst/XkaZp9+/bVm2++qa1bt7q679mzRy+//LLOPfdcJSUlVTqNUElKSlKjRo18+jvwlS+ft1S6vk60riSpS5cuSk1N1axZs1RYWOjq/t5772n9+vVB/W0AAFCGLOUdWco7shQAAKXIUt6RpbwjSwHhwxV/gAW89dZbOnjwoAYMGOCx/9lnn62UlBTNmzdPV111lZKTkzV48GD985//lMPhUKtWrfTOO+9o7969FcbNyMiQJI0bN05ZWVmKjY3VkCFDdMkll6h3797661//qq1bt+qMM87QBx98oDfffFO33XabWrVqJan0dgV//etfdd999+m8887T5ZdfroSEBH3xxRdq2rSppk2bppSUFE2cOFFTpkxRv379NGDAAG3YsEFPPfWUzjrrLF177bVBrZ+ZM2fq3HPPVceOHTVq1Ci1bNlSe/bs0apVq7Rjxw59++23Hsdr27atWrVqpTvvvFM7d+5UUlKSXnvtNY/35fa2njy5//77tXTpUp177rm6+eabVaNGDT3zzDMqLCzUQw89FNSy+uuGG27Qgw8+qBtuuEFdunTRypUr9b///S/g6fnyeUul6+vpp5/W/fffr9atWys1NbXCmVNS6Rlx06dP18iRI9WzZ09dffXV2rNnjx5//HE1b95ct99+e8BtBQCgDFmqcmQp78hSAACQpU6ELOUdWQoIEwMg4l1yySUmMTHRHDp0yOswI0aMMHFxcebXX381xhizb98+M2jQIFOrVi1Tv359c+ONN5offvjBSDJz5sxxjVdcXGxuvfVWk5KSYhwOhym/WTh48KC5/fbbTdOmTU1cXJw59dRTzcMPP2ycTmeF+T/33HPmzDPPNAkJCaZ+/fqmZ8+eZunSpW7DPPnkk6Zt27YmLi7ONG7c2IwZM8b89ttvbsP07NnTdOjQocL0t2zZYiSZhx9+2OPyb9q0yQwbNsykpaWZuLg4c9JJJ5mLL77YvPrqq65hli9fbiSZ5cuXu7r9+OOPJjMz09SpU8c0atTIjBo1ynz77bd+rSdJZvLkyW7t+eqrr0xWVpapU6eOqVWrlundu7f57LPP3IaZM2eOkWS++OILt+6e2unJ5MmTjSSzb98+r8MUFBSY66+/3iQnJ5u6deuaK6+80uzdu7dCm71Nq6yNW7Zscet+os87Ozvb9O/f39StW9dIMj179qx02RYsWOCaXoMGDczQoUPNjh073IYZPny4qV27ttf1AACAN2QpspQnZCn3tgMA4A1ZiizlCVnKve1AJHEYEyFPxgQAAAAAAAAAAAAQMJ7xBwAAAAAAAAAAANgAhT8AAAAAAAAAAADABij8AQAAAAAAAAAAADZA4Q8AAAAAAAAAAACwAQp/AAAAAAAAAAAAgA1Q+AMAAAAAAAAAAABsgMIfAESRESNGqE6dOuFuBgAAQMSbO3euHA6Hvvzyy3A3BQAAwHJWrFghh8OhV199NdxNAaIOhT8AQanuAyI//vij7r33Xm3dutWn4Xfv3q0JEyaod+/eqlu3rhwOh1asWFFhuIKCAs2cOVN9+/ZVkyZNVLduXZ155pl6+umnVVJS4tO8HA6HHA6HbrjhBo/9//rXv7qG+fXXX32aZiAKCgp07733elxOAABgDZGescp8+OGHOv/885WcnKy6desqIyNDCxYsOOF4vXr1ksPh0Kmnnuqx/9KlS125qaoPFj311FOaO3dulc4DAABUr0jPUitXrtSAAQOUnp6uxMREpaWlqV+/fvr00099Gn/EiBFyOBxKSkrS4cOHK/T/+eefXVnqkUce8WdR/Pbyyy9rxowZVToPAP6h8AfAUn788UdNmTLF5yC1YcMGTZ8+XTt37lTHjh29Drd582bdeuutMsZo/PjxeuSRR9SiRQvdfPPNuu6663xuX2Jiol577TUVFRVV6PfKK68oMTHR52kFqqCgQFOmTKHwBwAAfOZvxpKkOXPmqG/fvoqLi9MDDzyghx9+WD169ND27dt9Gj8xMVEbN27UmjVrKvSbN29eteQmicIfAAAInr9Z6n//+59iYmJ00003aebMmbrzzjuVnZ2tHj16aMmSJT5No0aNGiooKNDbb79doV91ZikKf0DkqRHuBgBAVcrIyND+/fvVoEEDvfrqqxo8eLDH4dLS0vT999+rQ4cOrm433nijrrvuOs2ZM0f33HOPWrdufcL59evXT2+99Zbee+89XXrppa7un332mbZs2aJBgwbptddeC37BAAAAwmjr1q265ZZbdOutt+rxxx8PaBqtWrVScXGxXnnlFXXt2tXV/ciRI3rjjTfUv39/chMAALClG264ocIdo26++Wa1bNlSM2bMUL9+/U44jYSEBP3hD3/QK6+8oiuvvNKt38svv0yWAqIYV/wBqHJFRUWaNGmSMjIylJycrNq1a+u8887T8uXLKww7f/58ZWRkqG7dukpKSlLHjh1dB5Pmzp3rKtz17t3bdcuCyq5sq1u3rho0aHDCNjZq1Mit6FfmsssukyStX7/el0XVSSedpB49eujll1926z5v3jx17NhRp59+usfxFi5cqIyMDNWsWVONGjXStddeq507d7oNU/Z8vp07d2rgwIGqU6eOUlJSdOedd7puR7p161alpKRIkqZMmeJaR/fee6/btCqbRpnKPgsAABB+4cxYs2bNUklJiaZOnSpJys/PlzHG72W4+uqrtWDBAjmdTle3t99+WwUFBRUOYJX5+uuvdeGFFyopKUl16tRRnz599Pnnn7sNU3Z7r08//VTjx49XSkqKateurcsuu0z79u1zDde8eXOtW7dOH3/8sWu5e/Xq5TatwsLCSqchSV9++aWysrLUqFEj1axZUy1atPDrrhEAAKD6hTNLeVKrVi2lpKTowIEDPo9zzTXX6L333nMb54svvtDPP/+sa665xuM4mzdv1uDBg9WgQQPVqlVLZ599thYvXuw2TNnz+f7zn//o73//u04++WQlJiaqT58+2rhxo2u4Xr16afHixfrll19cy928eXO3aTmdzkqnIZXemnTQoEFKS0tTYmKiTj75ZA0ZMkS5ubk+rwsAx1D4A1Dl8vLy9O9//1u9evXS9OnTde+992rfvn3KysrSN9984xpu6dKluvrqq1W/fn1Nnz5dDz74oHr16uW6v3mPHj00btw4SdJf/vIXvfjii3rxxRfVrl27Kmt7dna2pNLCoK+uueYavf3228rPz5ckFRcXa+HChV4D19y5c3XllVcqNjZW06ZN06hRo/T666/r3HPPrRD2SkpKlJWVpYYNG+qRRx5Rz5499eijj+pf//qXJCklJUVPP/20pNKiZdk6uvzyy32ehnTizwIAAIRfODPWhx9+qLZt2+rdd9/VySefrLp166phw4a655573Ip4J3LNNddo9+7dbgfGXn75ZfXp00epqakVhl+3bp3OO+88ffvtt7rrrrt0zz33aMuWLerVq5dWr15dYfhbb71V3377rSZPnqwxY8bo7bff1tixY139Z8yYoZNPPllt27Z1Lfdf//pXv6axd+9e9e3bV1u3btWECRP0z3/+U0OHDq1QjAQAAJElEo5X5eXl6ddff9VPP/2kv/zlL/rhhx/Up08fn5fh8ssvl8Ph0Ouvv+7q9vLLL6tt27b6v//7vwrD79mzR+ecc47ef/993Xzzzfr73/+uI0eOaMCAAXrjjTcqDP/ggw/qjTfe0J133qmJEyfq888/19ChQ139//rXv6pz585q1KiRa7mPv+3niaZRVFSkrKwsff7557r11ls1c+ZMjR49Wps3b/arCAqgHAMAQZgzZ46RZL744guvwxQXF5vCwkK3br/99ptp3Lixue6661zd/vSnP5mkpCRTXFzsdVoLFy40kszy5cv9bqu/4xYWFpr27dubFi1amKNHj55weEnmlltuMTk5OSY+Pt68+OKLxhhjFi9ebBwOh9m6dauZPHmykWT27dtnjDGmqKjIpKammtNPP90cPnzYNa133nnHSDKTJk1ydRs+fLiRZKZOneo23zPPPNNkZGS43u/bt89IMpMnT67QRl+n4ctnAQAAqk6kZ6ykpCRTv359k5CQYO655x7z6quvmmuuucZIMhMmTDjh+D179jQdOnQwxhjTpUsXc/3117vaHx8fb55//nmzfPlyI8ksXLjQNd7AgQNNfHy82bRpk6vbrl27TN26dU2PHj1c3crWX2ZmpnE6na7ut99+u4mNjTUHDhxwdevQoYPp2bNnhTb6Oo033njjhJ8VAACoXpGepcpkZWUZSUaSiY+PNzfeeKPb8SFvhg8fbmrXrm2MMeaKK64wffr0McYYU1JSYtLS0syUKVPMli1bjCTz8MMPu8a77bbbjCTz3//+19Xt4MGDpkWLFqZ58+ampKTEGGNcOaxdu3Zu6+jxxx83ksz333/v6ta/f3/TrFmzCm30dRpff/11hcwHIDhc8QegysXGxio+Pl5S6eX9OTk5Ki4uVpcuXfTVV1+5hqtXr54OHTqkpUuXhqupbsaOHasff/xRTz75pGrU8P2RqPXr11e/fv30yiuvSCo90+qcc85Rs2bNKgz75Zdfau/evbr55pvdHrrcv39/tW3btsKtFiTppptucnt/3nnnafPmzT63z5dpRNpnAQAAKgpnxsrPz9dvv/2mKVOmaOrUqRo0aJDmzZunfv366fHHH9fBgwd9ntY111yj119/XUVFRXr11VcVGxvrut16eSUlJfrggw80cOBAtWzZ0tW9SZMmuuaaa/TJJ58oLy/PbZzRo0fL4XC43p933nkqKSnRL7/84nP7TjSNevXqSZLeeecdHT161OfpAgCA8IqE41UPPvigPvjgA82ePVtnn322ioqKVFxc7Nc0rrnmGq1YsULZ2dn66KOPlJ2d7fWuU++++666du2qc88919WtTp06Gj16tLZu3aoff/zRbfiRI0e61pFUmoMk+XUc6kTTSE5OliS9//77Kigo8Hm6ALyj8AegWjz//PPq1KmTEhMT1bBhQ6WkpGjx4sVu9+q++eabddppp+nCCy/UySefrOuuu05LliwJS3sffvhhPfvss7rvvvt00UUX+T3+Nddco6VLl2rbtm1atGiR18BVdsCoTZs2Ffq1bdu2wkGpxMRE1zP8ytSvX1+//fabz23zZRqR9FkAAADvwpWxatasKan0GX3lXX311Tp8+LC+/vprn6dV9vyW9957T/PmzdPFF1+sunXrVhhu3759Kigo8Jib2rVrJ6fTqe3bt7t1P+WUU9ze169fX5L8yk4nmkbPnj01aNAgTZkyRY0aNdKll16qOXPmqLCw0Od5AACA8Aj38arOnTvrggsu0HXXXaelS5dqzZo1GjFihF/TuOiii1S3bl0tWLBA8+bN01lnnaXWrVt7HPaXX37xmqXK+pdXHVmqRYsWGj9+vP7973+rUaNGysrK0syZM3m+HxAECn8AqtxLL72kESNGqFWrVpo9e7aWLFmipUuX6vzzz3d7Bkxqaqq++eYbvfXWWxowYICWL1+uCy+8UMOHD6/W9s6dO1d33323brrpJv3tb38LaBoDBgxQQkKChg8frsLCQl155ZUhaVtsbGy1TCNSPgsAAOBdODNW06ZNJUmNGzd26172XD5/DgY1adJEvXr10qOPPqqVK1d6PWEqEN5yjzEmZNNwOBx69dVXtWrVKo0dO1Y7d+7Uddddp4yMDNcznwEAQOSJtONV8fHxGjBggF5//XUdPnzY5/ESEhJ0+eWX6/nnn9cbb7xhuSwlSY8++qi+++47/eUvf9Hhw4c1btw4dejQQTt27PCvwQAkUfgDUA1effVVtWzZUq+//rr++Mc/KisrS5mZmTpy5EiFYePj43XJJZfoqaee0qZNm3TjjTfqhRde0MaNGyXJ7TZLVeHNN9/UDTfcoMsvv1wzZ84MeDo1a9bUwIEDtWLFCl1wwQVq1KiRx+HKbv+5YcOGCv02bNjg8fagJxKqdXSizwIAAIRXODNWRkaGJGnnzp1u3Xft2iVJFe4ucCLXXHON/vvf/yopKcnr3RZSUlJUq1Ytj7npp59+UkxMjNLT0/2arxS67HT22Wfr73//u7788kvNmzdP69at0/z580MybQAAEHqReLzq8OHDMsb4ddt0qTRLff311zp48KCGDBnidbhmzZp5zVJl/f0VqmXv2LGj/va3v2nlypX673//q507d2rWrFkhmTYQbSj8AahyZWf2lD+TZ/Xq1Vq1apXbcPv373d7HxMTo06dOkmS61ZJtWvXliQdOHAg5O1cuXKlhgwZoh49emjevHmKiQluE3nnnXdq8uTJuueee7wO06VLF6WmpmrWrFlut4N67733tH79evXv39/v+daqVUtScOvIl88CAACEVzgz1lVXXSVJmj17tqub0+nUnDlz1KBBA1dh0FdXXHGFJk+erKeeesrtGTDlxcbGqm/fvnrzzTe1detWV/c9e/bo5Zdf1rnnnqukpCS/5iuVLnswuem3336rcNZ7586dJZGbAACIZOHMUnv37q3Q7cCBA3rttdeUnp7uuouCr3r37q377rtPTz75pNLS0rwOd9FFF2nNmjVuy3jo0CH961//UvPmzdW+fXu/5iuVLnswt+XMy8ur8FzDjh07KiYmhiwFBKhGuBsAwB6ee+45j/c3/9Of/qSLL75Yr7/+ui677DL1799fW7Zs0axZs9S+fXu32x/dcMMNysnJ0fnnn6+TTz5Zv/zyi/75z3+qc+fOrnuNd+7cWbGxsZo+fbpyc3OVkJCg888/v9JAdP/990uS1q1bJ0l68cUX9cknn0iS61aev/zyiwYMGCCHw6ErrrhCCxcudJtGp06dXKHOV2eccYbOOOOMSoeJi4vT9OnTNXLkSPXs2VNXX3219uzZo8cff1zNmzfX7bff7tc8pdKrDdu3b68FCxbotNNOU4MGDXT66afr9NNP93kavnwWAACg6kVqxrr00kvVp08fTZs2Tb/++qvOOOMMLVq0SJ988omeeeYZJSQk+LWcycnJuvfee0843P3336+lS5fq3HPP1c0336waNWromWeeUWFhoR566CG/5lkmIyNDTz/9tO6//361bt1aqampOv/8830e//nnn9dTTz2lyy67TK1atdLBgwf17LPPVnr1IgAAqB6RmqXKnhfYrVs3paamatu2bZozZ4527dqlBQsW+L2cMTExPj2uZsKECXrllVd04YUXaty4cWrQoIGef/55bdmyRa+99lpAJ8FnZGRowYIFGj9+vM466yzVqVNHl1xyic/jf/TRRxo7dqwGDx6s0047TcXFxXrxxRcVGxurQYMG+d0eAJIMAARhzpw5RpLX1/bt243T6TQPPPCAadasmUlISDBnnnmmeeedd8zw4cNNs2bNXNN69dVXTd++fU1qaqqJj483p5xyirnxxhvN7t273eb57LPPmpYtW5rY2FgjySxfvrzSNlbWvjLLly+vdLjJkyefcF1IMrfcckulw0yePNlIMvv27XPrvmDBAnPmmWeahIQE06BBAzN06FCzY8cOt2GGDx9uateu7XWa5X322WcmIyPDxMfHu7Xf12n4+lkAAICqYYWMdfDgQfOnP/3JpKWlmfj4eNOxY0fz0ksv+bR8PXv2NB06dKh0mLJ8tnDhQrfuX331lcnKyjJ16tQxtWrVMr179zafffaZ2zBl6++LL77wOM3yy5adnW369+9v6tataySZnj17+jWNr776ylx99dXmlFNOMQkJCSY1NdVcfPHF5ssvv/RpXQAAgNCL9Cz15JNPmnPPPdc0atTI1KhR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Xr16yeFwuL1uuukmt2G2bdum/v37q1atWkpNTdWf//xnFRcXV+WiAAAAVDuyFAAAQODIUgAAwCpqhLsBvho6dKh2796tpUuX6ujRoxo5cqRGjx6tl19+udLxRo0apalTp7re16pVy/V7SUmJ+vfvr7S0NH322WfavXu3hg0bpri4OD3wwANVtiwAAADVjSwFAAAQOLIUAACwCocxxoS7ESeyfv16tW/fXl988YW6dOkiSVqyZIkuuugi7dixQ02bNvU4Xq9evdS5c2fNmDHDY//33ntPF198sXbt2qXGjRtLkmbNmqW7775b+/btU3x8vE/ty8vLU3JysnJzc5WUlOT/AgIAgIhn5f09WQoAAISblff3ZCkAABBu/uzvLXGrz1WrVqlevXqucCVJmZmZiomJ0erVqysdd968eWrUqJFOP/10TZw4UQUFBW7T7dixoytcSVJWVpby8vK0bt06r9MsLCxUXl6e2wsAACBSkaUAAAACR5YCAABWYolbfWZnZys1NdWtW40aNdSgQQNlZ2d7He+aa65Rs2bN1LRpU3333Xe6++67tWHDBr3++uuu6ZYPV5Jc7yub7rRp0zRlypRAFwcAAKBakaUAAAACR5YCAABWEtbC34QJEzR9+vRKh1m/fn3A0x89erTr944dO6pJkybq06ePNm3apFatWgU83YkTJ2r8+PGu93l5eUpPTw94egAAAIEgSwEAAASOLAUAAOworIW/O+64QyNGjKh0mJYtWyotLU179+51615cXKycnBylpaX5PL9u3bpJkjZu3KhWrVopLS1Na9ascRtmz549klTpdBMSEpSQkODzfAEAAKoCWQoAACBwZCkAAGBHYS38paSkKCUl5YTDde/eXQcOHNDatWuVkZEhSfroo4/kdDpdockX33zzjSSpSZMmrun+/e9/1969e123bFi6dKmSkpLUvn17P5cGAACgepGlAAAAAkeWAgAAdhQT7gb4ol27durXr59GjRqlNWvW6NNPP9XYsWM1ZMgQNW3aVJK0c+dOtW3b1nWm1KZNm3Tfffdp7dq12rp1q9566y0NGzZMPXr0UKdOnSRJffv2Vfv27fXHP/5R3377rd5//3397W9/0y233MKZUwAAwDbIUgAAAIEjSwEAACuxROFPkubNm6e2bduqT58+uuiii3TuuefqX//6l6v/0aNHtWHDBhUU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\n" 350 | }, 351 | "metadata": {} 352 | } 353 | ] 354 | }, 355 | { 356 | "cell_type": "markdown", 357 | "source": [ 358 | "## 5. Ljung-Box Q-Test\n", 359 | "The Ljung-Box Q-test helps determine whether a series of autocorrelations are jointly zero." 360 | ], 361 | "metadata": { 362 | "id": "8NNBEnAUgDSF" 363 | } 364 | }, 365 | { 366 | "cell_type": "markdown", 367 | "source": [ 368 | "### 5.1. Performing the Ljung-Box Q-Test\n", 369 | "We will perform the Ljung-Box Q-test for each period and interpret the results." 370 | ], 371 | "metadata": { 372 | "id": "CDFuO5vwgN_I" 373 | } 374 | }, 375 | { 376 | "cell_type": "code", 377 | "source": [ 378 | "# Initialize a dictionary to hold the test results\n", 379 | "ljung_box_results = {}\n", 380 | "\n", 381 | "# Significance level\n", 382 | "alpha = 0.05\n", 383 | "\n", 384 | "# Perform Ljung-Box Q-Test for each period\n", 385 | "for title, start_date in periods.items():\n", 386 | " # Slice the returns for the given period\n", 387 | " period_returns = returns.loc[start_date:end_date]\n", 388 | "\n", 389 | " # Perform the Ljung-Box test\n", 390 | " lb_test = acorr_ljungbox(period_returns, lags=num_lags, return_df=True)\n", 391 | "\n", 392 | " # Add to the dictionary\n", 393 | " ljung_box_results[title] = lb_test\n", 394 | "\n", 395 | " # Display the results\n", 396 | " print(f\"Ljung-Box Q-Test Results for {title}:\\n\")\n", 397 | " print(lb_test)\n", 398 | " print(\"\\n\")" 399 | ], 400 | "metadata": { 401 | "colab": { 402 | "base_uri": "https://localhost:8080/" 403 | }, 404 | "id": "Q8XMaUstgRBy", 405 | "outputId": "6ed965fd-c23b-40fa-d307-aee41b1a42b8" 406 | }, 407 | "execution_count": 8, 408 | "outputs": [ 409 | { 410 | "output_type": "stream", 411 | "name": "stdout", 412 | "text": [ 413 | "Ljung-Box Q-Test Results for Last 12 Months:\n", 414 | "\n", 415 | " lb_stat lb_pvalue\n", 416 | "1 1.255442 0.262516\n", 417 | "2 1.262044 0.532048\n", 418 | "3 1.275729 0.734904\n", 419 | "4 2.073704 0.722205\n", 420 | "5 3.723870 0.589816\n", 421 | "6 3.857364 0.695972\n", 422 | "7 3.969060 0.783334\n", 423 | "8 3.972504 0.859596\n", 424 | "9 4.287177 0.891515\n", 425 | "10 4.319925 0.931763\n", 426 | "11 5.862491 0.882380\n", 427 | "12 5.882599 0.921884\n", 428 | "13 5.888432 0.950119\n", 429 | "14 10.142760 0.751673\n", 430 | "15 10.336815 0.798036\n", 431 | "16 10.398155 0.845025\n", 432 | "17 10.569320 0.878057\n", 433 | "18 10.605445 0.910344\n", 434 | "19 12.249693 0.874677\n", 435 | "20 12.431012 0.900443\n", 436 | "21 12.697382 0.918853\n", 437 | "22 15.438628 0.842737\n", 438 | "23 15.454347 0.877614\n", 439 | "24 15.571233 0.902927\n", 440 | "25 16.226624 0.907913\n", 441 | "26 17.833362 0.881752\n", 442 | "27 18.251718 0.895638\n", 443 | "28 18.286643 0.918699\n", 444 | "29 18.772169 0.926991\n", 445 | "30 18.778554 0.944523\n", 446 | "\n", 447 | "\n", 448 | "Ljung-Box Q-Test Results for Last 6 Months:\n", 449 | "\n", 450 | " lb_stat lb_pvalue\n", 451 | "1 0.040216 0.841060\n", 452 | "2 0.173442 0.916933\n", 453 | "3 0.745851 0.862370\n", 454 | "4 1.740690 0.783314\n", 455 | "5 2.613209 0.759357\n", 456 | "6 2.618106 0.855023\n", 457 | "7 2.784585 0.904189\n", 458 | "8 3.126319 0.926182\n", 459 | "9 3.691238 0.930535\n", 460 | "10 4.039988 0.945525\n", 461 | "11 4.056959 0.968221\n", 462 | "12 4.061317 0.982304\n", 463 | "13 4.081018 0.990299\n", 464 | "14 9.244931 0.815047\n", 465 | "15 9.963922 0.822003\n", 466 | "16 9.976485 0.867853\n", 467 | "17 9.994341 0.903847\n", 468 | "18 10.217179 0.924586\n", 469 | "19 10.300963 0.945127\n", 470 | "20 10.393585 0.960461\n", 471 | "21 10.635403 0.969425\n", 472 | "22 11.131316 0.972825\n", 473 | "23 12.195994 0.967335\n", 474 | "24 12.306581 0.976229\n", 475 | "25 13.765443 0.965668\n", 476 | "26 15.159773 0.954342\n", 477 | "27 16.617295 0.940140\n", 478 | "28 16.983700 0.948910\n", 479 | "29 20.217324 0.886043\n", 480 | "30 20.410547 0.905411\n", 481 | "\n", 482 | "\n", 483 | "Ljung-Box Q-Test Results for Last 3 Months:\n", 484 | "\n", 485 | " lb_stat lb_pvalue\n", 486 | "1 0.535303 0.464386\n", 487 | "2 0.578348 0.748882\n", 488 | "3 0.694053 0.874602\n", 489 | "4 0.695277 0.951910\n", 490 | "5 0.900160 0.970210\n", 491 | "6 1.149192 0.979320\n", 492 | "7 2.501957 0.926950\n", 493 | "8 2.551029 0.959309\n", 494 | "9 3.009040 0.963935\n", 495 | "10 4.456776 0.924398\n", 496 | "11 6.412718 0.844457\n", 497 | "12 7.306813 0.836690\n", 498 | "13 7.551507 0.871543\n", 499 | "14 10.258442 0.743055\n", 500 | "15 11.890942 0.687264\n", 501 | "16 23.104672 0.110965\n", 502 | "17 23.735204 0.126810\n", 503 | "18 23.805135 0.161516\n", 504 | "19 23.819289 0.203176\n", 505 | "20 23.940748 0.244990\n", 506 | "21 24.872300 0.252737\n", 507 | "22 25.120888 0.291329\n", 508 | "23 25.257443 0.337150\n", 509 | "24 25.339491 0.387504\n", 510 | "25 25.408179 0.439695\n", 511 | "26 25.672935 0.481191\n", 512 | "27 25.738165 0.533166\n", 513 | "28 25.973311 0.574512\n", 514 | "29 31.087854 0.361294\n", 515 | "30 33.299661 0.309686\n", 516 | "\n", 517 | "\n" 518 | ] 519 | } 520 | ] 521 | }, 522 | { 523 | "cell_type": "markdown", 524 | "source": [ 525 | "### 5.2. Interpreting the Results\n", 526 | "For each lag, if the p-value is less than the significance level (0.05), we reject the null hypothesis that there is no autocorrelation up to that lag." 527 | ], 528 | "metadata": { 529 | "id": "Bz_TDfovgb61" 530 | } 531 | }, 532 | { 533 | "cell_type": "code", 534 | "source": [ 535 | "# Interpret the results\n", 536 | "for title, lb_test in ljung_box_results.items():\n", 537 | " print(f\"Interpretation for {title}:\\n\")\n", 538 | " for lag in range(1, num_lags + 1):\n", 539 | " p_value = lb_test['lb_pvalue'].iloc[lag - 1]\n", 540 | " if p_value < alpha:\n", 541 | " print(f\"At lag {lag}, p-value = {p_value:.4f} < {alpha}, reject null hypothesis of no autocorrelation.\")\n", 542 | " else:\n", 543 | " print(f\"At lag {lag}, p-value = {p_value:.4f} >= {alpha}, fail to reject null hypothesis.\")\n", 544 | " print(\"\\n\")" 545 | ], 546 | "metadata": { 547 | "colab": { 548 | "base_uri": "https://localhost:8080/" 549 | }, 550 | "id": "O-gEdrvvgbNp", 551 | "outputId": "5edf41f1-b54a-4ea5-b9ce-908af0a05939" 552 | }, 553 | "execution_count": 10, 554 | "outputs": [ 555 | { 556 | "output_type": "stream", 557 | "name": "stdout", 558 | "text": [ 559 | "Interpretation for Last 12 Months:\n", 560 | "\n", 561 | "At lag 1, p-value = 0.2625 >= 0.05, fail to reject null hypothesis.\n", 562 | "At lag 2, p-value = 0.5320 >= 0.05, fail to reject null hypothesis.\n", 563 | "At lag 3, p-value = 0.7349 >= 0.05, fail to reject null hypothesis.\n", 564 | "At lag 4, p-value = 0.7222 >= 0.05, fail to reject null hypothesis.\n", 565 | "At lag 5, p-value = 0.5898 >= 0.05, fail to reject null hypothesis.\n", 566 | "At lag 6, p-value = 0.6960 >= 0.05, fail to reject null hypothesis.\n", 567 | "At lag 7, p-value = 0.7833 >= 0.05, fail to reject null hypothesis.\n", 568 | "At lag 8, p-value = 0.8596 >= 0.05, fail to reject null hypothesis.\n", 569 | "At lag 9, p-value = 0.8915 >= 0.05, fail to reject null hypothesis.\n", 570 | "At lag 10, p-value = 0.9318 >= 0.05, fail to reject null hypothesis.\n", 571 | "At lag 11, p-value = 0.8824 >= 0.05, fail to reject null hypothesis.\n", 572 | "At lag 12, p-value = 0.9219 >= 0.05, fail to reject null hypothesis.\n", 573 | "At lag 13, p-value = 0.9501 >= 0.05, fail to reject null hypothesis.\n", 574 | "At lag 14, p-value = 0.7517 >= 0.05, fail to reject null hypothesis.\n", 575 | "At lag 15, p-value = 0.7980 >= 0.05, fail to reject null hypothesis.\n", 576 | "At lag 16, p-value = 0.8450 >= 0.05, fail to reject null hypothesis.\n", 577 | "At lag 17, p-value = 0.8781 >= 0.05, fail to reject null hypothesis.\n", 578 | "At lag 18, p-value = 0.9103 >= 0.05, fail to reject null hypothesis.\n", 579 | "At lag 19, p-value = 0.8747 >= 0.05, fail to reject null hypothesis.\n", 580 | "At lag 20, p-value = 0.9004 >= 0.05, fail to reject null hypothesis.\n", 581 | "At lag 21, p-value = 0.9189 >= 0.05, fail to reject null hypothesis.\n", 582 | "At lag 22, p-value = 0.8427 >= 0.05, fail to reject null hypothesis.\n", 583 | "At lag 23, p-value = 0.8776 >= 0.05, fail to reject null hypothesis.\n", 584 | "At lag 24, p-value = 0.9029 >= 0.05, fail to reject null hypothesis.\n", 585 | "At lag 25, p-value = 0.9079 >= 0.05, fail to reject null hypothesis.\n", 586 | "At lag 26, p-value = 0.8818 >= 0.05, fail to reject null hypothesis.\n", 587 | "At lag 27, p-value = 0.8956 >= 0.05, fail to reject null hypothesis.\n", 588 | "At lag 28, p-value = 0.9187 >= 0.05, fail to reject null hypothesis.\n", 589 | "At lag 29, p-value = 0.9270 >= 0.05, fail to reject null hypothesis.\n", 590 | "At lag 30, p-value = 0.9445 >= 0.05, fail to reject null hypothesis.\n", 591 | "\n", 592 | "\n", 593 | "Interpretation for Last 6 Months:\n", 594 | "\n", 595 | "At lag 1, p-value = 0.8411 >= 0.05, fail to reject null hypothesis.\n", 596 | "At lag 2, p-value = 0.9169 >= 0.05, fail to reject null hypothesis.\n", 597 | "At lag 3, p-value = 0.8624 >= 0.05, fail to reject null hypothesis.\n", 598 | "At lag 4, p-value = 0.7833 >= 0.05, fail to reject null hypothesis.\n", 599 | "At lag 5, p-value = 0.7594 >= 0.05, fail to reject null hypothesis.\n", 600 | "At lag 6, p-value = 0.8550 >= 0.05, fail to reject null hypothesis.\n", 601 | "At lag 7, p-value = 0.9042 >= 0.05, fail to reject null hypothesis.\n", 602 | "At lag 8, p-value = 0.9262 >= 0.05, fail to reject null hypothesis.\n", 603 | "At lag 9, p-value = 0.9305 >= 0.05, fail to reject null hypothesis.\n", 604 | "At lag 10, p-value = 0.9455 >= 0.05, fail to reject null hypothesis.\n", 605 | "At lag 11, p-value = 0.9682 >= 0.05, fail to reject null hypothesis.\n", 606 | "At lag 12, p-value = 0.9823 >= 0.05, fail to reject null hypothesis.\n", 607 | "At lag 13, p-value = 0.9903 >= 0.05, fail to reject null hypothesis.\n", 608 | "At lag 14, p-value = 0.8150 >= 0.05, fail to reject null hypothesis.\n", 609 | "At lag 15, p-value = 0.8220 >= 0.05, fail to reject null hypothesis.\n", 610 | "At lag 16, p-value = 0.8679 >= 0.05, fail to reject null hypothesis.\n", 611 | "At lag 17, p-value = 0.9038 >= 0.05, fail to reject null hypothesis.\n", 612 | "At lag 18, p-value = 0.9246 >= 0.05, fail to reject null hypothesis.\n", 613 | "At lag 19, p-value = 0.9451 >= 0.05, fail to reject null hypothesis.\n", 614 | "At lag 20, p-value = 0.9605 >= 0.05, fail to reject null hypothesis.\n", 615 | "At lag 21, p-value = 0.9694 >= 0.05, fail to reject null hypothesis.\n", 616 | "At lag 22, p-value = 0.9728 >= 0.05, fail to reject null hypothesis.\n", 617 | "At lag 23, p-value = 0.9673 >= 0.05, fail to reject null hypothesis.\n", 618 | "At lag 24, p-value = 0.9762 >= 0.05, fail to reject null hypothesis.\n", 619 | "At lag 25, p-value = 0.9657 >= 0.05, fail to reject null hypothesis.\n", 620 | "At lag 26, p-value = 0.9543 >= 0.05, fail to reject null hypothesis.\n", 621 | "At lag 27, p-value = 0.9401 >= 0.05, fail to reject null hypothesis.\n", 622 | "At lag 28, p-value = 0.9489 >= 0.05, fail to reject null hypothesis.\n", 623 | "At lag 29, p-value = 0.8860 >= 0.05, fail to reject null hypothesis.\n", 624 | "At lag 30, p-value = 0.9054 >= 0.05, fail to reject null hypothesis.\n", 625 | "\n", 626 | "\n", 627 | "Interpretation for Last 3 Months:\n", 628 | "\n", 629 | "At lag 1, p-value = 0.4644 >= 0.05, fail to reject null hypothesis.\n", 630 | "At lag 2, p-value = 0.7489 >= 0.05, fail to reject null hypothesis.\n", 631 | "At lag 3, p-value = 0.8746 >= 0.05, fail to reject null hypothesis.\n", 632 | "At lag 4, p-value = 0.9519 >= 0.05, fail to reject null hypothesis.\n", 633 | "At lag 5, p-value = 0.9702 >= 0.05, fail to reject null hypothesis.\n", 634 | "At lag 6, p-value = 0.9793 >= 0.05, fail to reject null hypothesis.\n", 635 | "At lag 7, p-value = 0.9269 >= 0.05, fail to reject null hypothesis.\n", 636 | "At lag 8, p-value = 0.9593 >= 0.05, fail to reject null hypothesis.\n", 637 | "At lag 9, p-value = 0.9639 >= 0.05, fail to reject null hypothesis.\n", 638 | "At lag 10, p-value = 0.9244 >= 0.05, fail to reject null hypothesis.\n", 639 | "At lag 11, p-value = 0.8445 >= 0.05, fail to reject null hypothesis.\n", 640 | "At lag 12, p-value = 0.8367 >= 0.05, fail to reject null hypothesis.\n", 641 | "At lag 13, p-value = 0.8715 >= 0.05, fail to reject null hypothesis.\n", 642 | "At lag 14, p-value = 0.7431 >= 0.05, fail to reject null hypothesis.\n", 643 | "At lag 15, p-value = 0.6873 >= 0.05, fail to reject null hypothesis.\n", 644 | "At lag 16, p-value = 0.1110 >= 0.05, fail to reject null hypothesis.\n", 645 | "At lag 17, p-value = 0.1268 >= 0.05, fail to reject null hypothesis.\n", 646 | "At lag 18, p-value = 0.1615 >= 0.05, fail to reject null hypothesis.\n", 647 | "At lag 19, p-value = 0.2032 >= 0.05, fail to reject null hypothesis.\n", 648 | "At lag 20, p-value = 0.2450 >= 0.05, fail to reject null hypothesis.\n", 649 | "At lag 21, p-value = 0.2527 >= 0.05, fail to reject null hypothesis.\n", 650 | "At lag 22, p-value = 0.2913 >= 0.05, fail to reject null hypothesis.\n", 651 | "At lag 23, p-value = 0.3371 >= 0.05, fail to reject null hypothesis.\n", 652 | "At lag 24, p-value = 0.3875 >= 0.05, fail to reject null hypothesis.\n", 653 | "At lag 25, p-value = 0.4397 >= 0.05, fail to reject null hypothesis.\n", 654 | "At lag 26, p-value = 0.4812 >= 0.05, fail to reject null hypothesis.\n", 655 | "At lag 27, p-value = 0.5332 >= 0.05, fail to reject null hypothesis.\n", 656 | "At lag 28, p-value = 0.5745 >= 0.05, fail to reject null hypothesis.\n", 657 | "At lag 29, p-value = 0.3613 >= 0.05, fail to reject null hypothesis.\n", 658 | "At lag 30, p-value = 0.3097 >= 0.05, fail to reject null hypothesis.\n", 659 | "\n", 660 | "\n" 661 | ] 662 | } 663 | ] 664 | } 665 | ] 666 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PythonFinanceAI 2 | 3 | ## Overview 4 | `PythonFinanceAI` is a dynamic repository combining AI and financial strategies. It features a variety of Python notebooks, each delving into different aspects of financial analysis and portfolio management using AI techniques. 5 | 6 | ## Contents 7 | The repository includes notebooks on a wide range of topics, from basic financial data analysis to complex AI-driven investment strategies. Each notebook is designed to be standalone, providing insights into various facets of AI in finance. 8 | 9 | ## How to Use 10 | Explore the repository to discover a variety of notebooks tailored to your interests. While these notebooks are designed to be user-friendly for both finance and AI enthusiasts, for comprehensive insights and detailed discussions that delve deeper into each topic, I highly recommend visiting my Medium articles. There, you'll find extensive explanations and additional context that enhance your understanding. Check out my Medium articles for a deeper dive into these subjects at [https://medium.com/@hugomichaelisss](https://medium.com/@hugomichaelisss). 11 | --------------------------------------------------------------------------------