eshan6704 commited on
Commit
e15bacf
Β·
verified Β·
1 Parent(s): aa42e53

Delete app/yahooinfo2.py

Browse files
Files changed (1) hide show
  1. app/yahooinfo2.py +0 -382
app/yahooinfo2.py DELETED
@@ -1,382 +0,0 @@
1
- # ==============================
2
- # Imports (kept same style)
3
- # ==============================
4
- import yfinance as yf
5
- import pandas as pd
6
- import traceback
7
- import time
8
-
9
- # persist helpers
10
- from .persist import exists, load, save
11
-
12
-
13
- # ==============================
14
- # Yahoo Finance info fetch (RAW)
15
- # ==============================
16
- def yfinfo(symbol):
17
- """
18
- Low-level Yahoo Finance info fetch.
19
- Returns raw dict or {"__error__": "..."}
20
- """
21
- try:
22
- t = yf.Ticker(symbol + ".NS")
23
- info = t.info
24
- if not info or not isinstance(info, dict):
25
- return {}
26
- return info
27
- except Exception as e:
28
- return {"__error__": str(e)}
29
-
30
-
31
- # ==============================
32
- # Icons
33
- # ==============================
34
- SUBGROUP_ICONS = {
35
- "Live Price": "πŸ’Ή",
36
- "Volume": "πŸ“Š",
37
- "Moving Avg": "πŸ“ˆ",
38
- "Range / Vol": "πŸ“‰",
39
- "Bid / Analyst": "πŸ“",
40
- "Other": "ℹ️"
41
- }
42
-
43
- MAIN_ICONS = {
44
- "Price / Volume": "πŸ“ˆ",
45
- "Fundamentals": "πŸ“Š",
46
- "Company Profile": "🏒"
47
- }
48
-
49
-
50
- # ==============================
51
- # Responsive column layout
52
- # ==============================
53
- def column_layout(html, min_width=320):
54
- return f"""
55
- <div style="
56
- display:grid;
57
- grid-template-columns:repeat(auto-fit,minmax({min_width}px,1fr));
58
- gap:10px;
59
- align-items:start;
60
- ">
61
- {html}
62
- </div>
63
- """
64
-
65
-
66
- # ==============================
67
- # Card renderer
68
- # ==============================
69
- def html_card(title, body, mini=False, shade=0):
70
- font = "12px" if mini else "14px"
71
- pad = "6px" if mini else "10px"
72
-
73
- shades = ["#e6f0fa", "#d7e3f5", "#c8d6f0"]
74
- grads = [
75
- "linear-gradient(to right,#1a4f8a,#4a7ac7)",
76
- "linear-gradient(to right,#1f5595,#5584d6)",
77
- "linear-gradient(to right,#205ca0,#6192e0)"
78
- ]
79
-
80
- return f"""
81
- <div style="
82
- background:{shades[shade%3]};
83
- border:1px solid #a3c0e0;
84
- border-radius:8px;
85
- padding:{pad};
86
- font-size:{font};
87
- box-shadow:0 2px 6px rgba(0,0,0,.08);
88
- ">
89
- <div style="
90
- background:{grads[shade%3]};
91
- color:white;
92
- padding:4px 8px;
93
- border-radius:6px;
94
- font-weight:600;
95
- margin-bottom:6px;
96
- ">
97
- {title}
98
- </div>
99
- {body}
100
- </div>
101
- """
102
-
103
-
104
- # ==============================
105
- # Formatting helpers
106
- # ==============================
107
- def format_number(x):
108
- try:
109
- x = float(x)
110
- if abs(x) >= 100:
111
- return f"{x:,.0f}"
112
- if abs(x) >= 1:
113
- return f"{x:,.2f}"
114
- return f"{x:.4f}"
115
- except:
116
- return str(x)
117
-
118
-
119
- # ==============================
120
- # Compact inline key:value view
121
- # ==============================
122
- def make_table(df):
123
- rows = ""
124
- for _, r in df.iterrows():
125
- color = "#0d1f3c"
126
- if any(x in r[0].lower() for x in ["chg", "%"]):
127
- try:
128
- color = "#0a7d32" if float(r[1]) >= 0 else "#b00020"
129
- except:
130
- pass
131
-
132
- rows += f"""
133
- <div style="
134
- display:flex;
135
- justify-content:space-between;
136
- gap:6px;
137
- padding:2px 0;
138
- border-bottom:1px dashed #bcd0ea;
139
- ">
140
- <span style="color:#1a4f8a;font-weight:500;">
141
- {r[0]}
142
- </span>
143
- <span style="
144
- color:{color};
145
- font-weight:600;
146
- background:#f1f6ff;
147
- padding:1px 6px;
148
- border-radius:4px;
149
- ">
150
- {r[1]}
151
- </span>
152
- </div>
153
- """
154
- return f"<div>{rows}</div>"
155
-
156
-
157
- # ==============================
158
- # Noise filtering
159
- # ==============================
160
- NOISE_KEYS = {
161
- "maxAge","priceHint","triggerable",
162
- "customPriceAlertConfidence",
163
- "sourceInterval","exchangeDataDelayedBy",
164
- "esgPopulated"
165
- }
166
-
167
- def is_noise(k):
168
- return k in NOISE_KEYS
169
-
170
-
171
- # ==============================
172
- # Duplicate resolver
173
- # ==============================
174
- DUPLICATE_PRIORITY = {
175
- "price": ["regularMarketPrice","currentPrice"],
176
- "prev": ["regularMarketPreviousClose","previousClose"],
177
- "open": ["regularMarketOpen","open"],
178
- "high": ["regularMarketDayHigh","dayHigh"],
179
- "low": ["regularMarketDayLow","dayLow"],
180
- "volume": ["regularMarketVolume","volume"]
181
- }
182
-
183
- def resolve_duplicates(data):
184
- resolved, used = {}, set()
185
- for keys in DUPLICATE_PRIORITY.values():
186
- for k in keys:
187
- if k in data:
188
- resolved[k] = data[k]
189
- used.update(keys)
190
- break
191
- for k,v in data.items():
192
- if k not in used:
193
- resolved[k] = v
194
- return resolved
195
-
196
-
197
- # ==============================
198
- # Short key names
199
- # ==============================
200
- SHORT_NAMES = {
201
- "regularMarketPrice":"Price",
202
- "regularMarketChange":"Chg",
203
- "regularMarketChangePercent":"Chg%",
204
- "regularMarketPreviousClose":"Prev",
205
- "regularMarketOpen":"Open",
206
- "regularMarketDayHigh":"High",
207
- "regularMarketDayLow":"Low",
208
- "regularMarketVolume":"Vol",
209
- "averageDailyVolume10Day":"AvgV10",
210
- "averageDailyVolume3Month":"AvgV3M",
211
- "fiftyDayAverage":"50DMA",
212
- "twoHundredDayAverage":"200DMA",
213
- "fiftyTwoWeekLow":"52WL",
214
- "fiftyTwoWeekHigh":"52WH",
215
- "beta":"Beta",
216
- "targetMeanPrice":"Target"
217
- }
218
-
219
- def pretty_key(k):
220
- return SHORT_NAMES.get(k, k[:12])
221
-
222
-
223
- # ==============================
224
- # Classifiers
225
- # ==============================
226
- def classify_price_volume_subgroup(key):
227
- k = key.lower()
228
- if "volume" in k: return "Volume"
229
- if "average" in k or "dma" in k: return "Moving Avg"
230
- if "week" in k or "beta" in k: return "Range / Vol"
231
- if "target" in k or "recommend" in k: return "Bid / Analyst"
232
- return "Live Price"
233
-
234
-
235
- def classify_key(key, value):
236
- k = key.lower()
237
- if isinstance(value,(int,float)) and any(x in k for x in [
238
- "price","volume","avg","change","percent","market","week","beta","target"
239
- ]):
240
- return "price_volume"
241
- if any(x in k for x in [
242
- "revenue","income","profit","margin","pe","pb","roe","roa","debt","equity"
243
- ]):
244
- return "fundamental"
245
- if isinstance(value,str) and len(value) > 80:
246
- return "long_text"
247
- return "profile"
248
-
249
-
250
- # ==============================
251
- # Group builder
252
- # ==============================
253
- def build_grouped_info(info):
254
- groups = {
255
- "price_volume":{},
256
- "fundamental":{},
257
- "profile":{},
258
- "long_text":{}
259
- }
260
- for k,v in info.items():
261
- if v in [None,"",[],{}]:
262
- continue
263
- groups[classify_key(k,v)][k] = v
264
- return groups
265
-
266
-
267
- # ==============================
268
- # Column splitter
269
- # ==============================
270
- def split_df_evenly(df):
271
- if df is None or df.empty:
272
- return []
273
-
274
- n = len(df)
275
- cols = 1 if n <= 6 else 2 if n <= 14 else 3
276
- chunk = (n + cols - 1) // cols
277
- return [df.iloc[i:i+chunk] for i in range(0, n, chunk)]
278
-
279
-
280
- # ==============================
281
- # DataFrame builder
282
- # ==============================
283
- def build_df_from_dict(data):
284
- rows = []
285
- for k,v in data.items():
286
- if is_noise(k):
287
- continue
288
- if isinstance(v,(int,float)):
289
- v = format_number(v)
290
- rows.append([pretty_key(k), v])
291
- return pd.DataFrame(rows, columns=["Field","Value"])
292
-
293
-
294
- # ==============================
295
- # MAIN FUNCTION (CACHED)
296
- # ==============================
297
- def fetch_info(symbol):
298
- """
299
- Cached Yahoo Finance info renderer
300
- Cache validity: 1 hour
301
- """
302
- key = f"info_{symbol}"
303
-
304
- # ---------- CACHE CHECK ----------
305
- if exists(key, "html"):
306
- cached = load(key, "html")
307
- if cached:
308
- return cached
309
-
310
- try:
311
- info = yfinfo(symbol)
312
-
313
- # ---------- VALIDATION ----------
314
- if not info or "__error__" in info:
315
- return "No data"
316
-
317
- groups = build_grouped_info(info)
318
- html = ""
319
-
320
- # ---------- PRICE / VOLUME ----------
321
- pv = resolve_duplicates(groups["price_volume"])
322
- sub = {}
323
- for k,v in pv.items():
324
- sg = classify_price_volume_subgroup(k)
325
- sub.setdefault(sg,{})[k] = v
326
-
327
- cards = ""
328
- for i,(t,d) in enumerate(sub.items()):
329
- df = build_df_from_dict(d)
330
- if not df.empty:
331
- cards += html_card(
332
- f"{SUBGROUP_ICONS.get(t,'ℹ️')} {t}",
333
- make_table(df),
334
- mini=True,
335
- shade=i
336
- )
337
-
338
- if cards:
339
- html += html_card(
340
- f"{MAIN_ICONS['Price / Volume']} Price / Volume",
341
- column_layout(cards),
342
- shade=0
343
- )
344
-
345
- # ---------- FUNDAMENTALS ----------
346
- if groups["fundamental"]:
347
- chunks = split_df_evenly(build_df_from_dict(groups["fundamental"]))
348
- cols = "".join(
349
- html_card("πŸ“Š Fundamentals", make_table(c), mini=True, shade=i)
350
- for i,c in enumerate(chunks)
351
- )
352
- html += html_card(
353
- f"{MAIN_ICONS['Fundamentals']} Fundamentals",
354
- column_layout(cols),
355
- shade=1
356
- )
357
-
358
- # ---------- COMPANY PROFILE ----------
359
- if groups["profile"]:
360
- chunks = split_df_evenly(build_df_from_dict(groups["profile"]))
361
- cols = "".join(
362
- html_card("🏒 Profile", make_table(c), mini=True, shade=i)
363
- for i,c in enumerate(chunks)
364
- )
365
- html += html_card(
366
- f"{MAIN_ICONS['Company Profile']} Company Profile",
367
- column_layout(cols),
368
- shade=2
369
- )
370
-
371
- # ---------- LONG TEXT ----------
372
- for k,v in groups["long_text"].items():
373
- html += html_card(pretty_key(k), v, shade=2)
374
-
375
- # ---------- SAVE CACHE ----------
376
- if html.strip():
377
- save(key, html, "html")
378
-
379
- return html
380
-
381
- except Exception:
382
- return f"<pre>{traceback.format_exc()}</pre>"