Implementing the Squeeze Momentum Indicator in Python

This commit is contained in:
yongghongg
2021-07-23 01:01:08 +09:00
parent e1eac9bc32
commit 343a89902a

View File

@@ -0,0 +1,180 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"name": "Squeeze-Momentum-Indicator-LazyBear-Demo.ipynb",
"provenance": [],
"collapsed_sections": [],
"authorship_tag": "ABX9TyMPOlxSbHiQSr+XPYFnINuh",
"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/github/yongghongg/stock-screener/blob/main/Squeeze_Momentum_Indicator_LazyBear_Demo.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "nKgeIyzc7IMw"
},
"source": [
"A demo Colab Notebook for my Medium article 'Implementing the Squeeze Momentum Indicator in Python'"
]
},
{
"cell_type": "code",
"metadata": {
"id": "jZjYphw06_5Y"
},
"source": [
"!pip install yfinance\n",
"!pip install bs4\n",
"!pip install requests\n",
"!pip install ta\n",
"!pip install finta\n",
"!pip install mplfinance\n",
"import pandas as pd\n",
"import requests\n",
"from datetime import datetime\n",
"import yfinance as yf\n",
"from bs4 import BeautifulSoup\n",
"import numpy as np\n",
"import math\n",
"import mplfinance as mpf"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "CFmF-TFE0M3I"
},
"source": [
"screened_list = []\n",
"stock_list = ['AAPL','TSLA','MSFT','AMZN']\n",
"for stock_code in stock_list:\n",
" # get stock prices\n",
" df = yf.download(stock_code, start='2020-01-01', threads= False)\n",
"\n",
" # parameter setup\n",
" length = 20\n",
" mult = 2\n",
" length_KC = 20\n",
" mult_KC = 1.5\n",
"\n",
" # calculate BB\n",
" m_avg = df['Close'].rolling(window=length).mean()\n",
" m_std = df['Close'].rolling(window=length).std(ddof=0)\n",
" df['upper_BB'] = m_avg + mult * m_std\n",
" df['lower_BB'] = m_avg - mult * m_std\n",
"\n",
" # calculate true range\n",
" df['tr0'] = abs(df[\"High\"] - df[\"Low\"])\n",
" df['tr1'] = abs(df[\"High\"] - df[\"Close\"].shift())\n",
" df['tr2'] = abs(df[\"Low\"] - df[\"Close\"].shift())\n",
" df['tr'] = df[['tr0', 'tr1', 'tr2']].max(axis=1)\n",
"\n",
" # calculate KC\n",
" range_ma = df['tr'].rolling(window=length_KC).mean()\n",
" df['upper_KC'] = m_avg + range_ma * mult_KC\n",
" df['lower_KC'] = m_avg - range_ma * mult_KC\n",
"\n",
" # calculate bar value\n",
" highest = df['High'].rolling(window = length_KC).max()\n",
" lowest = df['Low'].rolling(window = length_KC).min()\n",
" m1 = (highest + lowest)/2\n",
" df['value'] = (df['Close'] - (m1 + m_avg)/2)\n",
" fit_y = np.array(range(0,length_KC))\n",
" df['value'] = df['value'].rolling(window = length_KC).apply(lambda x: \n",
" np.polyfit(fit_y, x, 1)[0] * (length_KC-1) + \n",
" np.polyfit(fit_y, x, 1)[1], raw=True)\n",
"\n",
" # check for 'squeeze'\n",
" df['squeeze_on'] = (df['lower_BB'] > df['lower_KC']) & (df['upper_BB'] < df['upper_KC'])\n",
" df['squeeze_off'] = (df['lower_BB'] < df['lower_KC']) & (df['upper_BB'] > df['upper_KC'])\n",
"\n",
" # buying window for long position:\n",
" # 1. black cross becomes gray (the squeeze is released)\n",
" long_cond1 = (df['squeeze_off'][-2] == False) & (df['squeeze_off'][-1] == True) \n",
" # 2. bar value is positive => the bar is light green k\n",
" long_cond2 = df['value'][-1] > 0\n",
" enter_long = long_cond1 and long_cond2\n",
"\n",
" # buying window for short position:\n",
" # 1. black cross becomes gray (the squeeze is released)\n",
" short_cond1 = (df['squeeze_off'][-2] == False) & (df['squeeze_off'][-1] == True) \n",
" # 2. bar value is negative => the bar is light red \n",
" short_cond2 = df['value'][-1] < 0\n",
" enter_short = short_cond1 and short_cond2\n",
"\n",
" if enter_long | enter_short:\n",
" screened_list.append(stock_code)\n",
"\n",
"if screened_list:\n",
" print(screened_list)\n",
"else:\n",
" print('No stock fits the Squeeze Momentum Indicator entry requirement')"
],
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"metadata": {
"id": "ZeSijaFbbt1w"
},
"source": [
"# to make the visualization better by only taking the last 100 rows of data\n",
"df = df[-100:]\n",
"\n",
"# extract only ['Open', 'High', 'Close', 'Low'] from df\n",
"ohcl = df[['Open', 'High', 'Close', 'Low']]\n",
"\n",
"# add colors for the 'value bar'\n",
"colors = []\n",
"for ind, val in enumerate(df['value']):\n",
" if val >= 0:\n",
" color = 'green'\n",
" if val > df['value'][ind-1]:\n",
" color = 'lime'\n",
" else:\n",
" color = 'maroon'\n",
" if val < df['value'][ind-1]:\n",
" color='red'\n",
" colors.append(color)\n",
" \n",
"# add 2 subplots: 1. bars, 2. crosses\n",
"apds = [mpf.make_addplot(df['value'], panel=1, type='bar', color=colors, alpha=0.8, secondary_y=False),\n",
" mpf.make_addplot([0] * len(df), panel=1, type='scatter', marker='x', markersize=50, color=['gray' if s else 'black' for s in df['squeeze_off']], secondary_y=False)]\n",
"\n",
"# plot ohcl with subplots\n",
"fig, axes = mpf.plot(ohcl, \n",
" volume_panel = 2,\n",
" figratio=(2,1),\n",
" figscale=1, \n",
" type='candle', \n",
" addplot=apds,\n",
" returnfig=True)"
],
"execution_count": null,
"outputs": []
}
]
}