import pandas as pd import yfinance as yf import numpy as np import plotly.graph_objects as go from plotly.subplots import make_subplots from sklearn.cluster import AgglomerativeClustering import streamlit as st import requests from streamlit_lottie import st_lottie st.set_page_config(page_title = "Support and resistance levels", page_icon = ':📈:', layout = 'wide') st.title('📈 Technical analysis 📉') st.header('Find support and resistance levels for :blue[price action] analysis!') st.markdown('##') def load_lottieurl(url: str): r = requests.get(url) if r.status_code != 200: return None return r.json() lottie_url__money = "https://assets1.lottiefiles.com/packages/lf20_06a6pf9i.json" lottie_money = load_lottieurl(lottie_url__money) st.sidebar.header('Please choose parameters: ') ticker = st.text_input('Select stock to analyse: (Make sure the ticker you search for is supported by Yahoo! Finance).', 'BNB-USD') interval = '1h' num_clusters = st.sidebar.select_slider( 'Select a number of clusters', options=[i for i in range(1,8)]) rolling_wave_length = st.sidebar.select_slider( '''Select a length of rolling wave (how much data to cluster at one time)''', options=[i for i in range(5, 21)]) period_num = st.sidebar.select_slider( 'Select number of days to display on chart', options=[i for i in range(1, 31)]) period = '{}d'.format(period_num) df = yf.download(ticker, period = period, interval = interval) df.index = pd.to_datetime(df.index).strftime("%d-%m-%Y %H:%M") df = df.drop(columns = ["Adj Close"]) left_column, right_column = st.columns(2) left_column.markdown('Preview data:', unsafe_allow_html = True) left_column.dataframe(df, height = 400) with right_column: st_lottie(lottie_money, key="money") #creating function def calculate_support_resistance(df, rolling_wave_length, num_clusters): date = df.index df.reset_index(inplace=True) max_waves_temp = df.High.rolling(rolling_wave_length).max().rename('waves') min_waves_temp = df.Low.rolling(rolling_wave_length).min().rename('waves') max_waves = pd.concat([max_waves_temp, pd.Series(np.zeros(len(max_waves_temp)) + 1)], axis=1) min_waves = pd.concat([min_waves_temp, pd.Series(np.zeros(len(min_waves_temp)) + -1)], axis=1) max_waves.drop_duplicates('waves', inplace=True) min_waves.drop_duplicates('waves', inplace=True) waves = pd.concat([max_waves, min_waves]).sort_index() waves = waves[waves[0] != waves[0].shift()].dropna() x = np.concatenate((waves.waves.values.reshape(-1, 1), (np.zeros(len(waves)) + 1).reshape(-1, 1)), axis=1) cluster = AgglomerativeClustering(n_clusters=num_clusters, linkage='ward') cluster.fit_predict(x) waves['clusters'] = cluster.labels_ waves2 = waves.loc[waves.groupby('clusters')['waves'].idxmax()] df.index = date waves2.waves.drop_duplicates(keep='first', inplace=True) return waves2.reset_index().waves support_resistance_levels = calculate_support_resistance(df, rolling_wave_length, num_clusters) #creating a plot fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.06, subplot_titles=('OHLC', 'Volume'), row_width=[0.3, 0.7]) fig.add_trace(go.Candlestick(x=df.index, open=df['Open'], high=df['High'], low=df['Low'], close=df['Close'], name = "Market data"), row = 1, col = 1) fig.update_xaxes( rangeslider_visible = False, rangeselector=dict( buttons=list([ dict(count=1, label="1d", step="day", stepmode="backward"), dict(count=3, label="3d", step="day", stepmode="backward"), dict(count=7, label="7d", step="day", stepmode="backward"), dict(count=30, label="30d", step="day", stepmode="backward"), dict(step="all")]))) i = 0 for level in support_resistance_levels.to_list(): fig.add_hline(y=level, line_width=1, line_dash="dash", row=1, col=1, line_color="snow") i += 1 colors = [] for i in range(len(df.Close)): if i != 0: if df.Close[i] > df.Close[i-1]: colors.append('lightgreen') else: colors.append('lightcoral') else: colors.append('lightcoral') fig.add_trace(go.Bar(x=df.index, y=df['Volume'], showlegend=False, marker=dict(color=colors)), row=2, col=1) fig.update_traces(name= 'Volume', selector=dict(type='bar')) text = f'{ticker} Chart' fig.update_layout( title=go.layout.Title( text=text, xref="paper", x=0)) #show chart st.plotly_chart(fig, use_container_width=True)