mirror of
https://github.com/yongghongg/stock-screener.git
synced 2022-03-09 00:26:31 +03:00
Implementing the Squeeze Momentum Indicator in Python
This commit is contained in:
180
Squeeze_Momentum_Indicator_LazyBear_Demo.ipynb
Normal file
180
Squeeze_Momentum_Indicator_LazyBear_Demo.ipynb
Normal 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": []
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user