Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
import numpy as np
|
| 2 |
-
import yfinance as yf
|
| 3 |
import pandas as pd
|
|
|
|
| 4 |
import plotly.graph_objects as go
|
| 5 |
import streamlit as st
|
| 6 |
from datetime import datetime, timedelta
|
|
@@ -9,7 +9,6 @@ from sklearn.cluster import KMeans
|
|
| 9 |
import matplotlib.pyplot as plt
|
| 10 |
|
| 11 |
# Streamlit app
|
| 12 |
-
|
| 13 |
st.set_page_config(page_title="Identifying Key Support and Resistance In Price Levels", layout="wide")
|
| 14 |
st.title('Key Support and Resistance In Price Levels')
|
| 15 |
|
|
@@ -57,11 +56,21 @@ with st.sidebar.expander("Volume Profile and KMeans", expanded=True):
|
|
| 57 |
|
| 58 |
# Define functions for different analyses
|
| 59 |
def calculate_pivot_points(df, window):
|
| 60 |
-
|
| 61 |
-
|
| 62 |
-
|
| 63 |
-
|
| 64 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 65 |
return df
|
| 66 |
|
| 67 |
def find_levels(data, window):
|
|
@@ -74,20 +83,9 @@ def check_significant_break(data, support, resistance):
|
|
| 74 |
breaks_below_support = (data['Close'] < support.shift(1)) & (data['Volume'] > data['Volume'].rolling(window=30).mean())
|
| 75 |
return breaks_above_resistance, breaks_below_support
|
| 76 |
|
| 77 |
-
# Updated function to use positional indexing via .iloc and .values
|
| 78 |
def prepare_data_for_trendlines(data, lookback_period):
|
| 79 |
-
|
| 80 |
-
|
| 81 |
-
|
| 82 |
-
high_positions = argrelextrema(data['High'].values, np.greater_equal, order=lookback_period)[0]
|
| 83 |
-
low_positions = argrelextrema(data['Low'].values, np.less_equal, order=lookback_period)[0]
|
| 84 |
-
|
| 85 |
-
# Use .iloc with .values to ensure scalar assignments
|
| 86 |
-
swing_highs.iloc[high_positions] = data['High'].iloc[high_positions].values
|
| 87 |
-
swing_lows.iloc[low_positions] = data['Low'].iloc[low_positions].values
|
| 88 |
-
|
| 89 |
-
data['Swing_High'] = swing_highs
|
| 90 |
-
data['Swing_Low'] = swing_lows
|
| 91 |
return data
|
| 92 |
|
| 93 |
def calculate_fibonacci_levels(data, lookback_period):
|
|
@@ -116,12 +114,21 @@ def calculate_kmeans_clusters(data, n_days, num_clusters):
|
|
| 116 |
|
| 117 |
# Run the analysis
|
| 118 |
if st.sidebar.button('Run Analysis'):
|
| 119 |
-
data =
|
|
|
|
|
|
|
|
|
|
| 120 |
|
| 121 |
if not data.empty:
|
| 122 |
# Calculate Pivot Points
|
| 123 |
-
|
| 124 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 125 |
|
| 126 |
# Calculate Support and Resistance Levels
|
| 127 |
support, resistance = find_levels(data.copy(), window_period)
|
|
@@ -142,11 +149,11 @@ if st.sidebar.button('Run Analysis'):
|
|
| 142 |
# Plot Pivot Points
|
| 143 |
st.write("### Pivot Points")
|
| 144 |
st.markdown("""
|
| 145 |
-
**Pivot Points** are short-term trend indicators used to determine potential support and resistance levels
|
| 146 |
- **Pivot Point (P)**: The average of the high, low, and close of the previous trading period.
|
| 147 |
- **First Resistance (R1)**: Calculated by doubling the pivot point and then subtracting the previous low.
|
| 148 |
- **First Support (S1)**: Derived by doubling the pivot point and then subtracting the previous high.
|
| 149 |
-
- **Second Resistance (R2)**: Obtained by adding the
|
| 150 |
- **Second Support (S2)**: Found by subtracting the range from the pivot point.
|
| 151 |
""")
|
| 152 |
|
|
@@ -170,7 +177,10 @@ if st.sidebar.button('Run Analysis'):
|
|
| 170 |
# Plot Support and Resistance Levels using Rolling Midpoint Range
|
| 171 |
st.write("### Rolling Midpoint Range")
|
| 172 |
st.markdown("""
|
| 173 |
-
**Support and Resistance Levels**
|
|
|
|
|
|
|
|
|
|
| 174 |
""")
|
| 175 |
|
| 176 |
fig2 = go.Figure()
|
|
@@ -214,7 +224,8 @@ if st.sidebar.button('Run Analysis'):
|
|
| 214 |
# Plot Fibonacci Retracement Levels
|
| 215 |
st.write("### Fibonacci Retracement Levels")
|
| 216 |
st.markdown("""
|
| 217 |
-
**Fibonacci Retracement Levels** are horizontal lines
|
|
|
|
| 218 |
""")
|
| 219 |
|
| 220 |
fig4 = go.Figure()
|
|
@@ -235,7 +246,12 @@ if st.sidebar.button('Run Analysis'):
|
|
| 235 |
# Plot Trendlines
|
| 236 |
st.write("### Trendlines with Regression Analysis")
|
| 237 |
st.markdown("""
|
| 238 |
-
**Trendlines** are
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 239 |
""")
|
| 240 |
|
| 241 |
fig5 = go.Figure()
|
|
@@ -265,7 +281,8 @@ if st.sidebar.button('Run Analysis'):
|
|
| 265 |
# Plot Volume Profile
|
| 266 |
st.write("### Volume Profile")
|
| 267 |
st.markdown("""
|
| 268 |
-
**Volume Profile** is a charting tool that shows the amount of volume traded at different price levels over a specified period.
|
|
|
|
| 269 |
""")
|
| 270 |
|
| 271 |
fig6, (ax1, ax2) = plt.subplots(nrows=1, ncols=2, figsize=(20, 5), gridspec_kw={'width_ratios': [3, 1]})
|
|
@@ -291,12 +308,13 @@ if st.sidebar.button('Run Analysis'):
|
|
| 291 |
ax1.set_title(f'{ticker} Price Data')
|
| 292 |
ax2.barh(price_bins[:-1], volume_profile, height=(price_bins[1] - price_bins[0]), color='blue', edgecolor='none')
|
| 293 |
ax2.set_title('Volume Profile')
|
| 294 |
-
st.pyplot(fig6,
|
| 295 |
|
| 296 |
# Plot KMeans Clusters
|
| 297 |
st.write("### KMeans Clusters")
|
| 298 |
st.markdown("""
|
| 299 |
-
**KMeans Clustering**
|
|
|
|
| 300 |
""")
|
| 301 |
|
| 302 |
fig7 = go.Figure()
|
|
@@ -325,4 +343,4 @@ hide_streamlit_style = """
|
|
| 325 |
footer {visibility: hidden;}
|
| 326 |
</style>
|
| 327 |
"""
|
| 328 |
-
st.markdown(hide_streamlit_style, unsafe_allow_html=True)
|
|
|
|
| 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
|
|
|
|
| 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 |
|
|
|
|
| 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):
|
|
|
|
| 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):
|
|
|
|
| 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)
|
|
|
|
| 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 |
|
|
|
|
| 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()
|
|
|
|
| 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()
|
|
|
|
| 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()
|
|
|
|
| 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]})
|
|
|
|
| 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()
|
|
|
|
| 343 |
footer {visibility: hidden;}
|
| 344 |
</style>
|
| 345 |
"""
|
| 346 |
+
st.markdown(hide_streamlit_style, unsafe_allow_html=True)
|