Raaniel commited on
Commit
1ccd1a1
β€’
1 Parent(s): 483f601

Upload 2 files

Browse files
Files changed (2) hide show
  1. .streamlit/config.toml +3 -0
  2. app.py +147 -0
.streamlit/config.toml ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ [theme]
2
+ base="dark"
3
+ primaryColor="#32d18b"
app.py ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import pandas as pd
2
+ import yfinance as yf
3
+ import numpy as np
4
+ import plotly.graph_objects as go
5
+ from plotly.subplots import make_subplots
6
+ from sklearn.cluster import AgglomerativeClustering
7
+ import streamlit as st
8
+ import requests
9
+ from streamlit_lottie import st_lottie
10
+
11
+ st.set_page_config(page_title = "Support and resistance levels",
12
+ page_icon = ':πŸ“ˆ:',
13
+ layout = 'wide')
14
+
15
+ st.title('πŸ“ˆ Technical analysis πŸ“‰')
16
+ st.header('Find support and resistance levels for :blue[price action] analysis!')
17
+ st.divider()
18
+
19
+ def load_lottieurl(url: str):
20
+ r = requests.get(url)
21
+ if r.status_code != 200:
22
+ return None
23
+ return r.json()
24
+
25
+ lottie_url__money = "https://assets1.lottiefiles.com/packages/lf20_06a6pf9i.json"
26
+ lottie_money = load_lottieurl(lottie_url__money)
27
+
28
+ st.sidebar.header('Please choose parameters: ')
29
+
30
+ ticker = st.text_input('Select stock to analyse: (Make sure the ticker you search for is supported by Yahoo! Finance).', 'BNB-USD')
31
+
32
+ interval = '1h'
33
+
34
+ num_clusters = st.sidebar.select_slider(
35
+ 'Select a number of clusters',
36
+ options=[i for i in range(1,8)])
37
+
38
+ rolling_wave_length = st.sidebar.select_slider(
39
+ '''Select a length of rolling wave
40
+ (how much data to cluster at one time)''',
41
+ options=[i for i in range(5, 21)])
42
+
43
+ period_num = st.sidebar.select_slider(
44
+ 'Select number of days to display on chart',
45
+ options=[i for i in range(1, 31)])
46
+
47
+ period = '{}d'.format(period_num)
48
+ df = yf.download(ticker, period = period, interval = interval)
49
+ df.index = pd.to_datetime(df.index).strftime("%d-%m-%Y %H:%M")
50
+ df = df.drop(columns = ["Adj Close"])
51
+
52
+ left_column, right_column = st.columns(2)
53
+
54
+ left_column.markdown('<span style="font-size:20px; font-weight:600; letter-spacing:2px;">Preview data:</span>',
55
+ unsafe_allow_html = True)
56
+ left_column.dataframe(df, height = 400)
57
+
58
+ with right_column:
59
+ st_lottie(lottie_money, key="money")
60
+
61
+ #creating function
62
+ def calculate_support_resistance(df, rolling_wave_length, num_clusters):
63
+ date = df.index
64
+ df.reset_index(inplace=True)
65
+
66
+ max_waves_temp = df.High.rolling(rolling_wave_length).max().rename('waves')
67
+ min_waves_temp = df.Low.rolling(rolling_wave_length).min().rename('waves')
68
+
69
+ max_waves = pd.concat([max_waves_temp, pd.Series(np.zeros(len(max_waves_temp)) + 1)], axis=1)
70
+ min_waves = pd.concat([min_waves_temp, pd.Series(np.zeros(len(min_waves_temp)) + -1)], axis=1)
71
+ max_waves.drop_duplicates('waves', inplace=True)
72
+ min_waves.drop_duplicates('waves', inplace=True)
73
+
74
+ waves = pd.concat([max_waves, min_waves]).sort_index()
75
+ waves = waves[waves[0] != waves[0].shift()].dropna()
76
+
77
+ x = np.concatenate((waves.waves.values.reshape(-1, 1),
78
+ (np.zeros(len(waves)) + 1).reshape(-1, 1)), axis=1)
79
+
80
+ cluster = AgglomerativeClustering(n_clusters=num_clusters, linkage='ward')
81
+ cluster.fit_predict(x)
82
+ waves['clusters'] = cluster.labels_
83
+ waves2 = waves.loc[waves.groupby('clusters')['waves'].idxmax()]
84
+ df.index = date
85
+ waves2.waves.drop_duplicates(keep='first', inplace=True)
86
+
87
+ return waves2.reset_index().waves
88
+ support_resistance_levels = calculate_support_resistance(df, rolling_wave_length, num_clusters)
89
+
90
+ #creating a plot
91
+ fig = make_subplots(rows=2, cols=1, shared_xaxes=True,
92
+ vertical_spacing=0.06, subplot_titles=('OHLC', 'Volume'),
93
+ row_width=[0.3, 0.7])
94
+
95
+ fig.add_trace(go.Candlestick(x=df.index,
96
+ open=df['Open'],
97
+ high=df['High'],
98
+ low=df['Low'],
99
+ close=df['Close'], name = "Market data"), row = 1, col = 1)
100
+
101
+ fig.update_xaxes(
102
+ rangeslider_visible = False,
103
+ rangeselector=dict(
104
+ buttons=list([
105
+ dict(count=1, label="1d",
106
+ step="day", stepmode="backward"),
107
+ dict(count=3, label="3d",
108
+ step="day", stepmode="backward"),
109
+ dict(count=7, label="7d",
110
+ step="day", stepmode="backward"),
111
+ dict(count=30, label="30d",
112
+ step="day", stepmode="backward"),
113
+ dict(step="all")])))
114
+
115
+ i = 0
116
+ for level in support_resistance_levels.to_list():
117
+ fig.add_hline(y=level, line_width=1,
118
+ line_dash="dash", row=1, col=1,
119
+ line_color="snow")
120
+ i += 1
121
+
122
+ colors = []
123
+
124
+ for i in range(len(df.Close)):
125
+ if i != 0:
126
+ if df.Close[i] > df.Close[i-1]:
127
+ colors.append('lightgreen')
128
+ else:
129
+ colors.append('lightcoral')
130
+ else:
131
+ colors.append('lightcoral')
132
+
133
+ fig.add_trace(go.Bar(x=df.index, y=df['Volume'], showlegend=False,
134
+ marker=dict(color=colors)), row=2, col=1)
135
+
136
+ fig.update_traces(name= 'Volume', selector=dict(type='bar'))
137
+
138
+ text = f'{ticker} Chart'
139
+
140
+ fig.update_layout(
141
+ title=go.layout.Title(
142
+ text=text,
143
+ xref="paper",
144
+ x=0))
145
+
146
+ #show chart
147
+ st.plotly_chart(fig, use_container_width=True)