|
| 1 | +{ |
| 2 | + "cells": [ |
| 3 | + { |
| 4 | + "cell_type": "markdown", |
| 5 | + "id": "fb4c77e0-f8b7-47fa-b514-35c5161ee7ca", |
| 6 | + "metadata": {}, |
| 7 | + "source": [ |
| 8 | + "# Screener 02\n", |
| 9 | + "\n", |
| 10 | + "https://readmedium.com/en/https:/wire.insiderfinance.io/identifying-breakout-stocks-with-python-a-data-driven-selection-guide-d8a3d1ba172e\n", |
| 11 | + "https://github.com/shashankvemuri/Finance/blob/master/find_stocks/get_rsi_tickers.py\n", |
| 12 | + "\n", |
| 13 | + "https://medium.com/@redeaddiscolll\n", |
| 14 | + "https://medium.com/@py.chin315\n", |
| 15 | + "https://github.com/peiyingchin/Medium/blob/main/Trading%20strategy%20with%2055%25%20win%20chance/Trading%20strategy%20with%2055%25%20win%20chance.ipynb" |
| 16 | + ] |
| 17 | + }, |
| 18 | + { |
| 19 | + "cell_type": "code", |
| 20 | + "execution_count": 2, |
| 21 | + "id": "00beccde-3951-4426-a338-29a19777f853", |
| 22 | + "metadata": {}, |
| 23 | + "outputs": [ |
| 24 | + { |
| 25 | + "ename": "KeyError", |
| 26 | + "evalue": "['Target Price', 'P/E']", |
| 27 | + "output_type": "error", |
| 28 | + "traceback": [ |
| 29 | + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", |
| 30 | + "\u001b[0;31mKeyError\u001b[0m Traceback (most recent call last)", |
| 31 | + "\u001b[0;32m/tmp/ipykernel_27437/3637564337.py\u001b[0m in \u001b[0;36m?\u001b[0;34m()\u001b[0m\n\u001b[1;32m 27\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mtop_candidates\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'Ticker'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Company'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Sector'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Industry'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Price'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Volume'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'P/E'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Target Price'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Price to Target %'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'Composite Score'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 28\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 29\u001b[0m \u001b[0;31m# Usage of the function with the path to the CSV file\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 30\u001b[0m \u001b[0mcsv_file_path\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m'nifty50_symbols.txt'\u001b[0m \u001b[0;31m# Replace with your actual file path\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 31\u001b[0;31m \u001b[0mselected_stocks\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mselect_breakout_candidates\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcsv_file_path\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 32\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[0;31m# Display the selected stocks\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 34\u001b[0m \u001b[0mselected_stocks\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
| 32 | + "\u001b[0;32m/tmp/ipykernel_27437/3637564337.py\u001b[0m in \u001b[0;36m?\u001b[0;34m(csv_path)\u001b[0m\n\u001b[1;32m 5\u001b[0m \u001b[0;31m# Load the dataset\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6\u001b[0m \u001b[0mstock_data\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mpd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mread_csv\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mcsv_path\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;31m# Preprocessing and filtering based on the provided criteria\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 9\u001b[0;31m \u001b[0mstock_data_filtered\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mstock_data\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdropna\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msubset\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'Target Price'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'P/E'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 10\u001b[0m \u001b[0mstock_data_filtered\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mstock_data_filtered\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mstock_data_filtered\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'Price'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m<\u001b[0m \u001b[0mstock_data_filtered\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'Target Price'\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 11\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;31m# Calculate additional metrics\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
| 33 | + "\u001b[0;32m~/stock-market/env3/lib/python3.10/site-packages/pandas/core/frame.py\u001b[0m in \u001b[0;36m?\u001b[0;34m(self, axis, how, thresh, subset, inplace, ignore_index)\u001b[0m\n\u001b[1;32m 6414\u001b[0m \u001b[0max\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_get_axis\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0magg_axis\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6415\u001b[0m \u001b[0mindices\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0max\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mget_indexer_for\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msubset\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6416\u001b[0m \u001b[0mcheck\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mindices\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0;36m1\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6417\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcheck\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0many\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 6418\u001b[0;31m \u001b[0;32mraise\u001b[0m \u001b[0mKeyError\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msubset\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mcheck\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtolist\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6419\u001b[0m \u001b[0magg_obj\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtake\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mindices\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0maxis\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0magg_axis\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6420\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 6421\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mthresh\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mlib\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mno_default\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", |
| 34 | + "\u001b[0;31mKeyError\u001b[0m: ['Target Price', 'P/E']" |
| 35 | + ] |
| 36 | + } |
| 37 | + ], |
| 38 | + "source": [ |
| 39 | + "import pandas as pd\n", |
| 40 | + "\n", |
| 41 | + "# Define the function to load data and select breakout stock candidates\n", |
| 42 | + "def select_breakout_candidates(csv_path):\n", |
| 43 | + " # Load the dataset\n", |
| 44 | + " stock_data = pd.read_csv(csv_path)\n", |
| 45 | + " \n", |
| 46 | + " # Preprocessing and filtering based on the provided criteria\n", |
| 47 | + " stock_data_filtered = stock_data.dropna(subset=['Target Price', 'P/E'])\n", |
| 48 | + " stock_data_filtered = stock_data_filtered[stock_data_filtered['Price'] < stock_data_filtered['Target Price']]\n", |
| 49 | + " \n", |
| 50 | + " # Calculate additional metrics\n", |
| 51 | + " stock_data_filtered['Price to Target %'] = ((stock_data_filtered['Target Price'] - stock_data_filtered['Price']) / stock_data_filtered['Price']) * 100\n", |
| 52 | + " stock_data_filtered['Change Percentile'] = stock_data_filtered['Change'].rank(pct=True)\n", |
| 53 | + " stock_data_filtered['Volume Percentile'] = stock_data_filtered['Volume'].rank(pct=True)\n", |
| 54 | + " stock_data_filtered['Price to Target Percentile'] = stock_data_filtered['Price to Target %'].rank(pct=True)\n", |
| 55 | + " stock_data_filtered['Composite Score'] = stock_data_filtered[['Change Percentile', 'Volume Percentile', 'Price to Target Percentile']].mean(axis=1)\n", |
| 56 | + " \n", |
| 57 | + " # Exclude overvalued stocks based on P/E ratio threshold\n", |
| 58 | + " pe_threshold = stock_data_filtered['P/E'].quantile(0.80)\n", |
| 59 | + " candidates = stock_data_filtered[stock_data_filtered['P/E'] <= pe_threshold]\n", |
| 60 | + " \n", |
| 61 | + " # Select top candidates based on composite score\n", |
| 62 | + " top_candidates = candidates.sort_values(by='Composite Score', ascending=False).head(8)\n", |
| 63 | + " \n", |
| 64 | + " # Return the selection with relevant information for the article\n", |
| 65 | + " return top_candidates[['Ticker', 'Company', 'Sector', 'Industry', 'Price', 'Volume', 'P/E', 'Target Price', 'Price to Target %', 'Composite Score']]\n", |
| 66 | + "\n", |
| 67 | + "# Usage of the function with the path to the CSV file\n", |
| 68 | + "csv_file_path = 'nifty50_symbols.txt' # Replace with your actual file path\n", |
| 69 | + "selected_stocks = select_breakout_candidates(csv_file_path)\n", |
| 70 | + "\n", |
| 71 | + "# Display the selected stocks\n", |
| 72 | + "selected_stocks" |
| 73 | + ] |
| 74 | + }, |
| 75 | + { |
| 76 | + "cell_type": "markdown", |
| 77 | + "id": "37410db1-243b-4ee7-8b04-e89389d3b0ec", |
| 78 | + "metadata": {}, |
| 79 | + "source": [ |
| 80 | + "## RSI" |
| 81 | + ] |
| 82 | + }, |
| 83 | + { |
| 84 | + "cell_type": "code", |
| 85 | + "execution_count": null, |
| 86 | + "id": "0e7dd783-c120-4588-94bb-3ff8ddc3a575", |
| 87 | + "metadata": {}, |
| 88 | + "outputs": [], |
| 89 | + "source": [ |
| 90 | + "# Import Dependencies\n", |
| 91 | + "import datetime\n", |
| 92 | + "from pandas_datareader import data as pdr\n", |
| 93 | + "import sys\n", |
| 94 | + "import os\n", |
| 95 | + "parent_dir = os.path.dirname(os.getcwd())\n", |
| 96 | + "sys.path.append(parent_dir)\n", |
| 97 | + "import ta_functions as ta\n", |
| 98 | + "import tickers as ti\n", |
| 99 | + "\n", |
| 100 | + "# Get dates for the past year\n", |
| 101 | + "start_date = datetime.datetime.now() - datetime.timedelta(days=365)\n", |
| 102 | + "end_date = datetime.date.today()\n", |
| 103 | + "\n", |
| 104 | + "# Load list of S&P 500 tickers from tickers module\n", |
| 105 | + "tickers = ti.tickers_sp500()\n", |
| 106 | + "\n", |
| 107 | + "# Initialize lists for overbought and oversold tickers\n", |
| 108 | + "oversold_tickers = []\n", |
| 109 | + "overbought_tickers = []\n", |
| 110 | + "\n", |
| 111 | + "# Retrieve adjusted close prices for the tickers\n", |
| 112 | + "sp500_data = pdr.get_data_yahoo(tickers, start_date, end_date)['Adj Close']\n", |
| 113 | + "\n", |
| 114 | + "# Analyze each ticker for RSI\n", |
| 115 | + "for ticker in tickers:\n", |
| 116 | + " try:\n", |
| 117 | + " # Create a new DataFrame for the ticker\n", |
| 118 | + " data = sp500_data[[ticker]].copy()\n", |
| 119 | + "\n", |
| 120 | + " # Calculate the RSI for the ticker\n", |
| 121 | + " data[\"rsi\"] = ta.RSI(data[ticker], timeperiod=14)\n", |
| 122 | + "\n", |
| 123 | + " # Calculate the mean of the last 14 RSI values\n", |
| 124 | + " mean_rsi = data[\"rsi\"].tail(14).mean()\n", |
| 125 | + "\n", |
| 126 | + " # Print the RSI value\n", |
| 127 | + " print(f'{ticker} has an RSI value of {round(mean_rsi, 2)}')\n", |
| 128 | + "\n", |
| 129 | + " # Classify the ticker based on its RSI value\n", |
| 130 | + " if mean_rsi <= 30:\n", |
| 131 | + " oversold_tickers.append(ticker)\n", |
| 132 | + " elif mean_rsi >= 70:\n", |
| 133 | + " overbought_tickers.append(ticker)\n", |
| 134 | + "\n", |
| 135 | + " except Exception as e:\n", |
| 136 | + " print(f'Error processing {ticker}: {e}')\n", |
| 137 | + "\n", |
| 138 | + "# Output the lists of oversold and overbought tickers\n", |
| 139 | + "print(f'Oversold tickers: {oversold_tickers}')\n", |
| 140 | + "print(f'Overbought tickers: {overbought_tickers}')" |
| 141 | + ] |
| 142 | + } |
| 143 | + ], |
| 144 | + "metadata": { |
| 145 | + "kernelspec": { |
| 146 | + "display_name": "Python 3 (ipykernel)", |
| 147 | + "language": "python", |
| 148 | + "name": "python3" |
| 149 | + }, |
| 150 | + "language_info": { |
| 151 | + "codemirror_mode": { |
| 152 | + "name": "ipython", |
| 153 | + "version": 3 |
| 154 | + }, |
| 155 | + "file_extension": ".py", |
| 156 | + "mimetype": "text/x-python", |
| 157 | + "name": "python", |
| 158 | + "nbconvert_exporter": "python", |
| 159 | + "pygments_lexer": "ipython3", |
| 160 | + "version": "3.10.12" |
| 161 | + } |
| 162 | + }, |
| 163 | + "nbformat": 4, |
| 164 | + "nbformat_minor": 5 |
| 165 | +} |
0 commit comments