Update app.py
Browse files
app.py
CHANGED
@@ -39,70 +39,52 @@ futures_stocks = [
|
|
39 |
"WHIRLPOOL.NS", "WIPRO.NS", "ZEEL.NS"
|
40 |
]
|
41 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
42 |
|
43 |
-
|
44 |
-
def fetch_and_calculate_indicators(ticker, start_date, end_date, rsi_length, stoch_length, k_period, d_period):
|
45 |
-
try:
|
46 |
-
df = yf.download(ticker, start=start_date, end=end_date)
|
47 |
-
|
48 |
-
if df.empty:
|
49 |
-
return None
|
50 |
-
|
51 |
-
# Calculate RSI
|
52 |
-
df['RSI'] = ta.momentum.RSIIndicator(df['Close'], window=rsi_length).rsi()
|
53 |
-
|
54 |
-
# Calculate Stochastic RSI
|
55 |
-
stoch_rsi = ta.momentum.StochRSIIndicator(
|
56 |
-
df['Close'],
|
57 |
-
window=stoch_length,
|
58 |
-
smooth1=k_period,
|
59 |
-
smooth2=d_period
|
60 |
-
)
|
61 |
-
df['StochRSI_K'] = stoch_rsi.stochrsi_k()
|
62 |
-
df['StochRSI_D'] = stoch_rsi.stochrsi_d()
|
63 |
-
|
64 |
-
# Calculate OBV
|
65 |
-
df['OBV'] = ta.volume.OnBalanceVolumeIndicator(df['Close'], df['Volume']).on_balance_volume()
|
66 |
-
|
67 |
-
if df['RSI'].isna().all() or df['StochRSI_K'].isna().all() or df['OBV'].isna().all():
|
68 |
-
return None
|
69 |
-
|
70 |
-
return df
|
71 |
-
except Exception as e:
|
72 |
-
st.error(f"Error occurred for {ticker}: {str(e)}")
|
73 |
-
return None
|
74 |
-
|
75 |
-
def filter_stocks_by_indicators(stocks, start_date, end_date, rsi_threshold, stoch_rsi_threshold, obv_threshold, indicator_choice, rsi_length, stoch_length, k_period, d_period):
|
76 |
-
filtered_stocks = []
|
77 |
-
progress_bar = st.progress(0)
|
78 |
-
for i, ticker in enumerate(stocks):
|
79 |
-
df = fetch_and_calculate_indicators(ticker, start_date, end_date, rsi_length, stoch_length, k_period, d_period)
|
80 |
-
if df is not None and not df['RSI'].empty and not df['StochRSI_K'].empty and not df['OBV'].empty:
|
81 |
-
rsi_value = df['RSI'].iloc[-1]
|
82 |
-
stoch_rsi_value = df['StochRSI_K'].iloc[-1]
|
83 |
-
obv_value = df['OBV'].iloc[-1]
|
84 |
-
obv_change = (df['OBV'].iloc[-1] - df['OBV'].iloc[-2]) / df['OBV'].iloc[-2] * 100 # Percentage change
|
85 |
-
|
86 |
-
if not pd.isna(rsi_value) and not pd.isna(stoch_rsi_value) and not pd.isna(obv_value):
|
87 |
-
if (indicator_choice == 'RSI' and rsi_value < rsi_threshold) or \
|
88 |
-
(indicator_choice == 'StochRSI' and stoch_rsi_value < stoch_rsi_threshold) or \
|
89 |
-
(indicator_choice == 'OBV' and obv_change > obv_threshold) or \
|
90 |
-
(indicator_choice == 'All' and rsi_value < rsi_threshold and stoch_rsi_value < stoch_rsi_threshold and obv_change > obv_threshold):
|
91 |
-
filtered_stocks.append({
|
92 |
-
'Ticker': ticker,
|
93 |
-
'RSI': rsi_value,
|
94 |
-
'StochRSI': stoch_rsi_value,
|
95 |
-
'OBV_Change': obv_change
|
96 |
-
})
|
97 |
-
st.info(f"{ticker} - RSI: {rsi_value:.2f}, StochRSI: {stoch_rsi_value:.2f}, OBV Change: {obv_change:.2f}%")
|
98 |
-
else:
|
99 |
-
st.info(f"{ticker} - RSI: {rsi_value:.2f}, StochRSI: {stoch_rsi_value:.2f}, OBV Change: {obv_change:.2f}% (doesn't meet criteria)")
|
100 |
-
else:
|
101 |
-
st.info(f"{ticker} has NaN value for RSI, StochRSI, or OBV.")
|
102 |
-
else:
|
103 |
-
st.info(f"No valid data available for {ticker}.")
|
104 |
-
progress_bar.progress((i + 1) / len(stocks))
|
105 |
-
return filtered_stocks
|
106 |
|
107 |
def main():
|
108 |
st.title("Indian Stock Market Scanner: RSI, Stochastic RSI, and OBV")
|
@@ -110,22 +92,40 @@ def main():
|
|
110 |
start_date = st.date_input("Start Date", dt.date(2020, 1, 1))
|
111 |
end_date = st.date_input("End Date", dt.date.today())
|
112 |
|
113 |
-
|
114 |
-
|
115 |
-
col1, col2, col3 = st.columns(3)
|
116 |
-
|
117 |
-
with col1:
|
118 |
-
rsi_threshold = st.slider("RSI Threshold", 0, 100, 30)
|
119 |
-
rsi_length = st.number_input("RSI Length", value=14, min_value=1, max_value=100)
|
120 |
|
121 |
-
|
122 |
-
|
123 |
-
|
124 |
-
|
125 |
-
|
126 |
-
|
127 |
-
|
128 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
129 |
|
130 |
output_filename = st.text_input("Enter output filename (with .csv extension):", "filtered_stocks.csv")
|
131 |
|
|
|
39 |
"WHIRLPOOL.NS", "WIPRO.NS", "ZEEL.NS"
|
40 |
]
|
41 |
|
42 |
+
# Predefined setups
|
43 |
+
predefined_setups = {
|
44 |
+
"Custom": None,
|
45 |
+
"Conservative Approach": {
|
46 |
+
"RSI Threshold": 40, "RSI Length": 20, "Stochastic RSI Threshold": 0.30,
|
47 |
+
"Stochastic Length": 20, "OBV Change Threshold": 1.00
|
48 |
+
},
|
49 |
+
"Aggressive Approach": {
|
50 |
+
"RSI Threshold": 25, "RSI Length": 10, "Stochastic RSI Threshold": 0.10,
|
51 |
+
"Stochastic Length": 10, "OBV Change Threshold": 5.00
|
52 |
+
},
|
53 |
+
"Swing Trading Setup": {
|
54 |
+
"RSI Threshold": 30, "RSI Length": 14, "Stochastic RSI Threshold": 0.20,
|
55 |
+
"Stochastic Length": 14, "OBV Change Threshold": 2.00
|
56 |
+
},
|
57 |
+
"Reversal Trading": {
|
58 |
+
"RSI Threshold": 20, "RSI Length": 14, "Stochastic RSI Threshold": 0.15,
|
59 |
+
"Stochastic Length": 14, "OBV Change Threshold": 3.00
|
60 |
+
},
|
61 |
+
"Momentum Trading": {
|
62 |
+
"RSI Threshold": 50, "RSI Length": 9, "Stochastic RSI Threshold": 0.50,
|
63 |
+
"Stochastic Length": 9, "OBV Change Threshold": 4.00
|
64 |
+
},
|
65 |
+
"Day Trading Setup": {
|
66 |
+
"RSI Threshold": 35, "RSI Length": 7, "Stochastic RSI Threshold": 0.25,
|
67 |
+
"Stochastic Length": 7, "OBV Change Threshold": 2.50
|
68 |
+
},
|
69 |
+
"Trend Following Setup": {
|
70 |
+
"RSI Threshold": 50, "RSI Length": 20, "Stochastic RSI Threshold": 0.50,
|
71 |
+
"Stochastic Length": 20, "OBV Change Threshold": 1.50
|
72 |
+
},
|
73 |
+
"Volatility Setup": {
|
74 |
+
"RSI Threshold": 30, "RSI Length": 12, "Stochastic RSI Threshold": 0.35,
|
75 |
+
"Stochastic Length": 12, "OBV Change Threshold": 5.00
|
76 |
+
},
|
77 |
+
"Long-Term Investment Setup": {
|
78 |
+
"RSI Threshold": 60, "RSI Length": 30, "Stochastic RSI Threshold": 0.40,
|
79 |
+
"Stochastic Length": 30, "OBV Change Threshold": 0.50
|
80 |
+
},
|
81 |
+
"Short Squeeze Setup": {
|
82 |
+
"RSI Threshold": 20, "RSI Length": 5, "Stochastic RSI Threshold": 0.10,
|
83 |
+
"Stochastic Length": 5, "OBV Change Threshold": 7.00
|
84 |
+
}
|
85 |
+
}
|
86 |
|
87 |
+
# The fetch_and_calculate_indicators and filter_stocks_by_indicators functions remain unchanged
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
88 |
|
89 |
def main():
|
90 |
st.title("Indian Stock Market Scanner: RSI, Stochastic RSI, and OBV")
|
|
|
92 |
start_date = st.date_input("Start Date", dt.date(2020, 1, 1))
|
93 |
end_date = st.date_input("End Date", dt.date.today())
|
94 |
|
95 |
+
setup_choice = st.selectbox("Choose a predefined setup or customize", list(predefined_setups.keys()))
|
|
|
|
|
|
|
|
|
|
|
|
|
96 |
|
97 |
+
if setup_choice == "Custom":
|
98 |
+
indicator_choice = st.radio("Choose Indicator", ('RSI', 'StochRSI', 'OBV', 'All'))
|
99 |
+
|
100 |
+
col1, col2, col3 = st.columns(3)
|
101 |
+
|
102 |
+
with col1:
|
103 |
+
rsi_threshold = st.slider("RSI Threshold", 0, 100, 30)
|
104 |
+
rsi_length = st.number_input("RSI Length", value=14, min_value=1, max_value=100)
|
105 |
+
|
106 |
+
with col2:
|
107 |
+
stoch_rsi_threshold = st.slider("Stochastic RSI Threshold", 0.0, 1.0, 0.2)
|
108 |
+
stoch_length = st.number_input("Stochastic Length", value=14, min_value=1, max_value=100)
|
109 |
+
|
110 |
+
with col3:
|
111 |
+
obv_threshold = st.slider("OBV Change Threshold (%)", -10.0, 10.0, 2.0)
|
112 |
+
k_period = st.number_input("K Period", value=3, min_value=1, max_value=20)
|
113 |
+
d_period = st.number_input("D Period", value=3, min_value=1, max_value=20)
|
114 |
+
else:
|
115 |
+
setup = predefined_setups[setup_choice]
|
116 |
+
indicator_choice = 'All'
|
117 |
+
rsi_threshold = setup["RSI Threshold"]
|
118 |
+
rsi_length = setup["RSI Length"]
|
119 |
+
stoch_rsi_threshold = setup["Stochastic RSI Threshold"]
|
120 |
+
stoch_length = setup["Stochastic Length"]
|
121 |
+
obv_threshold = setup["OBV Change Threshold"]
|
122 |
+
k_period = 3 # Default value
|
123 |
+
d_period = 3 # Default value
|
124 |
+
|
125 |
+
st.write(f"Selected setup: {setup_choice}")
|
126 |
+
st.write(f"RSI Threshold: {rsi_threshold}, RSI Length: {rsi_length}")
|
127 |
+
st.write(f"Stochastic RSI Threshold: {stoch_rsi_threshold}, Stochastic Length: {stoch_length}")
|
128 |
+
st.write(f"OBV Change Threshold: {obv_threshold}%")
|
129 |
|
130 |
output_filename = st.text_input("Enter output filename (with .csv extension):", "filtered_stocks.csv")
|
131 |
|