riteshcp's picture
Update app.py
687c3b1 verified
Raw
History Blame Contribute Delete
5.6 kB
import streamlit as st
import yfinance as yf
import pandas as pd
import numpy as np
import ta
from datetime import datetime
# Streamlit Title
st.title("NIFTY 500 Turtle Strategy Scanner with Support, Resistance, RSI, and Volume Filters")
# Load the NIFTY 500 stock list
stock_list = pd.read_csv('ind_nifty500list.csv')
stock_list['Symbol'] = stock_list['Symbol'] + ".NS"
nifty_500_stocks = stock_list['Symbol'].tolist()
# Sidebar for Parameters
st.sidebar.header("Turtle Strategy, RSI, and Support/Resistance Parameters")
entry_days = st.sidebar.slider("Entry Lookback Period (days)", min_value=10, max_value=60, value=20, step=1)
exit_days = st.sidebar.slider("Exit Lookback Period (days)", min_value=5, max_value=30, value=10, step=1)
# RSI Thresholds
lower_rsi_threshold = st.sidebar.slider("Lower RSI Threshold (Oversold)", min_value=10, max_value=50, value=30, step=5)
upper_rsi_threshold = st.sidebar.slider("Upper RSI Threshold (Overbought)", min_value=50, max_value=90, value=70, step=5)
# Volume Threshold
volume_threshold = st.sidebar.number_input("Volume Threshold", min_value=100000, value=500000)
# Moving Average Parameters
short_term_ma = st.sidebar.slider("Short-Term Moving Average (days)", min_value=5, max_value=50, value=20, step=1)
long_term_ma = st.sidebar.slider("Long-Term Moving Average (days)", min_value=20, max_value=200, value=50, step=1)
# Support and Resistance Lookback Periods
support_period = st.sidebar.slider("Support Lookback Period (days)", min_value=5, max_value=50, value=20, step=1)
resistance_period = st.sidebar.slider("Resistance Lookback Period (days)", min_value=5, max_value=50, value=20, step=1)
# Option to limit the number of stocks to scan
limit_stocks = st.sidebar.slider("Number of Stocks to Scan", min_value=5, max_value=len(nifty_500_stocks), value=502, step=5)
# Initialize an empty DataFrame to store the filtered stocks
filtered_data = pd.DataFrame(columns=["Stock", "Latest Price", "RSI", "Volume", "Short MA", "Long MA", "Support", "Resistance", "Entry Signal", "Exit Signal"])
# Get today's date for the end date
end_date = datetime.today().strftime('%Y-%m-%d')
# Loop through the selected stocks to scan
st.write(f"Scanning the top {limit_stocks} stocks in NIFTY 500 based on Turtle Strategy, Support/Resistance, RSI, and Volume...")
for symbol in nifty_500_stocks[:limit_stocks]:
try:
# Fetch historical data for the stock up to today's date
data = yf.download(symbol, start='2022-01-01', end=end_date, progress=False)
# Check if the data is sufficient for analysis
if len(data) < long_term_ma:
st.write(f"Skipping {symbol}: Not enough data available.")
continue
# Calculate Turtle Strategy parameters
data['20D_High'] = data['High'].rolling(window=entry_days).max()
data['10D_Low'] = data['Low'].rolling(window=exit_days).min()
# Entry and Exit Signals
data['Long'] = np.where(data['Close'] > data['20D_High'].shift(1), 1, 0)
data['Exit'] = np.where(data['Close'] < data['10D_Low'].shift(1), 1, 0)
# Calculate RSI using 'ta' library
data['RSI'] = ta.momentum.RSIIndicator(data['Close'], window=14).rsi()
# Calculate Moving Averages for confirmation
data['Short_MA'] = ta.trend.SMAIndicator(data['Close'], window=short_term_ma).sma_indicator()
data['Long_MA'] = ta.trend.SMAIndicator(data['Close'], window=long_term_ma).sma_indicator()
# Calculate Support and Resistance Levels
data['Support'] = data['Low'].rolling(window=support_period).min()
data['Resistance'] = data['High'].rolling(window=resistance_period).max()
# Position Management
data['Position'] = 0
data.loc[data['Long'] == 1, 'Position'] = 1
data.loc[data['Exit'] == 1, 'Position'] = 0
data['Position'] = data['Position'].ffill().shift(1).fillna(0)
# Check for the latest entry or exit signal, RSI, Volume, and Support/Resistance
latest_entry = data['Long'].iloc[-1] # Last Long signal (Entry)
latest_exit = data['Exit'].iloc[-1] # Last Exit signal
latest_rsi = data['RSI'].iloc[-1] # Last RSI value
latest_volume = data['Volume'].iloc[-1] # Last Volume
latest_short_ma = data['Short_MA'].iloc[-1] # Latest Short-Term MA
latest_long_ma = data['Long_MA'].iloc[-1] # Latest Long-Term MA
latest_support = data['Support'].iloc[-1] # Latest Support Level
latest_resistance = data['Resistance'].iloc[-1] # Latest Resistance Level
# Filter based on Support/Resistance, RSI, Volume, and Moving Averages
if (latest_entry == 1 or latest_exit == 1) and ((latest_rsi <= lower_rsi_threshold or latest_rsi >= upper_rsi_threshold)) and latest_volume > volume_threshold and latest_short_ma > latest_long_ma:
latest_price = data['Close'].iloc[-1]
filtered_data = pd.concat([filtered_data, pd.DataFrame([[symbol, latest_price, latest_rsi, latest_volume, latest_short_ma, latest_long_ma, latest_support, latest_resistance, latest_entry, latest_exit]], columns=filtered_data.columns)], ignore_index=True)
except Exception as e:
st.write(f"Error processing {symbol}: {e}")
# Display the filtered stocks that meet the criteria
if not filtered_data.empty:
st.subheader(f"Filtered Stocks with Support/Resistance, Moving Average, Custom RSI, and Volume Thresholds:")
st.dataframe(filtered_data)
else:
st.write("No stocks meeting the criteria for entry/exit signals, Support/Resistance, RSI, MA, or volume thresholds.")