Trebor1009 commited on
Commit
d64071a
·
verified ·
1 Parent(s): 14d7914

Update src/streamlit_app.py

Browse files
Files changed (1) hide show
  1. src/streamlit_app.py +125 -1
src/streamlit_app.py CHANGED
@@ -143,7 +143,131 @@ def render_whale_monitor():
143
  render_premarket_scan()
144
 
145
 
146
- # --- Premarket scan section unchanged, omitted here for brevity ---
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
 
149
  def render_whale_single_ticker():
 
143
  render_premarket_scan()
144
 
145
 
146
+ @st.cache_data(ttl=24 * 3600, show_spinner="Loading curated ticker list...")
147
+ def get_clean_premarket_universe():
148
+ try:
149
+ local_path = hf_hub_download(
150
+ repo_id="Trebor1009/clean-premarket-data", repo_type="dataset",
151
+ filename="clean_premarket_data.csv", token=HF_TOKEN,
152
+ )
153
+ df = pd.read_csv(local_path, usecols=["Ticker"])
154
+ return sorted(df["Ticker"].dropna().unique().tolist())
155
+ except Exception as e:
156
+ st.warning(f"Could not load curated ticker list from Trebor1009/clean-premarket-data: {e}")
157
+ return []
158
+
159
+
160
+ @st.cache_data(ttl=3600, show_spinner="Fetching prior-close reference prices...")
161
+ def get_daily_reference_data(tickers_tuple):
162
+ ref = {}
163
+ batch_size = 10
164
+ total_batches = max(1, (len(tickers_tuple) + batch_size - 1) // batch_size)
165
+ progress = st.progress(0, text="Fetching reference prices...")
166
+ today_date = pd.Timestamp.now(tz="America/New_York").normalize().tz_localize(None)
167
+
168
+ for b, i in enumerate(range(0, len(tickers_tuple), batch_size)):
169
+ batch = tickers_tuple[i:i + batch_size]
170
+ try:
171
+ data = yf.download(list(batch), period="1mo", interval="1d", group_by="ticker",
172
+ progress=False, threads=True)
173
+ except Exception:
174
+ progress.progress((b + 1) / total_batches)
175
+ continue
176
+
177
+ for ticker in batch:
178
+ try:
179
+ try:
180
+ raw = data[ticker]
181
+ except Exception:
182
+ raw = data
183
+ closes = raw["Close"].dropna()
184
+ vol = raw["Volume"].dropna()
185
+ if closes.empty:
186
+ continue
187
+ idx = closes.index.tz_localize(None) if closes.index.tz is not None else closes.index
188
+ prior = closes[idx.normalize() < today_date]
189
+ if not prior.empty:
190
+ prev_close = float(prior.iloc[-1])
191
+ elif len(closes) >= 2:
192
+ prev_close = float(closes.iloc[-2])
193
+ else:
194
+ prev_close = float(closes.iloc[-1])
195
+ avg_vol = float(vol.mean()) if len(vol) >= 5 else None
196
+ ref[ticker] = {"prev_close": prev_close, "avg_vol": avg_vol}
197
+ except Exception:
198
+ continue
199
+
200
+ progress.progress((b + 1) / total_batches, text=f"Reference data: batch {b + 1}/{total_batches}...")
201
+
202
+ progress.empty()
203
+ return ref
204
+
205
+
206
+ @st.cache_data(ttl=300, show_spinner=False)
207
+ def run_premarket_scan(tickers_tuple, min_gap_pct, direction):
208
+ ref_data = get_daily_reference_data(tickers_tuple)
209
+ results = []
210
+ batch_size = 10
211
+ total_batches = max(1, (len(tickers_tuple) + batch_size - 1) // batch_size)
212
+ progress = st.progress(0, text="Scanning premarket activity...")
213
+
214
+ for b, i in enumerate(range(0, len(tickers_tuple), batch_size)):
215
+ batch = tickers_tuple[i:i + batch_size]
216
+ try:
217
+ data = yf.download(list(batch), period="1d", interval="1m", prepost=True,
218
+ group_by="ticker", progress=False, threads=True)
219
+ except Exception:
220
+ progress.progress((b + 1) / total_batches, text=f"Batch {b + 1}/{total_batches} failed, continuing...")
221
+ continue
222
+
223
+ for ticker in batch:
224
+ try:
225
+ try:
226
+ raw = data[ticker]
227
+ except Exception:
228
+ raw = data
229
+ df = raw.dropna(subset=["Close"])
230
+ if df.empty:
231
+ continue
232
+ if df.index.tz is not None:
233
+ df = df.copy()
234
+ df.index = df.index.tz_convert("America/New_York")
235
+ else:
236
+ df = df.copy()
237
+ df.index = df.index.tz_localize("America/New_York")
238
+ premarket = df[df.index.time < dt_time(9, 30)]
239
+ if premarket.empty:
240
+ continue
241
+ ref = ref_data.get(ticker)
242
+ if not ref or not ref.get("prev_close"):
243
+ continue
244
+ prev_close = ref["prev_close"]
245
+ last_price = float(premarket["Close"].iloc[-1])
246
+ if not prev_close:
247
+ continue
248
+ gap_pct = (last_price - prev_close) / prev_close * 100
249
+ if abs(gap_pct) < min_gap_pct:
250
+ continue
251
+ if direction == "Up only" and gap_pct <= 0:
252
+ continue
253
+ if direction == "Down only" and gap_pct >= 0:
254
+ continue
255
+ pm_volume = int(premarket["Volume"].sum())
256
+ results.append({
257
+ "Ticker": ticker,
258
+ "Prev Close": round(prev_close, 2),
259
+ "Premarket Price": round(last_price, 2),
260
+ "Gap %": round(gap_pct, 2),
261
+ "Premarket Volume": pm_volume,
262
+ "Avg Daily Vol": int(ref["avg_vol"]) if ref.get("avg_vol") else None,
263
+ })
264
+ except Exception:
265
+ continue
266
+
267
+ progress.progress((b + 1) / total_batches, text=f"Scanned batch {b + 1}/{total_batches}...")
268
+
269
+ progress.empty()
270
+ return pd.DataFrame(results)
271
 
272
 
273
  def render_whale_single_ticker():