Geek7 commited on
Commit
86f4dfa
·
verified ·
1 Parent(s): 3745eec

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +210 -14
app.py CHANGED
@@ -1,23 +1,219 @@
1
- import streamlit as st
 
2
  import yfinance as yf
3
- from tradingpatterns import tradingpatterns # Adjust import based on your package structure
4
 
5
- def main():
6
- st.title("Trading Pattern Detection App")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
 
8
- # Sidebar for user input
9
- stock_symbol = st.sidebar.text_input("Enter Stock Symbol", value='AAPL')
10
- period = st.sidebar.selectbox("Select Period", ['1d', '1mo', '3mo', '6mo', '1y'])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- # Download latest available data using yfinance
13
- data = yf.download(stock_symbol, period=period)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
14
 
15
- # Use tradingpatterns module
16
- result = tradingpatterns.hard_data(data)
 
 
 
 
 
 
 
 
 
17
 
18
- # Display the result
19
- st.write("## Result:")
20
- st.write(result)
21
 
22
  if __name__ == "__main__":
23
  main()
 
1
+ import pandas as pd
2
+ import numpy as np
3
  import yfinance as yf
4
+ import streamlit as st
5
 
6
+ # Function to fetch historical stock data using yfinance
7
+ def fetch_stock_data(ticker, start_date, end_date):
8
+ stock_data = yf.download(ticker, start=start_date, end=end_date)
9
+ return stock_data
10
+
11
+ # Function to detect head and shoulder patterns
12
+ def detect_head_shoulder(df, window=3):
13
+ roll_window = window
14
+ df['high_roll_max'] = df['High'].rolling(window=roll_window).max()
15
+ df['low_roll_min'] = df['Low'].rolling(window=roll_window).min()
16
+ mask_head_shoulder = (
17
+ (df['high_roll_max'] > df['High'].shift(1)) &
18
+ (df['high_roll_max'] > df['High'].shift(-1)) &
19
+ (df['High'] < df['High'].shift(1)) &
20
+ (df['High'] < df['High'].shift(-1))
21
+ )
22
+ mask_inv_head_shoulder = (
23
+ (df['low_roll_min'] < df['Low'].shift(1)) &
24
+ (df['low_roll_min'] < df['Low'].shift(-1)) &
25
+ (df['Low'] > df['Low'].shift(1)) &
26
+ (df['Low'] > df['Low'].shift(-1))
27
+ )
28
+ df['head_shoulder_pattern'] = np.nan
29
+ df.loc[mask_head_shoulder, 'head_shoulder_pattern'] = 'Head and Shoulder'
30
+ df.loc[mask_inv_head_shoulder, 'head_shoulder_pattern'] = 'Inverse Head and Shoulder'
31
+ return df
32
+
33
+ # Function to detect multiple tops and bottoms
34
+ def detect_multiple_tops_bottoms(df, window=3):
35
+ roll_window = window
36
+ df['high_roll_max'] = df['High'].rolling(window=roll_window).max()
37
+ df['low_roll_min'] = df['Low'].rolling(window=roll_window).min()
38
+ df['close_roll_max'] = df['Close'].rolling(window=roll_window).max()
39
+ df['close_roll_min'] = df['Close'].rolling(window=roll_window).min()
40
+ mask_top = (df['high_roll_max'] >= df['High'].shift(1)) & (df['close_roll_max'] < df['Close'].shift(1))
41
+ mask_bottom = (df['low_roll_min'] <= df['Low'].shift(1)) & (df['close_roll_min'] > df['Close'].shift(1))
42
+ df['multiple_top_bottom_pattern'] = np.nan
43
+ df.loc[mask_top, 'multiple_top_bottom_pattern'] = 'Multiple Top'
44
+ df.loc[mask_bottom, 'multiple_top_bottom_pattern'] = 'Multiple Bottom'
45
+ return df
46
+
47
+ # Function to calculate support and resistance levels
48
+ def calculate_support_resistance(df, window=3):
49
+ roll_window = window
50
+ std_dev = 2
51
+ df['high_roll_max'] = df['High'].rolling(window=roll_window).max()
52
+ df['low_roll_min'] = df['Low'].rolling(window=roll_window).min()
53
+ mean_high = df['High'].rolling(window=roll_window).mean()
54
+ std_high = df['High'].rolling(window=roll_window).std()
55
+ mean_low = df['Low'].rolling(window=roll_window).mean()
56
+ std_low = df['Low'].rolling(window=roll_window).std()
57
+ df['support'] = mean_low - std_dev * std_low
58
+ df['resistance'] = mean_high + std_dev * std_high
59
+ return df
60
+
61
+ # Function to detect triangle patterns
62
+ def detect_triangle_pattern(df, window=3):
63
+ roll_window = window
64
+ df['high_roll_max'] = df['High'].rolling(window=roll_window).max()
65
+ df['low_roll_min'] = df['Low'].rolling(window=roll_window).min()
66
+ mask_asc = (
67
+ (df['high_roll_max'] >= df['High'].shift(1)) &
68
+ (df['low_roll_min'] <= df['Low'].shift(1)) &
69
+ (df['Close'] > df['Close'].shift(1))
70
+ )
71
+ mask_desc = (
72
+ (df['high_roll_max'] <= df['High'].shift(1)) &
73
+ (df['low_roll_min'] >= df['Low'].shift(1)) &
74
+ (df['Close'] < df['Close'].shift(1))
75
+ )
76
+ df['triangle_pattern'] = np.nan
77
+ df.loc[mask_asc, 'triangle_pattern'] = 'Ascending Triangle'
78
+ df.loc[mask_desc, 'triangle_pattern'] = 'Descending Triangle'
79
+ return df
80
+
81
+ # Function to detect wedge patterns
82
+ def detect_wedge(df, window=3):
83
+ roll_window = window
84
+ df['high_roll_max'] = df['High'].rolling(window=roll_window).max()
85
+ df['low_roll_min'] = df['Low'].rolling(window=roll_window).min()
86
+ df['trend_high'] = df['High'].rolling(window=roll_window).apply(lambda x: 1 if (x[-1]-x[0]) > 0 else -1 if (x[-1]-x[0]) < 0 else 0)
87
+ df['trend_low'] = df['Low'].rolling(window=roll_window).apply(lambda x: 1 if (x[-1]-x[0]) > 0 else -1 if (x[-1]-x[0]) < 0 else 0)
88
+ mask_wedge_up = (
89
+ (df['high_roll_max'] >= df['High'].shift(1)) &
90
+ (df['low_roll_min'] <= df['Low'].shift(1)) &
91
+ (df['trend_high'] == 1) &
92
+ (df['trend_low'] == 1)
93
+ )
94
+ mask_wedge_down = (
95
+ (df['high_roll_max'] <= df['High'].shift(1)) &
96
+ (df['low_roll_min'] >= df['Low'].shift(1)) &
97
+ (df['trend_high'] == -1) &
98
+ (df['trend_low'] == -1)
99
+ )
100
+ df['wedge_pattern'] = np.nan
101
+ df.loc[mask_wedge_up, 'wedge_pattern'] = 'Wedge Up'
102
+ df.loc[mask_wedge_down, 'wedge_pattern'] = 'Wedge Down'
103
+ return df
104
 
105
+ # Function to detect channel patterns
106
+ def detect_channel(df, window=3):
107
+ roll_window = window
108
+ channel_range = 0.1
109
+ df['high_roll_max'] = df['High'].rolling(window=roll_window).max()
110
+ df['low_roll_min'] = df['Low'].rolling(window=roll_window).min()
111
+ df['trend_high'] = df['High'].rolling(window=roll_window).apply(lambda x: 1 if (x[-1]-x[0]) > 0 else -1 if (x[-1]-x[0]) < 0 else 0)
112
+ df['trend_low'] = df['Low'].rolling(window=roll_window).apply(lambda x: 1 if (x[-1]-x[0]) > 0 else -1 if (x[-1]-x[0]) <0 else 0)
113
+ mask_channel_up = (
114
+ (df['high_roll_max'] >= df['High'].shift(1)) &
115
+ (df['low_roll_min'] <= df['Low'].shift(1)) &
116
+ (df['high_roll_max'] - df['low_roll_min'] <= channel_range * (df['high_roll_max'] + df['low_roll_min'])/2) &
117
+ (df['trend_high'] == 1) &
118
+ (df['trend_low'] == 1)
119
+ )
120
+ mask_channel_down = (
121
+ (df['high_roll_max'] <= df['High'].shift(1)) &
122
+ (df['low_roll_min'] >= df['Low'].shift(1)) &
123
+ (df['high_roll_max'] - df['low_roll_min'] <= channel_range * (df['high_roll_max'] + df['low_roll_min'])/2) &
124
+ (df['trend_high'] == -1) &
125
+ (df['trend_low'] == -1)
126
+ )
127
+ df['channel_pattern'] = np.nan
128
+ df.loc[mask_channel_up, 'channel_pattern'] = 'Channel Up'
129
+ df.loc[mask_channel_down, 'channel_pattern'] = 'Channel Down'
130
+ return df
131
 
132
+ # Function to detect double top and bottom patterns
133
+ def detect_double_top_bottom(df, window=3, threshold=0.05):
134
+ roll_window = window
135
+ range_threshold = threshold
136
+ df['high_roll_max'] = df['High'].rolling(window=roll_window).max()
137
+ df['low_roll_min'] = df['Low'].rolling(window=roll_window).min()
138
+ mask_double_top = (
139
+ (df['high_roll_max'] >= df['High'].shift(1)) &
140
+ (df['high_roll_max'] >= df['High'].shift(-1)) &
141
+ (df['High'] < df['High'].shift(1)) &
142
+ (df['High'] < df['High'].shift(-1)) &
143
+ ((df['High'].shift(1) - df['Low'].shift(1)) <= range_threshold * (df['High'].shift(1) + df['Low'].shift(1))/2) &
144
+ ((df['High'].shift(-1) - df['Low'].shift(-1)) <= range_threshold * (df['High'].shift(-1) + df['Low'].shift(-1))/2)
145
+ )
146
+ mask_double_bottom = (
147
+ (df['low_roll_min'] <= df['Low'].shift(1)) &
148
+ (df['low_roll_min'] <= df['Low'].shift(-1)) &
149
+ (df['Low'] > df['Low'].shift(1)) &
150
+ (df['Low'] > df['Low'].shift(-1)) &
151
+ ((df['High'].shift(1) - df['Low'].shift(1)) <= range_threshold * (df['High'].shift(1) + df['Low'].shift(1))/2) &
152
+ ((df['High'].shift(-1) - df['Low'].shift(-1)) <= range_threshold * (df['High'].shift(-1) + df['Low'].shift(-1))/2)
153
+ )
154
+ df['double_pattern'] = np.nan
155
+ df.loc[mask_double_top, 'double_pattern'] = 'Double Top'
156
+ df.loc[mask_double_bottom, 'double_pattern'] = 'Double Bottom'
157
+ return df
158
+
159
+ # Function to detect trendlines
160
+ def detect_trendline(df, window=2):
161
+ roll_window = window
162
+ df['slope'] = np.nan
163
+ df['intercept'] = np.nan
164
+
165
+ for i in range(window, len(df)):
166
+ x = np.array(range(i-window, i))
167
+ y = df['Close'][i-window:i]
168
+ A = np.vstack([x, np.ones(len(x))]).T
169
+ m, c = np.linalg.lstsq(A, y, rcond=None)[0]
170
+ df.at[df.index[i], 'slope'] = m
171
+ df.at[df.index[i], 'intercept'] = c
172
+
173
+ mask_support = df['slope'] > 0
174
+ mask_resistance = df['slope'] < 0
175
+ df['support'] = np.nan
176
+ df['resistance'] = np.nan
177
+ df.loc[mask_support, 'support'] = df['Close'] * df['slope'] + df['intercept']
178
+ df.loc[mask_resistance, 'resistance'] = df['Close'] * df['slope'] + df['intercept']
179
+
180
+ return df
181
+
182
+ # Function to find pivots
183
+ def find_pivots(df):
184
+ high_diffs = df['High'].diff()
185
+ low_diffs = df['Low'].diff()
186
+ higher_high_mask = (high_diffs > 0) & (high_diffs.shift(-1) < 0)
187
+ lower_low_mask = (low_diffs < 0) & (low_diffs.shift(-1) > 0)
188
+ lower_high_mask = (high_diffs < 0) & (high_diffs.shift(-1) > 0)
189
+ higher_low_mask = (low_diffs > 0) & (low_diffs.shift(-1) < 0)
190
+ df['signal'] = ''
191
+ df.loc[higher_high_mask, 'signal'] = 'HH'
192
+ df.loc[lower_low_mask, 'signal'] = 'LL'
193
+ df.loc[lower_high_mask, 'signal'] = 'LH'
194
+ df.loc[higher_low_mask, 'signal'] = 'HL'
195
+ return df
196
+
197
+ # Streamlit App
198
+ def main():
199
+ st.title('Stock Pattern Detection App')
200
+ ticker = st.text_input('Enter Stock Ticker:', 'AAPL')
201
+ start_date = st.date_input('Start Date', pd.to_datetime('2020-01-01'))
202
+ end_date = st.date_input('End Date', pd.to_datetime('2022-01-01'))
203
 
204
+ if st.button('Detect Patterns'):
205
+ stock_data = fetch_stock_data(ticker, start_date, end_date)
206
+ stock_data = detect_head_shoulder(stock_data)
207
+ stock_data = detect_multiple_tops_bottoms(stock_data)
208
+ stock_data = calculate_support_resistance(stock_data)
209
+ stock_data = detect_triangle_pattern(stock_data)
210
+ stock_data = detect_wedge(stock_data)
211
+ stock_data = detect_channel(stock_data)
212
+ stock_data = detect_double_top_bottom(stock_data)
213
+ stock_data = detect_trendline(stock_data)
214
+ stock_data = find_pivots(stock_data)
215
 
216
+ st.write(stock_data)
 
 
217
 
218
  if __name__ == "__main__":
219
  main()