mokout commited on
Commit
f9020ac
·
verified ·
1 Parent(s): 0b09281

Upload 4 files

Browse files
Files changed (4) hide show
  1. LICENSE +21 -0
  2. README.md +51 -11
  3. app.py +346 -0
  4. requirements.txt +8 -0
LICENSE ADDED
@@ -0,0 +1,21 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Mohn Koushik
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
README.md CHANGED
@@ -1,14 +1,54 @@
 
 
 
 
 
 
 
 
 
 
1
  ---
2
- title: Data-Science Final-Project
3
- emoji: 🌍
4
- colorFrom: purple
5
- colorTo: gray
6
- sdk: streamlit
7
- sdk_version: 1.43.2
8
- app_file: app.py
9
- pinned: false
10
- license: mit
11
- short_description: Final Project for Graduate Data Science Certificate - MIDAS
 
12
  ---
13
 
14
- Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # MIDAS_Final_Project
2
+
3
+ 🚀 **Final Project for Graduate Data Science Certificate**
4
+ *From the Michigan Institute for Data & AI in Society (MIDAS)*
5
+
6
+ ---
7
+
8
+ ## Project Overview
9
+ This repository contains the final project submission for the Graduate Data Science Certificate program at MIDAS. The project showcases data science skills and methodologies learned throughout the program.
10
+
11
  ---
12
+
13
+ ## Project Metadata
14
+ | **Title** | MIDAS_Final_Project |
15
+ |----------------------|-----------------------------------------------|
16
+ | **Emoji** | 🚀 |
17
+ | **Color Gradient** | Purple to Green |
18
+ | **SDK Used** | Streamlit |
19
+ | **SDK Version** | 1.35.0 |
20
+ | **Application File**| `app.py` |
21
+ | **Pinned** | No |
22
+
23
  ---
24
 
25
+ ## How to Run the Project
26
+ 1. Clone this repository:
27
+ git clone https://github.com/your-username/MIDAS_Final_Project.git
28
+
29
+ 2. Navigate to the project directory:
30
+ cd MIDAS_Final_Project
31
+
32
+ text
33
+ 3. Install dependencies:
34
+ pip install -r requirements.txt
35
+
36
+ text
37
+ 4. Run the Streamlit application:
38
+ streamlit run app.py
39
+
40
+ text
41
+
42
+ ---
43
+
44
+ ## Features
45
+ - Interactive visualizations powered by Streamlit.
46
+ - Implementation of advanced data science techniques.
47
+ - User-friendly interface for exploring datasets and models.
48
+
49
+ ---
50
+
51
+ ## Acknowledgments
52
+ This project is part of the Graduate Data Science Certificate program at MIDAS - University of Michigan, which focuses on applying data science to real-world problems.
53
+
54
+ ---
app.py ADDED
@@ -0,0 +1,346 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ import pandas as pd
3
+ import yfinance as yf
4
+ import plotly.graph_objects as go
5
+ import streamlit as st
6
+ from datetime import datetime, timedelta
7
+ from scipy.signal import argrelextrema
8
+ from sklearn.cluster import KMeans
9
+ import matplotlib.pyplot as plt
10
+
11
+ # Streamlit app
12
+ st.set_page_config(page_title="Identifying Key Support and Resistance In Price Levels", layout="wide")
13
+ st.title('Key Support and Resistance In Price Levels')
14
+
15
+ st.markdown("""
16
+ This tool aims to identify key support and resistance price levels in stocks using various algorithmic methods. Each method is detailed below.
17
+ """)
18
+
19
+ with st.expander("Click here to read the description of each method:", expanded=False):
20
+ st.markdown("""
21
+ 1. **Pivot Points**: Short-term trend indicators used to determine potential support and resistance levels based on the high, low, and close prices of previous trading sessions.
22
+ 2. **Support and Resistance Levels using Rolling Midpoint Range**: Key price points where the stock's price tends to halt its upward or downward trajectory, identified using a rolling window to calculate dynamic support and resistance levels.
23
+ 3. **Swing Highs and Lows**: Local maxima and minima used to identify trends and potential reversal points by pinpointing key inflection points on a stock's chart.
24
+ 4. **Fibonacci Retracement Levels**: Horizontal lines indicating potential support and resistance levels based on Fibonacci numbers, helping to identify prospective market reversal points.
25
+ 5. **Trendlines**: Straight lines drawn to connect two or more price points, helping identify the market trend direction and potential areas of support and resistance.
26
+ 6. **Volume Profile**: A charting tool that shows the amount of volume traded at different price levels over a specified period, helping identify areas of high trading activity which can act as support or resistance.
27
+ 7. **KMeans Clustering**: A machine learning algorithm used to partition the dataset into clusters, identifying patterns and grouping similar price movements together to highlight significant price levels.
28
+ """)
29
+
30
+ # Sidebar: How to use and Input Parameters
31
+ st.sidebar.title('Input Parameters')
32
+
33
+ with st.sidebar.expander("How to use:", expanded=False):
34
+ st.markdown("""
35
+ 1. **Enter Ticker**: Specify a stock ticker or crypto pair.
36
+ 2. **Set Dates**: Choose the date range for analysis.
37
+ 3. **Adjust Parameters**: Modify methodology parameters as needed.
38
+ 4. **Run Analysis**: Click 'Run' to generate results.
39
+ """)
40
+
41
+ with st.sidebar.expander("Ticker and Date Settings", expanded=True):
42
+ st.write("Specify the ticker and date range for analysis.")
43
+ ticker = st.text_input('Stock Ticker or Crypto Pair', 'AAPL', help="Enter stock ticker (e.g., AAPL) or crypto pair (e.g., BTC-USD).")
44
+ start_date = st.date_input('Start Date', pd.to_datetime('2023-01-01'))
45
+ end_date = st.date_input('End Date', datetime.now() + timedelta(days=1))
46
+
47
+ with st.sidebar.expander("Pivot Points and Levels", expanded=True):
48
+ window_period = st.slider('Window Period for Pivot Points and Levels', min_value=10, max_value=60, value=30, help="Set the window period for calculating pivot points and support/resistance levels.")
49
+
50
+ with st.sidebar.expander("Trendlines and Fibonacci Levels", expanded=True):
51
+ lookback_period = st.slider('Lookback Period for Trendlines and Fibonacci', min_value=10, max_value=60, value=30, help="Set the lookback period for calculating trendlines and Fibonacci retracement levels.")
52
+
53
+ with st.sidebar.expander("Volume Profile and KMeans", expanded=True):
54
+ n_days = st.slider('Lookback Period for Volume Profile and KMeans (Days)', min_value=30, max_value=365, value=60, help="Set the number of days for calculating volume profile and KMeans clustering.")
55
+ num_clusters = st.slider('Number of Clusters for KMeans', min_value=2, max_value=10, value=3, help="Set the number of clusters for KMeans analysis.")
56
+
57
+ # Define functions for different analyses
58
+ def calculate_pivot_points(df, window):
59
+ # Ensure single-level columns
60
+ if isinstance(df.columns, pd.MultiIndex):
61
+ df.columns = df.columns.get_level_values(0)
62
+
63
+ # Calculate each step explicitly as a Series
64
+ pivot = df['Close'].rolling(window=window).mean()
65
+ low_min = df['Low'].rolling(window=window).min().reindex(df.index, method='ffill')
66
+ high_max = df['High'].rolling(window=window).max().reindex(df.index, method='ffill')
67
+
68
+ df['Pivot'] = pivot
69
+ df['R1'] = pd.Series(2 * pivot - low_min, index=df.index)
70
+ df['S1'] = pd.Series(2 * pivot - high_max, index=df.index)
71
+ df['R2'] = pd.Series(pivot + (high_max - low_min), index=df.index)
72
+ df['S2'] = pd.Series(pivot - (high_max - low_min), index=df.index)
73
+
74
+ return df
75
+
76
+ def find_levels(data, window):
77
+ resistance = data['High'].rolling(window=window).max()
78
+ support = data['Low'].rolling(window=window).min()
79
+ return support, resistance
80
+
81
+ def check_significant_break(data, support, resistance):
82
+ breaks_above_resistance = (data['Close'] > resistance.shift(1)) & (data['Volume'] > data['Volume'].rolling(window=30).mean())
83
+ breaks_below_support = (data['Close'] < support.shift(1)) & (data['Volume'] > data['Volume'].rolling(window=30).mean())
84
+ return breaks_above_resistance, breaks_below_support
85
+
86
+ def prepare_data_for_trendlines(data, lookback_period):
87
+ data['Swing_High'] = data['High'][argrelextrema(data['High'].values, np.greater_equal, order=lookback_period)[0]]
88
+ data['Swing_Low'] = data['Low'][argrelextrema(data['Low'].values, np.less_equal, order=lookback_period)[0]]
89
+ return data
90
+
91
+ def calculate_fibonacci_levels(data, lookback_period):
92
+ high_prices = data["High"].rolling(window=lookback_period).max()
93
+ low_prices = data["Low"].rolling(window=lookback_period).min()
94
+ price_diff = high_prices - low_prices
95
+ levels = np.array([0, 0.236, 0.382, 0.5, 0.618, 0.786, 1])
96
+ fib_levels = low_prices.values.reshape(-1, 1) + price_diff.values.reshape(-1, 1) * levels
97
+ return fib_levels, levels
98
+
99
+ def calculate_volume_profile(data, n_days):
100
+ filtered_data = data[-n_days:]
101
+ price_bins = np.linspace(filtered_data['Low'].min(), filtered_data['High'].max(), 100)
102
+ volume_profile = [filtered_data['Volume'][(filtered_data['Close'] > price_bins[i]) & (filtered_data['Close'] <= price_bins[i+1])].sum() for i in range(len(price_bins)-1)]
103
+ return price_bins, volume_profile
104
+
105
+ def calculate_kmeans_clusters(data, n_days, num_clusters):
106
+ filtered_data = data[-n_days:]
107
+ X_time = np.linspace(0, 1, len(filtered_data)).reshape(-1, 1)
108
+ X_price = (filtered_data['Close'].values - np.min(filtered_data['Close'])) / (np.max(filtered_data['Close']) - np.min(filtered_data['Close']))
109
+ X_cluster = np.column_stack((X_time, X_price))
110
+ kmeans = KMeans(n_clusters=num_clusters)
111
+ kmeans.fit(X_cluster)
112
+ cluster_centers = kmeans.cluster_centers_[:, 1] * (np.max(filtered_data['Close']) - np.min(filtered_data['Close'])) + np.min(filtered_data['Close'])
113
+ return cluster_centers
114
+
115
+ # Run the analysis
116
+ if st.sidebar.button('Run Analysis'):
117
+ # Fetch data with auto_adjust=False and flatten columns if multi-indexed
118
+ data = yf.download(ticker, start=start_date, end=end_date, auto_adjust=False)
119
+ if isinstance(data.columns, pd.MultiIndex):
120
+ data.columns = data.columns.get_level_values(0)
121
+
122
+ if not data.empty:
123
+ # Calculate Pivot Points
124
+ try:
125
+ df_pivot = calculate_pivot_points(data.copy(), window_period)
126
+ df_pivot = df_pivot.dropna()
127
+ except ValueError as e:
128
+ st.error(f"Error in calculate_pivot_points: {e}")
129
+ st.write("DataFrame columns:", data.columns)
130
+ st.write("Sample data:", data.head())
131
+ raise
132
+
133
+ # Calculate Support and Resistance Levels
134
+ support, resistance = find_levels(data.copy(), window_period)
135
+ breaks_above_resistance, breaks_below_support = check_significant_break(data.copy(), support, resistance)
136
+
137
+ # Calculate Swing Highs and Lows
138
+ data_with_trendlines = prepare_data_for_trendlines(data.copy(), lookback_period)
139
+
140
+ # Calculate Fibonacci Retracement Levels
141
+ fib_levels, levels = calculate_fibonacci_levels(data.copy(), lookback_period)
142
+
143
+ # Calculate Volume Profile
144
+ price_bins, volume_profile = calculate_volume_profile(data.copy(), n_days)
145
+
146
+ # Calculate KMeans Clusters
147
+ cluster_centers = calculate_kmeans_clusters(data.copy(), n_days, num_clusters)
148
+
149
+ # Plot Pivot Points
150
+ st.write("### Pivot Points")
151
+ st.markdown("""
152
+ **Pivot Points** are short-term trend indicators used to determine potential support and resistance levels. The central pivot point, as well as derived support and resistance levels, are calculated using the high, low, and close prices of a previous period (usually the previous day for day trading).
153
+ - **Pivot Point (P)**: The average of the high, low, and close of the previous trading period.
154
+ - **First Resistance (R1)**: Calculated by doubling the pivot point and then subtracting the previous low.
155
+ - **First Support (S1)**: Derived by doubling the pivot point and then subtracting the previous high.
156
+ - **Second Resistance (R2)**: Obtained by adding the difference of high and low (the range) to the pivot point.
157
+ - **Second Support (S2)**: Found by subtracting the range from the pivot point.
158
+ """)
159
+
160
+ fig1 = go.Figure()
161
+ fig1.add_trace(go.Scatter(x=df_pivot.index, y=df_pivot['Close'], mode='lines', name='Close Price'))
162
+ fig1.add_trace(go.Scatter(x=df_pivot.index, y=df_pivot['Pivot'], mode='lines', name='Pivot', line=dict(dash='dash', color='black')))
163
+ fig1.add_trace(go.Scatter(x=df_pivot.index, y=df_pivot['R1'], mode='lines', name='Resistance 1', line=dict(dash='dash', color='red')))
164
+ fig1.add_trace(go.Scatter(x=df_pivot.index, y=df_pivot['S1'], mode='lines', name='Support 1', line=dict(dash='dash', color='green')))
165
+ fig1.add_trace(go.Scatter(x=df_pivot.index, y=df_pivot['R2'], mode='lines', name='Resistance 2', line=dict(dash='dash', color='orange')))
166
+ fig1.add_trace(go.Scatter(x=df_pivot.index, y=df_pivot['S2'], mode='lines', name='Support 2', line=dict(dash='dash', color='blue')))
167
+ fig1.update_layout(
168
+ title=f'{ticker} Price with Pivot Points and Support/Resistance Levels',
169
+ xaxis_title='Date',
170
+ yaxis_title='Price',
171
+ legend_title='Legend',
172
+ width=1200,
173
+ height=600
174
+ )
175
+ st.plotly_chart(fig1, use_container_width=True)
176
+
177
+ # Plot Support and Resistance Levels using Rolling Midpoint Range
178
+ st.write("### Rolling Midpoint Range")
179
+ st.markdown("""
180
+ **Support and Resistance Levels** This method uses a rolling window to identify these levels. This provides a dynamic approach to pinpointing key price levels.
181
+ - **Support Level**: Calculated as the rolling minimum price over the specified window period. It acts as a floor where buying interest is strong enough to prevent further price declines.
182
+ - **Resistance Level**: Calculated as the rolling maximum price over the specified window period. It acts as a ceiling where selling interest prevents the price from rising further.
183
+ In this analysis, the support and resistance levels are determined using a rolling window approach. Significant breaks above resistance and below support are highlighted, especially when accompanied by higher-than-average trading volumes, which could indicate potential breakout or breakdown scenarios.
184
+ """)
185
+
186
+ fig2 = go.Figure()
187
+ fig2.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Stock Price'))
188
+ fig2.add_trace(go.Scatter(x=data.index, y=support, mode='lines', name='Support', line=dict(dash='dash', color='green')))
189
+ fig2.add_trace(go.Scatter(x=data.index, y=resistance, mode='lines', name='Resistance', line=dict(dash='dash', color='red')))
190
+ fig2.add_trace(go.Scatter(x=data[breaks_above_resistance].index, y=data['Close'][breaks_above_resistance], mode='markers', name='Break Above Resistance', marker=dict(color='blue')))
191
+ fig2.add_trace(go.Scatter(x=data[breaks_below_support].index, y=data['Close'][breaks_below_support], mode='markers', name='Break Below Support', marker=dict(color='purple')))
192
+ fig2.update_layout(
193
+ title=f'{ticker} Price with Support and Resistance Levels',
194
+ xaxis_title='Date',
195
+ yaxis_title='Price',
196
+ legend_title='Legend',
197
+ width=1200,
198
+ height=600
199
+ )
200
+ st.plotly_chart(fig2, use_container_width=True)
201
+
202
+ # Plot Swing Highs and Lows
203
+ st.write("### Swing Highs and Lows")
204
+ st.markdown("""
205
+ **Swing Highs and Lows** are the highest and lowest points in the price action over a specified period.
206
+ - **Swing High**: A peak where the price is higher than the surrounding prices.
207
+ - **Swing Low**: A trough where the price is lower than the surrounding prices.
208
+ """)
209
+
210
+ fig3 = go.Figure()
211
+ fig3.add_trace(go.Scatter(x=data_with_trendlines.index, y=data_with_trendlines['Close'], mode='lines', name='Close Price'))
212
+ fig3.add_trace(go.Scatter(x=data_with_trendlines.index, y=data_with_trendlines['Swing_High'], mode='markers', name='Swing Highs', marker=dict(color='red')))
213
+ fig3.add_trace(go.Scatter(x=data_with_trendlines.index, y=data_with_trendlines['Swing_Low'], mode='markers', name='Swing Lows', marker=dict(color='green')))
214
+ fig3.update_layout(
215
+ title=f'{ticker} with Swing Highs & Lows',
216
+ xaxis_title='Date',
217
+ yaxis_title='Price',
218
+ legend_title='Legend',
219
+ width=1200,
220
+ height=600
221
+ )
222
+ st.plotly_chart(fig3, use_container_width=True)
223
+
224
+ # Plot Fibonacci Retracement Levels
225
+ st.write("### Fibonacci Retracement Levels")
226
+ st.markdown("""
227
+ **Fibonacci Retracement Levels** are horizontal lines that indicate where support and resistance are likely to occur. They are based on Fibonacci numbers and are used to predict the future movement of asset prices.
228
+ - **Levels**: 23.6%, 38.2%, 50%, 61.8%, and 78.6% represent key points where the price could potentially reverse.
229
+ """)
230
+
231
+ fig4 = go.Figure()
232
+ fig4.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Stock Price'))
233
+ color_list = ['red', 'orange', 'yellow', 'green', 'blue', 'indigo', 'violet']
234
+ for i, (level, color) in enumerate(zip(levels, color_list)):
235
+ fig4.add_trace(go.Scatter(x=data.index, y=fib_levels[:, i], mode='lines', name=f'Fib {level:.3f}', line=dict(color=color)))
236
+ fig4.update_layout(
237
+ title=f'{ticker} with Fibonacci Retracement Levels',
238
+ xaxis_title='Date',
239
+ yaxis_title='Price',
240
+ legend_title='Legend',
241
+ width=1200,
242
+ height=600
243
+ )
244
+ st.plotly_chart(fig4, use_container_width=True)
245
+
246
+ # Plot Trendlines
247
+ st.write("### Trendlines with Regression Analysis")
248
+ st.markdown("""
249
+ **Trendlines** are straight lines drawn on a price chart to connect two or more price points. They help identify the direction of the market trend and potential areas of support and resistance. In this analysis, trendlines are determined using regression analysis to fit the lines through swing highs and lows.
250
+ - **Upper Trendline**: Connects higher highs using linear regression to fit a line through these points. This line acts as a resistance level.
251
+ - **Lower Trendline**: Connects lower lows using linear regression to fit a line through these points. This line acts as a support level.
252
+ 1. **Swing Highs and Lows Identification**: First, local maxima (swing highs) and minima (swing lows) are identified using a specified lookback period.
253
+ 2. **Linear Regression**: A linear regression is then applied to the swing highs to form the upper trendline and to the swing lows to form the lower trendline.
254
+ 3. **Visualization**: The trendlines are plotted along with the stock's closing prices to represent of potential resistance and support levels.
255
+ """)
256
+
257
+ fig5 = go.Figure()
258
+ fig5.add_trace(go.Scatter(x=data_with_trendlines.index, y=data_with_trendlines['Close'], mode='lines', name='Close Price'))
259
+
260
+ swing_highs = data_with_trendlines['Swing_High'].dropna()
261
+ swing_lows = data_with_trendlines['Swing_Low'].dropna()
262
+
263
+ if len(swing_highs) > 1 and len(swing_lows) > 1:
264
+ upper_m, upper_b = np.polyfit(swing_highs.index.map(pd.Timestamp.toordinal), swing_highs.values, 1)
265
+ lower_m, lower_b = np.polyfit(swing_lows.index.map(pd.Timestamp.toordinal), swing_lows.values, 1)
266
+ data_with_trendlines['Upper_Trendline'] = upper_m * data_with_trendlines.index.map(pd.Timestamp.toordinal) + upper_b
267
+ data_with_trendlines['Lower_Trendline'] = lower_m * data_with_trendlines.index.map(pd.Timestamp.toordinal) + lower_b
268
+ fig5.add_trace(go.Scatter(x=data_with_trendlines.index, y=data_with_trendlines['Upper_Trendline'], mode='lines', name='Upper Trendline', line=dict(color='orange')))
269
+ fig5.add_trace(go.Scatter(x=data_with_trendlines.index, y=data_with_trendlines['Lower_Trendline'], mode='lines', name='Lower Trendline', line=dict(color='blue')))
270
+
271
+ fig5.update_layout(
272
+ title=f'{ticker} with Trendlines',
273
+ xaxis_title='Date',
274
+ yaxis_title='Price',
275
+ legend_title='Legend',
276
+ width=1200,
277
+ height=600
278
+ )
279
+ st.plotly_chart(fig5, use_container_width=True)
280
+
281
+ # Plot Volume Profile
282
+ st.write("### Volume Profile")
283
+ st.markdown("""
284
+ **Volume Profile** is a charting tool that shows the amount of volume traded at different price levels over a specified period. It helps identify areas of high trading activity, which can act as support or resistance.
285
+ - **High Volume Areas**: Indicate significant trading activity and can act as strong support or resistance levels.
286
+ """)
287
+
288
+ fig6, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(20, 5), gridspec_kw={'width_ratios': [3, 1]})
289
+ ax1.plot(data['Close'], label="Close Price")
290
+ current_price = data['Close'].iloc[-1]
291
+ support_idx = np.argmax(volume_profile[:np.digitize(current_price, price_bins)])
292
+ resistance_idx = np.argmax(volume_profile[np.digitize(current_price, price_bins):]) + np.digitize(current_price, price_bins)
293
+ support_price = price_bins[support_idx]
294
+ resistance_price = price_bins[resistance_idx]
295
+ ax1.axhline(y=support_price, color='g', linestyle='--', label='Support')
296
+ ax1.axhline(y=resistance_price, color='r', linestyle='--', label='Resistance')
297
+ ax1.annotate(f'Support: {support_price:.2f}',
298
+ xy=(data.index[-1], support_price),
299
+ xytext=(data.index[-1], support_price - 5),
300
+ arrowprops=dict(facecolor='green', arrowstyle='->'),
301
+ color='green', fontsize=12)
302
+ ax1.annotate(f'Resistance: {resistance_price:.2f}',
303
+ xy=(data.index[-1], resistance_price),
304
+ xytext=(data.index[-1], resistance_price + 5),
305
+ arrowprops=dict(facecolor='red', arrowstyle='->'),
306
+ color='red', fontsize=12)
307
+ ax1.legend()
308
+ ax1.set_title(f'{ticker} Price Data')
309
+ ax2.barh(price_bins[:-1], volume_profile, height=(price_bins[1] - price_bins[0]), color='blue', edgecolor='none')
310
+ ax2.set_title('Volume Profile')
311
+ st.pyplot(fig6, use_container_width=True)
312
+
313
+ # Plot KMeans Clusters
314
+ st.write("### KMeans Clusters")
315
+ st.markdown("""
316
+ **KMeans Clustering** is a machine learning algorithm used to partition a dataset into clusters. In the context of stock prices, it helps identify patterns and group similar price movements together.
317
+ - **Clusters**: Represent different regimes or phases in the stock price movements.
318
+ """)
319
+
320
+ fig7 = go.Figure()
321
+ fig7.add_trace(go.Scatter(x=data.index, y=data['Close'], mode='lines', name='Close Price'))
322
+ for center in cluster_centers:
323
+ fig7.add_trace(go.Scatter(x=[data.index[-1]], y=[center], mode='markers+text', name=f'Cluster Center: {center:.2f}', text=[f'{center:.2f}'], textposition='top center'))
324
+ fig7.add_shape(type="line",
325
+ x0=data.index[0], x1=data.index[-1], y0=center, y1=center,
326
+ line=dict(color='Red', dash="dash"))
327
+ fig7.update_layout(
328
+ title=f'{ticker} with KMeans Clustering (Last {n_days} Days)',
329
+ xaxis_title='Date',
330
+ yaxis_title='Price',
331
+ legend_title='Legend',
332
+ width=1200,
333
+ height=600
334
+ )
335
+ st.plotly_chart(fig7, use_container_width=True)
336
+
337
+ else:
338
+ st.write("No data found for the given ticker and date range.")
339
+
340
+ hide_streamlit_style = """
341
+ <style>
342
+ #MainMenu {visibility: hidden;}
343
+ footer {visibility: hidden;}
344
+ </style>
345
+ """
346
+ st.markdown(hide_streamlit_style, unsafe_allow_html=True)
requirements.txt ADDED
@@ -0,0 +1,8 @@
 
 
 
 
 
 
 
 
 
1
+ numpy==1.26.4
2
+ pandas==2.2.2
3
+ yfinance==0.2.54
4
+ plotly==5.14.1
5
+ streamlit==1.36.0
6
+ scipy==1.11.4
7
+ scikit-learn==1.4.1.post1
8
+ matplotlib==3.7.1