Update stock.py
Browse files
stock.py
CHANGED
|
@@ -73,65 +73,69 @@ def wrap_html(content, title="Market Data"):
|
|
| 73 |
|
| 74 |
def make_table(df: pd.DataFrame):
|
| 75 |
return df.to_html(index=False)
|
|
|
|
|
|
|
|
|
|
| 76 |
|
|
|
|
|
|
|
| 77 |
|
|
|
|
| 78 |
def fetch_intraday(symbol, indicators=None):
|
| 79 |
key = f"intraday_{symbol}"
|
| 80 |
-
|
| 81 |
if exists(key, "html"):
|
| 82 |
-
|
| 83 |
-
if
|
| 84 |
-
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Using cached
|
| 85 |
-
return
|
| 86 |
|
| 87 |
try:
|
| 88 |
-
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Fetching intraday data for {symbol}")
|
| 89 |
df = intraday(symbol)
|
| 90 |
-
if df is None or df.empty:
|
| 91 |
return wrap_html(f"<h1>No intraday data for {symbol}</h1>")
|
| 92 |
|
| 93 |
if isinstance(df.columns, pd.MultiIndex):
|
| 94 |
df.columns = df.columns.get_level_values(0)
|
| 95 |
|
| 96 |
-
|
| 97 |
-
|
| 98 |
|
| 99 |
-
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
-
|
|
|
|
| 102 |
except Exception as e:
|
| 103 |
-
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error
|
| 104 |
return wrap_html(f"<h1>Error: {e}</h1>")
|
| 105 |
|
| 106 |
-
|
| 107 |
-
#
|
| 108 |
-
# ==============================
|
| 109 |
def fetch_daily(symbol):
|
| 110 |
key = f"daily_{symbol}"
|
| 111 |
-
|
| 112 |
if exists(key, "html"):
|
| 113 |
-
|
| 114 |
-
if
|
| 115 |
-
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Using cached
|
| 116 |
-
return
|
| 117 |
|
| 118 |
try:
|
| 119 |
-
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Fetching daily data for {symbol}")
|
| 120 |
df = daily(symbol)
|
| 121 |
-
if df is None or df.empty:
|
| 122 |
return wrap_html(f"<h1>No daily data for {symbol}</h1>")
|
| 123 |
|
| 124 |
-
|
| 125 |
-
df.columns = df.columns.get_level_values(0)
|
| 126 |
|
| 127 |
-
|
| 128 |
-
|
|
|
|
| 129 |
|
| 130 |
-
save(key,
|
| 131 |
-
|
| 132 |
-
return daily_html
|
| 133 |
except Exception as e:
|
| 134 |
-
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error
|
| 135 |
return wrap_html(f"<h1>Error: {e}</h1>")
|
| 136 |
|
| 137 |
|
|
@@ -149,18 +153,15 @@ def fetch_qresult(symbol):
|
|
| 149 |
if df.empty:
|
| 150 |
return wrap_html(f"<h1>No quarterly results for {symbol}</h1>")
|
| 151 |
|
| 152 |
-
# Optional upload
|
| 153 |
upload_file("eshanhf", f"qresult/{symbol}.csv", df)
|
| 154 |
|
| 155 |
-
|
| 156 |
-
|
| 157 |
-
|
| 158 |
-
|
| 159 |
-
df_fmt.index = [str(i.date()) if hasattr(i, "date") else str(i) for i in df_fmt.index]
|
| 160 |
|
| 161 |
-
html = wrap_html(make_table(
|
| 162 |
save(key, html, "html")
|
| 163 |
-
|
| 164 |
return html
|
| 165 |
except Exception as e:
|
| 166 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_qresult: {e}")
|
|
@@ -183,14 +184,13 @@ def fetch_result(symbol):
|
|
| 183 |
|
| 184 |
upload_file("eshanhf", f"result/{symbol}.csv", df)
|
| 185 |
|
| 186 |
-
|
| 187 |
-
for col in
|
| 188 |
-
|
| 189 |
-
|
| 190 |
|
| 191 |
-
html = wrap_html(make_table(
|
| 192 |
save(key, html, "html")
|
| 193 |
-
|
| 194 |
return html
|
| 195 |
except Exception as e:
|
| 196 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_result: {e}")
|
|
@@ -213,14 +213,13 @@ def fetch_balance(symbol):
|
|
| 213 |
|
| 214 |
upload_file("eshanhf", f"balance/{symbol}.csv", df)
|
| 215 |
|
| 216 |
-
|
| 217 |
-
for col in
|
| 218 |
-
|
| 219 |
-
|
| 220 |
|
| 221 |
-
html = wrap_html(make_table(
|
| 222 |
save(key, html, "html")
|
| 223 |
-
|
| 224 |
return html
|
| 225 |
except Exception as e:
|
| 226 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_balance: {e}")
|
|
@@ -243,14 +242,13 @@ def fetch_cashflow(symbol):
|
|
| 243 |
|
| 244 |
upload_file("eshanhf", f"cashflow/{symbol}.csv", df)
|
| 245 |
|
| 246 |
-
|
| 247 |
-
for col in
|
| 248 |
-
|
| 249 |
-
|
| 250 |
|
| 251 |
-
html = wrap_html(make_table(
|
| 252 |
save(key, html, "html")
|
| 253 |
-
|
| 254 |
return html
|
| 255 |
except Exception as e:
|
| 256 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_cashflow: {e}")
|
|
@@ -271,14 +269,13 @@ def fetch_dividend(symbol):
|
|
| 271 |
if df.empty:
|
| 272 |
return wrap_html(f"<h1>No dividend history for {symbol}</h1>")
|
| 273 |
|
| 274 |
-
|
| 275 |
-
for col in
|
| 276 |
-
|
| 277 |
-
|
| 278 |
|
| 279 |
-
html = wrap_html(make_table(
|
| 280 |
save(key, html, "html")
|
| 281 |
-
|
| 282 |
return html
|
| 283 |
except Exception as e:
|
| 284 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_dividend: {e}")
|
|
@@ -299,14 +296,13 @@ def fetch_split(symbol):
|
|
| 299 |
if df.empty:
|
| 300 |
return wrap_html(f"<h1>No splits for {symbol}</h1>")
|
| 301 |
|
| 302 |
-
|
| 303 |
-
for col in
|
| 304 |
-
|
| 305 |
-
|
| 306 |
|
| 307 |
-
html = wrap_html(make_table(
|
| 308 |
save(key, html, "html")
|
| 309 |
-
|
| 310 |
return html
|
| 311 |
except Exception as e:
|
| 312 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_split: {e}")
|
|
@@ -328,15 +324,14 @@ def fetch_other(symbol):
|
|
| 328 |
if df.empty:
|
| 329 |
return wrap_html(f"<h1>No earnings data for {symbol}</h1>")
|
| 330 |
|
| 331 |
-
|
| 332 |
-
for col in
|
| 333 |
-
|
|
|
|
| 334 |
|
| 335 |
-
html = wrap_html(make_table(
|
| 336 |
save(key, html, "html")
|
| 337 |
-
|
| 338 |
return html
|
| 339 |
except Exception as e:
|
| 340 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_other: {e}")
|
| 341 |
return wrap_html(html_error(f"Earnings Error: {e}"))
|
| 342 |
-
|
|
|
|
| 73 |
|
| 74 |
def make_table(df: pd.DataFrame):
|
| 75 |
return df.to_html(index=False)
|
| 76 |
+
from datetime import datetime
|
| 77 |
+
import pandas as pd
|
| 78 |
+
import yfinance as yf
|
| 79 |
|
| 80 |
+
# Assumes save, load, exists, upload_file, wrap_html, make_table, intraday, daily, result, qresult,
|
| 81 |
+
# balance, cashflow, dividend, split, format_large_number, html_error are already defined
|
| 82 |
|
| 83 |
+
# -------------------------- INTRADAY ------------------------------
|
| 84 |
def fetch_intraday(symbol, indicators=None):
|
| 85 |
key = f"intraday_{symbol}"
|
|
|
|
| 86 |
if exists(key, "html"):
|
| 87 |
+
cached = load(key, "html")
|
| 88 |
+
if cached is not False:
|
| 89 |
+
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Using cached intraday for {symbol}")
|
| 90 |
+
return cached
|
| 91 |
|
| 92 |
try:
|
|
|
|
| 93 |
df = intraday(symbol)
|
| 94 |
+
if df is False or df is None or df.empty:
|
| 95 |
return wrap_html(f"<h1>No intraday data for {symbol}</h1>")
|
| 96 |
|
| 97 |
if isinstance(df.columns, pd.MultiIndex):
|
| 98 |
df.columns = df.columns.get_level_values(0)
|
| 99 |
|
| 100 |
+
# Optional upload
|
| 101 |
+
upload_file("eshanhf", f"intraday/{symbol}.csv", df)
|
| 102 |
|
| 103 |
+
# Preserve index in HTML
|
| 104 |
+
df_display = df.tail(50).copy()
|
| 105 |
+
df_display.reset_index(inplace=True)
|
| 106 |
+
html = wrap_html(f"<h2>Last 50 Rows</h2>{make_table(df_display)}", title=f"{symbol} Intraday")
|
| 107 |
|
| 108 |
+
save(key, html, "html")
|
| 109 |
+
return html
|
| 110 |
except Exception as e:
|
| 111 |
+
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_intraday: {e}")
|
| 112 |
return wrap_html(f"<h1>Error: {e}</h1>")
|
| 113 |
|
| 114 |
+
|
| 115 |
+
# -------------------------- DAILY ------------------------------
|
|
|
|
| 116 |
def fetch_daily(symbol):
|
| 117 |
key = f"daily_{symbol}"
|
|
|
|
| 118 |
if exists(key, "html"):
|
| 119 |
+
cached = load(key, "html")
|
| 120 |
+
if cached is not False:
|
| 121 |
+
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Using cached daily for {symbol}")
|
| 122 |
+
return cached
|
| 123 |
|
| 124 |
try:
|
|
|
|
| 125 |
df = daily(symbol)
|
| 126 |
+
if df is False or df is None or df.empty:
|
| 127 |
return wrap_html(f"<h1>No daily data for {symbol}</h1>")
|
| 128 |
|
| 129 |
+
upload_file("eshanhf", f"daily/{symbol}.csv", df)
|
|
|
|
| 130 |
|
| 131 |
+
df_display = df.tail(50).copy()
|
| 132 |
+
df_display.reset_index(inplace=True)
|
| 133 |
+
html = wrap_html(f"<h2>Last 50 Rows</h2>{make_table(df_display)}", title=f"{symbol} Daily")
|
| 134 |
|
| 135 |
+
save(key, html, "html")
|
| 136 |
+
return html
|
|
|
|
| 137 |
except Exception as e:
|
| 138 |
+
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_daily: {e}")
|
| 139 |
return wrap_html(f"<h1>Error: {e}</h1>")
|
| 140 |
|
| 141 |
|
|
|
|
| 153 |
if df.empty:
|
| 154 |
return wrap_html(f"<h1>No quarterly results for {symbol}</h1>")
|
| 155 |
|
|
|
|
| 156 |
upload_file("eshanhf", f"qresult/{symbol}.csv", df)
|
| 157 |
|
| 158 |
+
df_display = df.copy()
|
| 159 |
+
for col in df_display.columns:
|
| 160 |
+
df_display[col] = df_display[col].apply(lambda x: format_large_number(x) if isinstance(x, (int, float)) else x)
|
| 161 |
+
df_display.reset_index(inplace=True) # preserve original index
|
|
|
|
| 162 |
|
| 163 |
+
html = wrap_html(make_table(df_display), title=f"{symbol} Quarterly Results")
|
| 164 |
save(key, html, "html")
|
|
|
|
| 165 |
return html
|
| 166 |
except Exception as e:
|
| 167 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_qresult: {e}")
|
|
|
|
| 184 |
|
| 185 |
upload_file("eshanhf", f"result/{symbol}.csv", df)
|
| 186 |
|
| 187 |
+
df_display = df.copy()
|
| 188 |
+
for col in df_display.columns:
|
| 189 |
+
df_display[col] = df_display[col].apply(lambda x: format_large_number(x) if isinstance(x, (int, float)) else x)
|
| 190 |
+
df_display.reset_index(inplace=True)
|
| 191 |
|
| 192 |
+
html = wrap_html(make_table(df_display), title=f"{symbol} Annual Results")
|
| 193 |
save(key, html, "html")
|
|
|
|
| 194 |
return html
|
| 195 |
except Exception as e:
|
| 196 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_result: {e}")
|
|
|
|
| 213 |
|
| 214 |
upload_file("eshanhf", f"balance/{symbol}.csv", df)
|
| 215 |
|
| 216 |
+
df_display = df.copy()
|
| 217 |
+
for col in df_display.columns:
|
| 218 |
+
df_display[col] = df_display[col].apply(lambda x: format_large_number(x) if isinstance(x, (int, float)) else x)
|
| 219 |
+
df_display.reset_index(inplace=True)
|
| 220 |
|
| 221 |
+
html = wrap_html(make_table(df_display), title=f"{symbol} Balance Sheet")
|
| 222 |
save(key, html, "html")
|
|
|
|
| 223 |
return html
|
| 224 |
except Exception as e:
|
| 225 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_balance: {e}")
|
|
|
|
| 242 |
|
| 243 |
upload_file("eshanhf", f"cashflow/{symbol}.csv", df)
|
| 244 |
|
| 245 |
+
df_display = df.copy()
|
| 246 |
+
for col in df_display.columns:
|
| 247 |
+
df_display[col] = df_display[col].apply(lambda x: format_large_number(x) if isinstance(x, (int, float)) else x)
|
| 248 |
+
df_display.reset_index(inplace=True)
|
| 249 |
|
| 250 |
+
html = wrap_html(make_table(df_display), title=f"{symbol} Cash Flow")
|
| 251 |
save(key, html, "html")
|
|
|
|
| 252 |
return html
|
| 253 |
except Exception as e:
|
| 254 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_cashflow: {e}")
|
|
|
|
| 269 |
if df.empty:
|
| 270 |
return wrap_html(f"<h1>No dividend history for {symbol}</h1>")
|
| 271 |
|
| 272 |
+
df_display = df.copy()
|
| 273 |
+
for col in df_display.columns:
|
| 274 |
+
df_display[col] = df_display[col].apply(lambda x: format_large_number(x) if isinstance(x, (int, float)) else x)
|
| 275 |
+
df_display.reset_index(inplace=True)
|
| 276 |
|
| 277 |
+
html = wrap_html(make_table(df_display), title=f"{symbol} Dividends")
|
| 278 |
save(key, html, "html")
|
|
|
|
| 279 |
return html
|
| 280 |
except Exception as e:
|
| 281 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_dividend: {e}")
|
|
|
|
| 296 |
if df.empty:
|
| 297 |
return wrap_html(f"<h1>No splits for {symbol}</h1>")
|
| 298 |
|
| 299 |
+
df_display = df.copy()
|
| 300 |
+
for col in df_display.columns:
|
| 301 |
+
df_display[col] = df_display[col].apply(lambda x: format_large_number(x) if isinstance(x, (int, float)) else x)
|
| 302 |
+
df_display.reset_index(inplace=True)
|
| 303 |
|
| 304 |
+
html = wrap_html(make_table(df_display), title=f"{symbol} Splits")
|
| 305 |
save(key, html, "html")
|
|
|
|
| 306 |
return html
|
| 307 |
except Exception as e:
|
| 308 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_split: {e}")
|
|
|
|
| 324 |
if df.empty:
|
| 325 |
return wrap_html(f"<h1>No earnings data for {symbol}</h1>")
|
| 326 |
|
| 327 |
+
df_display = df.copy()
|
| 328 |
+
for col in df_display.columns:
|
| 329 |
+
df_display[col] = df_display[col].apply(lambda x: format_large_number(x) if isinstance(x, (int, float)) else x)
|
| 330 |
+
df_display.reset_index(inplace=True)
|
| 331 |
|
| 332 |
+
html = wrap_html(make_table(df_display), title=f"{symbol} Earnings")
|
| 333 |
save(key, html, "html")
|
|
|
|
| 334 |
return html
|
| 335 |
except Exception as e:
|
| 336 |
print(f"[{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}] Error fetch_other: {e}")
|
| 337 |
return wrap_html(html_error(f"Earnings Error: {e}"))
|
|
|