308 lines
7.2 KiB
Plaintext
308 lines
7.2 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "639e1d89",
|
|
"metadata": {},
|
|
"source": [
|
|
"<div style=\"background-color:#000;\"><img src=\"pqn.png\"></img></div>"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "0b7f6187",
|
|
"metadata": {},
|
|
"source": [
|
|
"This code downloads historical stock data for TLT, computes log returns, and analyzes mean returns by calendar day of the month. It visualizes these mean returns to identify any calendar effects. The code also simulates a simple trading strategy of buying near month-end and selling at month-start. It evaluates the strategy's performance by aggregating and plotting returns over time. This analysis helps in identifying potential trading opportunities based on calendar effects."
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "d7817a7b",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import pandas as pd\n",
|
|
"import numpy as np\n",
|
|
"import yfinance as yf"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "58832881",
|
|
"metadata": {},
|
|
"source": [
|
|
"Download historical stock data for TLT from Yahoo Finance"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "8181d627",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tlt = yf.download(\"TLT\", start=\"2002-01-01\", end=\"2022-06-30\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "19030c97",
|
|
"metadata": {},
|
|
"source": [
|
|
"Compute log returns for the adjusted closing prices"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "c4a980db",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tlt[\"log_return\"] = np.log(tlt[\"Adj Close\"] / tlt[\"Adj Close\"].shift(1))"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "3b1939d4",
|
|
"metadata": {},
|
|
"source": [
|
|
"Add a column indicating the day of the month for each data entry"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "09f90951",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tlt[\"day_of_month\"] = tlt.index.day"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "2984311e",
|
|
"metadata": {},
|
|
"source": [
|
|
"Add a column indicating the year for each data entry"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "75dabddb",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tlt[\"year\"] = tlt.index.year"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "8c32a1d9",
|
|
"metadata": {},
|
|
"source": [
|
|
"Group the data by the day of the month and compute the mean log returns"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "603cb273",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"grouped_by_day = tlt.groupby(\"day_of_month\").log_return.mean()"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "1b4f8529",
|
|
"metadata": {},
|
|
"source": [
|
|
"Plot the mean log returns by calendar day of the month"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "91560197",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"grouped_by_day.plot.bar(title=\"Mean Log Returns by Calendar Day of Month\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "140667ff",
|
|
"metadata": {},
|
|
"source": [
|
|
"Initialize a simple trading strategy of buying before month-end and selling at month-start"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "2b18f9df",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Set initial returns for the first week of the month to zero\n",
|
|
"tlt[\"first_week_returns\"] = 0.0"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "af93c085",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Assign log returns to the first week of the month\n",
|
|
"tlt.loc[tlt.day_of_month <= 7, \"first_week_returns\"] = tlt[tlt.day_of_month <= 7].log_return"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "6f309aad",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Set initial returns for the last week of the month to zero\n",
|
|
"tlt[\"last_week_returns\"] = 0.0"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "2059ffd3",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Assign log returns to the last week of the month\n",
|
|
"tlt.loc[tlt.day_of_month >= 23, \"last_week_returns\"] = tlt[tlt.day_of_month >= 23].log_return"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "62b0088e",
|
|
"metadata": {},
|
|
"source": [
|
|
"Compute the difference between last week returns and first week returns to simulate the strategy"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "ba54fbac",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tlt[\"last_week_less_first_week\"] = tlt.last_week_returns - tlt.first_week_returns"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "faa8c041",
|
|
"metadata": {},
|
|
"source": [
|
|
"Group the data by year and plot the mean returns of the strategy for each year"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "18bd50b3",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"(\n",
|
|
" tlt.groupby(\"year\")\n",
|
|
" .last_week_less_first_week.mean()\n",
|
|
" .plot.bar(title=\"Mean Log Strategy Returns by Year\")\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "5e426d67",
|
|
"metadata": {},
|
|
"source": [
|
|
"Group the data by year, compute cumulative sum of returns, and plot it"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "4deb5f87",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"(\n",
|
|
" tlt.groupby(\"year\")\n",
|
|
" .last_week_less_first_week.sum()\n",
|
|
" .cumsum()\n",
|
|
" .plot(title=\"Cumulative Sum of Returns By Year\")\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6d5019f4",
|
|
"metadata": {},
|
|
"source": [
|
|
"Compute and plot the cumulative sum of returns by day"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "fea7dc3f",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"tlt.last_week_less_first_week.cumsum().plot(title=\"Cumulative Sum of Returns By Day\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6dc28f61",
|
|
"metadata": {},
|
|
"source": [
|
|
"<a href=\"https://pyquantnews.com/\">PyQuant News</a> is where finance practitioners level up with Python for quant finance, algorithmic trading, and market data analysis. Looking to get started? Check out the fastest growing, top-selling course to <a href=\"https://gettingstartedwithpythonforquantfinance.com/\">get started with Python for quant finance</a>. For educational purposes. Not investment advise. Use at your own risk."
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"jupytext": {
|
|
"cell_metadata_filter": "-all",
|
|
"main_language": "python",
|
|
"notebook_metadata_filter": "-all"
|
|
},
|
|
"kernelspec": {
|
|
"display_name": "Python 3 (ipykernel)",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.10.13"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
}
|