-
-
Save EvanMarie/806986d1219bc051cc59bb180d06320a to your computer and use it in GitHub Desktop.
stock_helpers.ipynb
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"nbformat": 4, | |
"nbformat_minor": 0, | |
"metadata": { | |
"colab": { | |
"provenance": [], | |
"include_colab_link": true | |
}, | |
"kernelspec": { | |
"name": "python3", | |
"display_name": "Python 3" | |
}, | |
"language_info": { | |
"name": "python" | |
} | |
}, | |
"cells": [ | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"id": "view-in-github", | |
"colab_type": "text" | |
}, | |
"source": [ | |
"<a href=\"https://colab.research.google.com/gist/EvanMarie/806986d1219bc051cc59bb180d06320a/stock_helpers.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"import yfinance as yf\n", | |
"import pandas as pd\n", | |
"import numpy as np\n", | |
"import matplotlib as mpl\n", | |
"import matplotlib.pyplot as plt\n", | |
"pd.options.display.float_format = '{:,.3f}'.format\n", | |
"\n", | |
"OUTTER_BACK = '#222222'\n", | |
"INNER_BACK = '#333333'\n", | |
"FOREGROUND = 'white'" | |
], | |
"metadata": { | |
"id": "c15Sp_z4EnK5" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"# dataframe display formatting\n", | |
"\n", | |
"def color_negative_red(val):\n", | |
" color = 'red' if val < 0 else 'black'\n", | |
" return 'color: %s' % color\n", | |
"\n", | |
"def highlight_max(s):\n", | |
" is_max = s == s.max()\n", | |
" return ['color: blue' if v else '' for v in is_max]\n", | |
"\n", | |
"def style_data(data):\n", | |
" return data.style.\\\n", | |
" applymap(color_negative_red).\\\n", | |
" apply(highlight_max).\\\n", | |
" set_table_attributes('style=\"font-size: 14px\"').\\\n", | |
" format(thousands = ',', precision = '2')" | |
], | |
"metadata": { | |
"id": "51ie_WMqEede" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def display_me(df, num, title=None):\n", | |
" if type(df) != pd.core.frame.DataFrame:\n", | |
" df = df.to_frame()\n", | |
" print(\"\")\n", | |
" highlight(title.upper(), 'cyan', 'black', 3)\n", | |
" highlight(f'(FIRST {num} ROWS of DATA)', 'cyan', 'black', 3)\n", | |
" display(style_data(df.head(num)))\n", | |
" print(\"\")\n", | |
" highlight(f'(LAST {num} ROWS of DATA)', 'cyan', 'black', 3)\n", | |
" display(style_data(df.tail(num)))\n", | |
" print(\"\")" | |
], | |
"metadata": { | |
"id": "bQ6kH6J7Eea-" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def head2(data, num_rows):\n", | |
" return display(style_data(data.head(num_rows)))\n", | |
"\n", | |
"def tail2(data, num_rows):\n", | |
" return display(style_data(data.tail(num_rows)))\n", | |
"\n", | |
"def sample2(data, num_rows):\n", | |
" return display(style_data(data.sample(num_rows)))" | |
], | |
"metadata": { | |
"id": "bsj9e0yoEeYp" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def colorprint(text, color='#0038ff', fontsize = 3):\n", | |
" from IPython.display import HTML as html_print\n", | |
" return display(html_print(\"<b><font size={}><text style=color:{}>{}</text></font></b>\".format(fontsize, color, text)))\n", | |
"\n", | |
"def redprint(text, fontsize = 3):\n", | |
" from IPython.display import HTML as html_print\n", | |
" return display(html_print(\"<b><font size={}><text style=color:{}>{}</text></font></b>\".format(fontsize, '#ff0000', text)))\n", | |
"\n", | |
"def blueprint(text, fontsize = 3):\n", | |
" from IPython.display import HTML as html_print\n", | |
" return display(html_print(\"<b><font size={}><text style=color:{}>{}</text></font></b>\".format(fontsize, 'blue', text)))\n", | |
"\n", | |
"def purpleprint(text, fontsize = 3):\n", | |
" from IPython.display import HTML as html_print\n", | |
" return display(html_print(\"<b><font size={}><text style=color:{}>{}</text></font></b>\".format(fontsize, '#8d00ff', text)))\n", | |
"\n", | |
"def greenprint(text, fontsize = 3):\n", | |
" from IPython.display import HTML as html_print\n", | |
" return display(html_print(\"<b><font size={}><text style=color:{}>{}</text></font></b>\".format(fontsize, '#00b648', text)))" | |
], | |
"metadata": { | |
"id": "jJjfKNk4EeWN" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def highlight(text, highlight_color='yellow', \n", | |
" text_color='black', fontsize=2):\n", | |
" from IPython.display import HTML as html_print\n", | |
" return display(html_print(\"<span style='background-color:{}; padding: 0.5em 0.5em;'><b><font size={}><text style=color:{}>{}</text></font></b></span>\".format(highlight_color, fontsize, text_color, text)))" | |
], | |
"metadata": { | |
"id": "kazdOKFHEeT-" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def display_rows(display_list, num_cols, title):\n", | |
" print(\"........\" * num_cols)\n", | |
" highlight(f\"{title.upper()}:\", 'cyan', 'black', 3)\n", | |
" current = 0\n", | |
" length = len(display_list)\n", | |
" num_rows = round(length / num_cols)\n", | |
" for i in range(num_rows + 1):\n", | |
" print('\\t'.join([str(x) for x in list(display_list[current:current+num_cols])]))\n", | |
" current = current + num_cols\n", | |
" print(\"........\" * num_cols)\n", | |
" print('')" | |
], | |
"metadata": { | |
"id": "0MdOb08dEhYj" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def rows_cols(df, df_name):\n", | |
" df_rows = df.shape[0]\n", | |
" df_cols = df.shape[1]\n", | |
" highlight(f'📊 \"{df_name}\" has {df_rows:,} rows and {df_cols} columns.\\n', \n", | |
" 'yellow', 'black', 3)" | |
], | |
"metadata": { | |
"id": "F-49j7KNEhWU" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def print_date_range(df, data_name = None):\n", | |
" start_year, start_month, start_day = (df.index.min().year, \n", | |
" df.index.min().month_name(), \n", | |
" df.index.min().day)\n", | |
"\n", | |
" end_year, end_month, end_day = (df.index.max().year, \n", | |
" df.index.max().month_name(), \n", | |
" df.index.max().day)\n", | |
" \n", | |
" if data_name != None:\n", | |
" highlight(f'⏰ \"{data_name}\" time range: {start_month} {start_day}, {start_year} to {end_month} {end_day}, {end_year}', 'yellow', 'black', 3)\n", | |
" else:\n", | |
" highlight(f\"⏰ Time range: {start_month} {start_day}, {start_year} to {end_month} {end_day}, {end_year}\", 'yellow', 'black', 3)" | |
], | |
"metadata": { | |
"id": "cxn7m6U-EhT_" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def get_df_range(df, start, end):\n", | |
" return df.loc[start : end]" | |
], | |
"metadata": { | |
"id": "nRXfWJdSEhRh" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def annualized_data(returns, title = None):\n", | |
" annualized = returns.agg(['mean', 'std']).T\n", | |
" annualized['return'] = annualized[\"mean\"] * 250\n", | |
" annualized['risk'] = annualized['std'] * np.sqrt(250)\n", | |
" annualized.drop(columns = ['mean', 'std'], inplace = True)\n", | |
" if title != None:\n", | |
" highlight(f\"💰 Annualized Return and Risk: {title}\", \n", | |
" \"lime\", \"black\",fontsize=3)\n", | |
" else:\n", | |
" highlight(f\"💰 Annualized Return and Risk\", \n", | |
" \"lime\", \"black\",fontsize=3)\n", | |
" display(annualized)\n", | |
" return annualized" | |
], | |
"metadata": { | |
"id": "4Hw2saHxEhPD" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def line_graph(data, start=None, end=None, close_column=\"close\",\n", | |
" title=None, xlabel=None, ylabel=None):\n", | |
" \n", | |
" import matplotlib as mpl\n", | |
" import matplotlib.pyplot as plt\n", | |
" import random\n", | |
" colors = ['tomato', 'yellow', 'peachpuff', 'lime', 'turquoise',\n", | |
" 'aqua', 'deepskyblue', 'dodgerblue', 'cornflowerblue', 'lavender',\n", | |
" 'violet', 'fuchsia', 'deeppink']\n", | |
" \n", | |
" if (start != None) & (end != None):\n", | |
" data = data.loc[start : end, close_column].to_frame()\n", | |
" else:\n", | |
" data = data\n", | |
" \n", | |
" mpl.rcParams['font.family'] = 'monospace'\n", | |
" fig, ax = plt.subplots(facecolor = OUTTER_BACK, figsize = (13, 7))\n", | |
" plt.style.use(\"ggplot\");\n", | |
" ax.plot(data, color = random.choice(colors))\n", | |
" ax.set_facecolor(INNER_BACK)\n", | |
" ax.grid(color=FOREGROUND, linestyle=':', linewidth=0.65, alpha = 1)\n", | |
"\n", | |
" plt.tick_params(labelrotation = 40);\n", | |
" plt.title(title, fontsize = 23, pad = 20, color=\"white\");\n", | |
" plt.ylabel(ylabel, fontsize = 18, color=FOREGROUND);\n", | |
" plt.xlabel(xlabel, fontsize = 18, color=FOREGROUND);\n", | |
" plt.xticks(fontsize=12, color=\"white\")\n", | |
" plt.yticks(fontsize=12, color=\"white\")\n", | |
" \n", | |
" print_date_range(data)\n", | |
" print(\"\")" | |
], | |
"metadata": { | |
"id": "7s9uLmLnEhMj" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def plot_threshold_strategies(df, start_threshold=0.00, return_column='dj_return', \n", | |
" close_column='dj_close', increase_increment=0.01, \n", | |
" iterations=10, start = None, end = None):\n", | |
" import warnings\n", | |
" warnings.filterwarnings(\"ignore\")\n", | |
" \n", | |
" if (start != None) & (end != None):\n", | |
" df = df.loc[start : end, close_column].to_frame()\n", | |
" else:\n", | |
" df = df\n", | |
" \n", | |
" return_trigger = start_threshold\n", | |
" results_log = []\n", | |
" \n", | |
" for iteration in range(iterations):\n", | |
" df[\"position\"] = np.where(df[return_column] > return_trigger, -1, 1)\n", | |
" df[\"strategy_return\"] = df[\"position\"].shift() * df[return_column]\n", | |
" df['strategy'] = (df.strategy_return.add(1,\n", | |
" fill_value = 0).cumprod() * \\\n", | |
" df.iloc[0, 0])\n", | |
" current_data = (return_trigger, df[['dj_close', 'strategy']])\n", | |
" results_log.append(current_data)\n", | |
" return_trigger += increase_increment\n", | |
" \n", | |
" rows = round(len(results_log) / 2)\n", | |
" fig, axs = plt.subplots(nrows=rows, ncols=2, \n", | |
" figsize = (13, rows*4), facecolor=OUTTER_BACK, \n", | |
" constrained_layout=True)\n", | |
" \n", | |
" print_date_range(df)\n", | |
" print(\"\")\n", | |
" plt.style.use(\"ggplot\");\n", | |
" plt.suptitle(\"Simple Strategy Selling Threshold\", color = \"white\", size = 24)\n", | |
" for idx, i in enumerate(results_log):\n", | |
" return_trigger = results_log[idx][0]\n", | |
" close = results_log[idx][1][close_column]\n", | |
" returns = results_log[idx][1]['strategy']\n", | |
" ax = plt.axes();\n", | |
" ax.remove()\n", | |
" plt.subplot(rows, 2, idx+1, facecolor = INNER_BACK)\n", | |
" close.plot(color = 'cyan')\n", | |
" returns.plot(color = 'yellow')\n", | |
" plt.grid(color=FOREGROUND, linestyle=':', linewidth=0.65, alpha = 1)\n", | |
" plt.legend(loc = 2, facecolor = \"#555555\", labelcolor = \"white\")\n", | |
" plt.yticks(color = FOREGROUND)\n", | |
" plt.xticks(color = FOREGROUND)\n", | |
" plt.xlabel(\"years\", color=\"white\", size = 10)\n", | |
" plt.ylabel('')\n", | |
" plt.title(f\"Strategy: {(return_trigger*100):.0f}% Sell Threshold\", \n", | |
" color = \"white\", size = 15, pad = 5)\n", | |
" \n", | |
" return results_log " | |
], | |
"metadata": { | |
"id": "o1umHkUyEeRi" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def try_strategy(df, return_column=\"dj_return\", close_column=\"dj_close\", \n", | |
" strategy = 'momentum', threshold = None, start = None,\n", | |
" end = None):\n", | |
" \n", | |
" if (start != None) & (end != None):\n", | |
" df = df.loc[start : end, close_column].to_frame()\n", | |
" else:\n", | |
" df = df\n", | |
" \n", | |
" if strategy == 'momentum':\n", | |
" df['position'] = np.sign(df[return_column])\n", | |
" elif strategy == 'contrarian':\n", | |
" df[\"position\"] = -np.sign(df[return_column])\n", | |
" else:\n", | |
" df[\"position\"] = np.where(df[return_column] > threshold, -1, 1) \n", | |
" \n", | |
" df[\"strategy_return\"] = df[\"position\"].shift() * df['dj_return']\n", | |
" df['strategy'] = df.strategy_return.add(1, \n", | |
" fill_value = 0).cumprod() * df.iloc[0,0]\n", | |
" plt.figure(figsize = (13, 7), facecolor = OUTTER_BACK);\n", | |
" ax = plt.axes();\n", | |
" ax.set_facecolor(INNER_BACK)\n", | |
" ax.grid(color=FOREGROUND, linestyle=':', linewidth=0.75, alpha = 0.75)\n", | |
" \n", | |
" df[close_column].plot(color = 'deeppink')\n", | |
" df['strategy'].plot(color = 'yellow')\n", | |
" plt.legend(loc = 2, facecolor = \"white\", labelcolor = \"black\")\n", | |
" plt.yticks(color = FOREGROUND, size = 10)\n", | |
" plt.xticks(color = FOREGROUND, size = 10)\n", | |
" plt.xlabel(\"years\", color=\"white\", size = 14)\n", | |
" plt.ylabel('')\n", | |
" if threshold != None:\n", | |
" plt.title(f\"Strategy: {(threshold*100):.0f}% Sell Threshold\", \n", | |
" color = \"white\", size = 22, pad = 20,)\n", | |
" else:\n", | |
" plt.title(f\"Strategy: {strategy.capitalize()}\", \n", | |
" color = \"white\", size = 22, pad = 20,)\n", | |
" \n", | |
" \n", | |
" print_date_range(df)\n", | |
" print(\"\") \n", | |
" \n", | |
" annualized = annualized_data(df[[return_column, 'strategy_return']])\n", | |
" \n", | |
" return df, annualized \n" | |
], | |
"metadata": { | |
"id": "9hM1KnVOE_mE" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def rolling_average(df, close_column='dj_close', window=50,\n", | |
" start=None, end=None, legend_loc = 2):\n", | |
" \n", | |
" if (start != None) & (end != None):\n", | |
" df = df.loc[start : end, close_column].to_frame()\n", | |
" else:\n", | |
" df = df\n", | |
" \n", | |
" rolling_col = \"SMA\" + (str(window))\n", | |
" df[rolling_col] = df[close_column].rolling(window = window).mean()\n", | |
" close = df[close_column]\n", | |
" rolling = df[rolling_col]\n", | |
" \n", | |
" fig, ax = plt.subplots(facecolor = OUTTER_BACK, figsize = (13, 7))\n", | |
" plt.style.use(\"ggplot\");\n", | |
" ax.set_facecolor(INNER_BACK)\n", | |
" ax.grid(color=FOREGROUND, linestyle=':', linewidth=0.75, alpha = 0.75)\n", | |
"\n", | |
" plt.tick_params(labelrotation = 40);\n", | |
" plt.title(f\"Rolling Averge: {window} day window\", fontsize = 21, pad = 20, color=\"white\");\n", | |
" plt.ylabel('', fontsize = 18, color=FOREGROUND);\n", | |
" plt.xlabel('', fontsize = 18, color=FOREGROUND);\n", | |
" plt.xticks(fontsize=12, color=FOREGROUND)\n", | |
" plt.yticks(fontsize=12, color=FOREGROUND)\n", | |
" close.plot(color='deeppink', linewidth=5, alpha = 0.7)\n", | |
" rolling.plot(color='cyan') \n", | |
" plt.legend(fontsize = 13, facecolor = INNER_BACK, \n", | |
" labelcolor = FOREGROUND, loc = legend_loc)\n", | |
" \n", | |
" print_date_range(df)\n", | |
" print(\"\") " | |
], | |
"metadata": { | |
"id": "hstB1Mg_FEsN" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def multiple_rolling_averages(df, close_column='dj_close', \n", | |
" window_list=[50], start=None,\n", | |
" end=None, legend_loc = 2):\n", | |
" import random\n", | |
" \n", | |
" colors = ['tomato', 'yellow', 'peachpuff', 'lime', 'turquoise',\n", | |
" 'aqua', 'deepskyblue', 'dodgerblue', 'cornflowerblue', 'lavender',\n", | |
" 'violet', 'fuchsia', 'deeppink']\n", | |
" \n", | |
" color_list = random.sample(colors, len(window_list))\n", | |
" \n", | |
" if (start != None) & (end != None):\n", | |
" df = df.loc[start : end, close_column].to_frame()\n", | |
" else:\n", | |
" df = df\n", | |
" \n", | |
" close = df[close_column]\n", | |
" window_log = []\n", | |
" \n", | |
" for i in window_list:\n", | |
" rolling_col = \"SMA\" + (str(i))\n", | |
" rolling = df[close_column].rolling(window = i).mean()\n", | |
" current_data = (rolling_col, rolling)\n", | |
" window_log.append(current_data)\n", | |
" \n", | |
" fig, ax = plt.subplots(facecolor = OUTTER_BACK, figsize = (13, 7))\n", | |
" plt.style.use(\"ggplot\");\n", | |
" ax.set_facecolor(INNER_BACK)\n", | |
" ax.grid(color=FOREGROUND, linestyle=':', linewidth=0.75, alpha = 0.75)\n", | |
" plt.tick_params(labelrotation = 40);\n", | |
" \n", | |
" if len(window_list) < 5:\n", | |
" title_string = ', '.join(str(i) for i in window_list)\n", | |
" plt.title(f\"Rolling Averges Compared: {title_string} days\", fontsize = 20, pad = 20, color=\"white\");\n", | |
" else:\n", | |
" plt.title(f\"Rolling Averges Compared\", fontsize = 22, pad = 20, color=\"white\");\n", | |
" \n", | |
" plt.ylabel('', fontsize = 18, color=FOREGROUND);\n", | |
" plt.xlabel('', fontsize = 18, color=FOREGROUND);\n", | |
" plt.xticks(fontsize=12, color=FOREGROUND)\n", | |
" plt.yticks(fontsize=12, color=FOREGROUND) \n", | |
" labels = [x[0] for x in window_log]\n", | |
" \n", | |
" for idx, i in enumerate(window_log):\n", | |
" ax.plot(i[1], color = color_list[idx], label = i[0])\n", | |
" \n", | |
" plt.legend(loc = legend_loc, fontsize = 13, \n", | |
" facecolor = INNER_BACK, labelcolor = FOREGROUND)\n", | |
" \n", | |
" print_date_range(df)\n", | |
" print(\"\") " | |
], | |
"metadata": { | |
"id": "9I4ud_OGFEpT" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def fancy_plot(data, kind = \"line\", title = None, legend_loc = 'upper right', \n", | |
" start=None, end=None, xlabel=None, ylabel=None, logy=False,\n", | |
" cmap = 'viridis', label_rot = None):\n", | |
" \n", | |
" import random \n", | |
" import matplotlib as mpl\n", | |
" import matplotlib.pyplot as plt\n", | |
" \n", | |
" if (start != None) & (end != None):\n", | |
" data = data.loc[start : end]\n", | |
" else:\n", | |
" data = data\n", | |
" \n", | |
" mpl.rcParams['xtick.color'] = OUTTER_BACK\n", | |
" mpl.rcParams['ytick.color'] = OUTTER_BACK\n", | |
" mpl.rcParams['font.family'] = 'monospace'\n", | |
" fig = plt.subplots(facecolor = OUTTER_BACK, figsize = (13, 7))\n", | |
" ax = plt.axes();\n", | |
" if kind == 'line':\n", | |
" data.plot(kind='line', ax = ax, rot = label_rot, cmap = cmap)\n", | |
" else:\n", | |
" data.plot(kind = kind, ax = ax, rot = label_rot, cmap = cmap);\n", | |
" plt.style.use(\"ggplot\");\n", | |
" ax.set_facecolor(INNER_BACK)\n", | |
" ax.grid(color=FOREGROUND, linestyle=':', linewidth=0.75, alpha = 0.75)\n", | |
" plt.tick_params(labelrotation = 40);\n", | |
" plt.title(title, fontsize = 23, pad = 20, color=\"white\");\n", | |
" plt.ylabel(ylabel, fontsize = 18, color=FOREGROUND);\n", | |
" plt.xlabel(xlabel, fontsize = 18, color=FOREGROUND);\n", | |
" plt.xticks(fontsize=10, color=FOREGROUND)\n", | |
" plt.yticks(fontsize=10, color=FOREGROUND)\n", | |
" plt.legend(labels = data.columns, fontsize = 10, loc = legend_loc,\n", | |
" facecolor = INNER_BACK, labelcolor = FOREGROUND)" | |
], | |
"metadata": { | |
"id": "ncrOobeLFEm9" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def correlation_heatmap(df, cmap, annot = True, fmt = '.1g',\n", | |
" vmin = 0.2, vmax = 0.8,\n", | |
" title = None, ):\n", | |
" import seaborn as sns\n", | |
" correlation_map = df.corr()\n", | |
" plt.figure(figsize = (13,9), facecolor = OUTTER_BACK)\n", | |
"\n", | |
" sns.heatmap(correlation_map, cmap = cmap, annot = annot, vmin = vmin,\n", | |
" vmax = vmax, linewidth=0.25, linecolor = \"white\", fmt = fmt) \n", | |
" plt.title(title, fontsize = 23, pad = 20, color=\"white\");\n", | |
" plt.xticks(fontsize=11, color=\"white\")\n", | |
" plt.yticks(fontsize=11, color=\"white\")" | |
], | |
"metadata": { | |
"id": "Kpwk2TwIFEkI" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def portfolio_returns(weights, portfolio):\n", | |
" return portfolio.dot(weights)\n", | |
"\n", | |
"\n", | |
"def tracking_error(weights, portfolio, index_data):\n", | |
" result = portfolio_returns(weights, portfolio).sub(index_data).std() * np.sqrt(250)\n", | |
" colorprint(f'The annualized tracking error for the portfolio is {(result*100):.2f}%', fontsize = 3)\n", | |
" return result\n", | |
" \n", | |
" \n", | |
"def tracking_error_general(data, portfolio_list, weights, \n", | |
" index, start, end, title = None,\n", | |
" printout=True):\n", | |
" \n", | |
" results = data.loc[start:end, portfolio_list].dot(weights).\\\n", | |
" sub(data.loc[start:end, index]).std() * np.sqrt(250)\n", | |
" if printout is True:\n", | |
" highlight(title, 'yellow', 'black', 2)\n", | |
" highlight(f'Period: {start} to {end}', 'yellow', 'black', 2)\n", | |
" highlight(f'Overall tracking error: {(results *100): .2f}%', 'yellow', 'black', 2)\n", | |
" else:\n", | |
" return results" | |
], | |
"metadata": { | |
"id": "zu7Sy6NrFEhm" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def visualize_tracking(data, portfolio_list, weights, index, start, end, \n", | |
" title=None, xlabel=None, ylabel=None, legend_loc=1, \n", | |
" cmap = 'rainbow', legend_labels = None, color1='red',\n", | |
" color2 = 'cyan'):\n", | |
" track = data.loc[start:end, portfolio_list].dot(weights).add(1).cumprod().mul(100)\n", | |
" track.name = 'Portfolio'\n", | |
" index = data.loc[start:end, index].add(1).cumprod().mul(100)\n", | |
" mpl.rcParams['xtick.color'] = OUTTER_BACK\n", | |
" mpl.rcParams['ytick.color'] = OUTTER_BACK\n", | |
" mpl.rcParams['font.family'] = 'monospace'\n", | |
" fig = plt.subplots(facecolor = OUTTER_BACK, figsize = (13, 7))\n", | |
" ax = plt.axes();\n", | |
" track.plot(ax = ax, color = color1)\n", | |
" index.plot(ax = ax, color = color2)\n", | |
" plt.legend(fontsize = 15, loc = 2)\n", | |
" plt.title(title, fontsize = 22, pad = 20)\n", | |
" plt.style.use(\"ggplot\");\n", | |
" ax.set_facecolor(INNER_BACK)\n", | |
" ax.grid(color=FOREGROUND, linestyle=':', linewidth=0.75, alpha = 0.75)\n", | |
" plt.tick_params(labelrotation = 40);\n", | |
" plt.title(title, fontsize = 23, pad = 20, color=\"white\");\n", | |
" plt.ylabel(ylabel, fontsize = 18, color=FOREGROUND);\n", | |
" plt.xlabel(xlabel, fontsize = 18, color=FOREGROUND);\n", | |
" plt.xticks(fontsize=10, color=FOREGROUND)\n", | |
" plt.yticks(fontsize=10, color=FOREGROUND)\n", | |
" plt.legend(labels = legend_labels, fontsize = 11, loc = legend_loc,\n", | |
" facecolor = INNER_BACK, labelcolor = FOREGROUND)\n", | |
" plt.show() " | |
], | |
"metadata": { | |
"id": "dS8vZAaZFZR6" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"source": [ | |
"def random_portfolios(num_portfolios, total_assets,\n", | |
" returns_df, stocks_list, seed = 123):\n", | |
" \n", | |
" np.random.seed(seed)\n", | |
" random_error_collection = np.empty(25000)\n", | |
" random_stocks = np.random.choice(stocks_list, size = total_assets, replace = False)\n", | |
" for i in range(25000):\n", | |
" random_numbers = np.random.random(total_assets)\n", | |
" random_weights = random_numbers / random_numbers.sum()\n", | |
" random_stock = np.random.choice(stocks_list, size = total_assets, replace = False)\n", | |
"\n", | |
" random_error_collection[i] = \\\n", | |
" tracking_error_general(returns_df,\n", | |
" random_stocks,\n", | |
" random_weights,\n", | |
" 'DJI', '2020', \n", | |
" '2022', \n", | |
" printout = False)\n", | |
" return random_error_collection" | |
], | |
"metadata": { | |
"id": "mzvxuao9FZPs" | |
}, | |
"execution_count": null, | |
"outputs": [] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"id": "3Pbhahof_7st" | |
}, | |
"outputs": [], | |
"source": [ | |
"def distro_histo(data, num_bins, color='cyan', edgecolor='black',\n", | |
" title=None, xlabel=None, ylabel=None, legend_loc=None,\n", | |
" legend_labels=None):\n", | |
" plt.figure(figsize = (12, 8), facecolor = OUTTER_BACK)\n", | |
" ax = plt.axes();\n", | |
" ax.set_facecolor(INNER_BACK)\n", | |
" plt.hist(data, bins = num_bins, edgecolor = edgecolor, \n", | |
" linewidth = 0.5, color = \"cyan\")\n", | |
" plt.title(title, fontsize = 22, pad = 20)\n", | |
" plt.style.use(\"ggplot\");\n", | |
" ax.grid(color=FOREGROUND, linestyle=':', linewidth=0.75, alpha = 0.75)\n", | |
" plt.tick_params(labelrotation = 40);\n", | |
" plt.title(title, fontsize = 21, pad = 20, color=\"white\");\n", | |
" plt.ylabel(ylabel, fontsize = 18, color=FOREGROUND);\n", | |
" plt.xlabel(xlabel, fontsize = 18, color=FOREGROUND);\n", | |
" plt.xticks(fontsize=10, color=FOREGROUND)\n", | |
" plt.yticks(fontsize=10, color=FOREGROUND)\n", | |
" if legend_labels != None:\n", | |
" plt.legend(labels = legend_labels, fontsize = 13, loc = legend_loc,\n", | |
" facecolor = INNER_BACK, labelcolor = FOREGROUND)\n", | |
" plt.show()\n", | |
"\n", | |
"\n", | |
"def compare_random_optimized(random_error_data, optimized_tracking_data, num_portfolios):\n", | |
" # Retrieving the results of random portfolios and comparing to optimized \n", | |
" # weight strategy\n", | |
" highlight(f'The optimized strategy outperformed {num_portfolios:,.0f} \\\n", | |
" random portfolios and weights {((1 - (random_error_data < optimized_tracking_data).mean()) \\\n", | |
" * 100):.2f}% of the time.', fontsize = 3)\n", | |
" highlight(f'{num_portfolios:,.0f} random portfolios & weights tracking error: \\\n", | |
" {(random_error_data.mean() * 100): .2f}%', fontsize = 3)\n", | |
" highlight(f'Optimized portfolio & weights tracking error: {(optimized_tracking_data \\\n", | |
" * 100):.2f}%', fontsize = 3)\n", | |
" print(\"\")\n", | |
"\n", | |
" # Plotting the distribution of tracking error across the random portfolios\n", | |
" distro_histo(random_error_data, 100, \"cyan\", \"black\",\n", | |
" title = f'Tracking Errors Across {num_portfolios:,.0f} \\\n", | |
" Random Portfolios',\n", | |
" xlabel = \"tracking errors across random portfolios\",\n", | |
" ylabel = \"count for tracking errors\")" | |
] | |
} | |
] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment