├── 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"," AAPL | \n"," AMZN | \n"," MSFT | \n"," GOOGL | \n"," META | \n"," TSLA | \n"," NVDA | \n"," ADBE | \n"," NFLX | \n"," INTC | \n","
\n"," \n"," Date | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n","
\n"," \n"," \n"," \n"," 2018-09-12 00:00:00-04:00 | \n"," 52.931549 | \n"," 99.500000 | \n"," 105.837601 | \n"," 58.580002 | \n"," 162.000000 | \n"," 19.369333 | \n"," 66.468536 | \n"," 267.790009 | \n"," 369.950012 | \n"," 39.068569 | \n","
\n"," \n"," 2018-09-13 00:00:00-04:00 | \n"," 54.210121 | \n"," 99.493500 | \n"," 106.974503 | \n"," 59.106998 | \n"," 161.360001 | \n"," 19.297333 | \n"," 67.246727 | \n"," 268.519989 | \n"," 368.149994 | \n"," 39.625080 | \n","
\n"," \n"," 2018-09-14 00:00:00-04:00 | \n"," 53.594776 | \n"," 98.509499 | \n"," 107.410316 | \n"," 58.898998 | \n"," 162.320007 | \n"," 19.680000 | \n"," 68.508194 | \n"," 274.690002 | \n"," 364.559998 | \n"," 39.598984 | \n","
\n"," \n"," 2018-09-17 00:00:00-04:00 | \n"," 52.167751 | \n"," 95.401497 | \n"," 106.244987 | \n"," 57.991501 | \n"," 160.580002 | \n"," 19.656000 | \n"," 67.888626 | \n"," 268.250000 | \n"," 350.350006 | \n"," 39.494640 | \n","
\n"," \n"," 2018-09-18 00:00:00-04:00 | \n"," 52.253948 | \n"," 97.052498 | \n"," 107.258720 | \n"," 58.355499 | \n"," 160.300003 | \n"," 18.997334 | \n"," 67.167412 | \n"," 270.790009 | \n"," 367.649994 | \n"," 40.085926 | \n","
\n"," \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n","
\n"," \n"," 2023-09-05 00:00:00-04:00 | \n"," 189.699997 | \n"," 137.270004 | \n"," 333.549988 | \n"," 135.770004 | \n"," 300.149994 | \n"," 256.489990 | \n"," 485.440033 | \n"," 564.880005 | \n"," 448.679993 | \n"," 36.709999 | \n","
\n"," \n"," 2023-09-06 00:00:00-04:00 | \n"," 182.910004 | \n"," 135.360001 | \n"," 332.880005 | \n"," 134.460007 | \n"," 299.170013 | \n"," 251.919998 | \n"," 470.609985 | \n"," 561.940002 | \n"," 445.760010 | \n"," 36.980000 | \n","
\n"," \n"," 2023-09-07 00:00:00-04:00 | \n"," 177.559998 | \n"," 137.850006 | \n"," 329.910004 | \n"," 135.259995 | \n"," 298.670013 | \n"," 251.490005 | \n"," 462.410004 | \n"," 560.460022 | \n"," 443.140015 | \n"," 38.180000 | \n","
\n"," \n"," 2023-09-08 00:00:00-04:00 | \n"," 178.179993 | \n"," 138.229996 | \n"," 334.269989 | \n"," 136.380005 | \n"," 297.890015 | \n"," 248.500000 | \n"," 455.720001 | \n"," 560.359985 | \n"," 442.799988 | \n"," 38.009998 | \n","
\n"," \n"," 2023-09-11 00:00:00-04:00 | \n"," 179.554794 | \n"," 142.520004 | \n"," 337.945007 | \n"," 136.949997 | \n"," 307.040009 | \n"," 274.359985 | \n"," 450.220001 | \n"," 564.559998 | \n"," 447.609985 | \n"," 38.564999 | \n","
\n"," \n","
\n","
1257 rows × 10 columns
\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"," Selected Stocks | \n"," Profit Before Tax | \n"," Tax Paid | \n"," Portfolio Value | \n","
\n"," \n"," Date | \n"," | \n"," | \n"," | \n"," | \n","
\n"," \n"," \n"," \n"," 2018-09-30 00:00:00-04:00 | \n"," NaN | \n"," NaN | \n"," NaN | \n"," 100000 | \n","
\n"," \n"," 2018-10-31 00:00:00-04:00 | \n"," NaN | \n"," NaN | \n"," NaN | \n"," 100000 | \n","
\n"," \n"," 2018-11-30 00:00:00-05:00 | \n"," [\"TSLA\"] | \n"," 3901.34 | \n"," 585.2 | \n"," 103316.14 | \n","
\n"," \n"," 2018-12-31 00:00:00-05:00 | \n"," [\"INTC\", \"AMZN\", \"MSFT\"] | \n"," -8391.44 | \n"," NaN | \n"," 94924.7 | \n","
\n"," \n"," 2019-01-31 00:00:00-05:00 | \n"," NaN | \n"," NaN | \n"," NaN | \n"," 94924.7 | \n","
\n"," \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n","
\n"," \n"," 2023-05-31 00:00:00-04:00 | \n"," [\"META\", \"MSFT\", \"GOOGL\"] | \n"," 44876.21 | \n"," 6731.43 | \n"," 462416.15 | \n","
\n"," \n"," 2023-06-30 00:00:00-04:00 | \n"," [\"NVDA\", \"TSLA\", \"NFLX\"] | \n"," 79589.96 | \n"," 11938.49 | \n"," 530067.61 | \n","
\n"," \n"," 2023-07-31 00:00:00-04:00 | \n"," [\"TSLA\", \"ADBE\", \"NVDA\"] | \n"," 42972.46 | \n"," 6445.87 | \n"," 566594.2 | \n","
\n"," \n"," 2023-08-31 00:00:00-04:00 | \n"," [\"ADBE\", \"META\", \"GOOGL\"] | \n"," -3998.75 | \n"," NaN | \n"," 562595.45 | \n","
\n"," \n"," 2023-09-30 00:00:00-04:00 | \n"," [\"NVDA\", \"AMZN\", \"GOOGL\"] | \n"," -9247.26 | \n"," NaN | \n"," 553348.19 | \n","
\n"," \n","
\n","
61 rows × 4 columns
\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"," AAPL | \n"," AMZN | \n"," MSFT | \n"," GOOGL | \n"," META | \n"," TSLA | \n"," NVDA | \n"," ADBE | \n"," NFLX | \n"," INTC | \n"," Portfolio Value | \n"," Baseline | \n","
\n"," \n"," Date | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n"," | \n","
\n"," \n"," \n"," \n"," 2018-09-30 00:00:00-04:00 | \n"," 100000 | \n"," 100000 | \n"," 100000 | \n"," 100000 | \n"," 100000 | \n"," 100000 | \n"," 100000 | \n"," 100000 | \n"," 100000 | \n"," 100000 | \n"," 100000 | \n"," 100000 | \n","
\n"," \n"," 2018-10-31 00:00:00-04:00 | \n"," 96952 | \n"," 79780 | \n"," 93389 | \n"," 90348 | \n"," 92295 | \n"," 127401 | \n"," 75023 | \n"," 91039 | \n"," 80661 | \n"," 99133 | \n"," 100000 | \n"," 92602 | \n","
\n"," \n"," 2018-11-30 00:00:00-05:00 | \n"," 79384 | \n"," 84381 | \n"," 97376 | \n"," 91928 | \n"," 85497 | \n"," 132371 | \n"," 58214 | \n"," 92939 | \n"," 76478 | \n"," 104927 | \n"," 103316 | \n"," 90350 | \n","
\n"," \n"," 2018-12-31 00:00:00-05:00 | \n"," 70120 | \n"," 74986 | \n"," 89191 | \n"," 86569 | \n"," 79709 | \n"," 125694 | \n"," 47553 | \n"," 83808 | \n"," 71541 | \n"," 99863 | \n"," 94924 | \n"," 82903 | \n","
\n"," \n"," 2019-01-31 00:00:00-05:00 | \n"," 73988 | \n"," 85807 | \n"," 91703 | \n"," 93273 | \n"," 101355 | \n"," 115957 | \n"," 51204 | \n"," 91802 | \n"," 90743 | \n"," 100267 | \n"," 94924 | \n"," 89610 | \n","
\n"," \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n"," ... | \n","
\n"," \n"," 2023-05-31 00:00:00-04:00 | \n"," 327496 | \n"," 120399 | \n"," 302420 | \n"," 203582 | \n"," 160963 | \n"," 1155323 | \n"," 543134 | \n"," 154765 | \n"," 105639 | \n"," 76183 | \n"," 462416 | \n"," 314990 | \n","
\n"," \n"," 2023-06-30 00:00:00-04:00 | \n"," 358389 | \n"," 130164 | \n"," 313609 | \n"," 198329 | \n"," 174498 | \n"," 1483004 | \n"," 607338 | \n"," 181140 | \n"," 117737 | \n"," 81030 | \n"," 530067 | \n"," 364524 | \n","
\n"," \n"," 2023-07-31 00:00:00-04:00 | \n"," 362971 | \n"," 133479 | \n"," 309355 | \n"," 219902 | \n"," 193724 | \n"," 1515069 | \n"," 670897 | \n"," 202322 | \n"," 117330 | \n"," 86676 | \n"," 566594 | \n"," 381173 | \n","
\n"," \n"," 2023-08-31 00:00:00-04:00 | \n"," 347587 | \n"," 137803 | \n"," 302479 | \n"," 225618 | \n"," 179916 | \n"," 1462099 | \n"," 708599 | \n"," 207201 | \n"," 115916 | \n"," 85455 | \n"," 562595 | \n"," 377267 | \n","
\n"," \n"," 2023-09-30 00:00:00-04:00 | \n"," 332203 | \n"," 142306 | \n"," 311878 | \n"," 226911 | \n"," 186695 | \n"," 1554330 | \n"," 646443 | \n"," 209135 | \n"," 119640 | \n"," 93784 | \n"," 553348 | \n"," 382332 | \n","
\n"," \n","
\n","
61 rows × 12 columns
\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",""]},"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 | " Adj Close | \n",
134 | "
\n",
135 | " \n",
136 | " Date | \n",
137 | " | \n",
138 | "
\n",
139 | " \n",
140 | " \n",
141 | " \n",
142 | " 2024-09-10 | \n",
143 | " 220.110001 | \n",
144 | "
\n",
145 | " \n",
146 | " 2024-09-11 | \n",
147 | " 222.660004 | \n",
148 | "
\n",
149 | " \n",
150 | " 2024-09-12 | \n",
151 | " 222.770004 | \n",
152 | "
\n",
153 | " \n",
154 | " 2024-09-13 | \n",
155 | " 222.500000 | \n",
156 | "
\n",
157 | " \n",
158 | " 2024-09-16 | \n",
159 | " 215.929993 | \n",
160 | "
\n",
161 | " \n",
162 | "
\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 | " Adj Close | \n",
232 | "
\n",
233 | " \n",
234 | " Date | \n",
235 | " | \n",
236 | "
\n",
237 | " \n",
238 | " \n",
239 | " \n",
240 | " 1980-12-15 | \n",
241 | " -0.053581 | \n",
242 | "
\n",
243 | " \n",
244 | " 1980-12-16 | \n",
245 | " -0.076231 | \n",
246 | "
\n",
247 | " \n",
248 | " 1980-12-17 | \n",
249 | " 0.024450 | \n",
250 | "
\n",
251 | " \n",
252 | " 1980-12-18 | \n",
253 | " 0.028580 | \n",
254 | "
\n",
255 | " \n",
256 | " 1980-12-19 | \n",
257 | " 0.059238 | \n",
258 | "
\n",
259 | " \n",
260 | "
\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 |
--------------------------------------------------------------------------------