eshan6704 commited on
Commit
8ce9e3c
·
verified ·
1 Parent(s): e15bacf

Create daily.py

Browse files
Files changed (1) hide show
  1. app/daily.py +99 -0
app/daily.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # daily.py
2
+ import yfinance as yf
3
+ import pandas as pd
4
+ from datetime import datetime as dt
5
+ from plotly import graph_objs as go
6
+ from plotly.subplots import make_subplots
7
+ import traceback
8
+
9
+ from . import persist
10
+ from . import backblaze as b2
11
+ from .common import wrap_html, format_large_number
12
+
13
+ def fetch_daily(symbol, date_end, date_start, b2_save=False):
14
+ """
15
+ Fetch daily historical stock data and generate full analysis dashboard with Plotly charts.
16
+ """
17
+ key = f"daily_{symbol}"
18
+ if persist.exists(key, "html"):
19
+ cached = persist.load(key, "html")
20
+ if cached:
21
+ print(f"[{date_end}] Using cached daily for {symbol}")
22
+ return cached
23
+
24
+ try:
25
+ start = dt.strptime(date_start, "%d-%m-%Y").strftime("%Y-%m-%d")
26
+ end = dt.strptime(date_end, "%d-%m-%Y").strftime("%Y-%m-%d")
27
+
28
+ print(f"[{dt.now().strftime('%Y-%m-%d %H:%M:%S')}] Fetching daily for {symbol}")
29
+ df = yf.download(symbol + ".NS", start=start, end=end)
30
+ if df.empty:
31
+ return wrap_html(f"<h1>No daily data for {symbol}</h1>")
32
+
33
+ # Reset index and format Date
34
+ df.reset_index(inplace=True)
35
+ df["Date"] = df["Date"].dt.strftime("%d-%b-%Y")
36
+
37
+ # Optional save to Backblaze
38
+ if b2_save:
39
+ b2.upload_file("eshanhf", f"daily/{symbol}.csv", df)
40
+
41
+ # Calculate additional metrics
42
+ df["Daily Return %"] = df["Close"].pct_change() * 100
43
+ df["SMA20"] = df["Close"].rolling(20).mean()
44
+ df["SMA50"] = df["Close"].rolling(50).mean()
45
+ df["EMA20"] = df["Close"].ewm(span=20, adjust=False).mean()
46
+ df["UpperBB"] = df["Close"].rolling(20).mean() + 2*df["Close"].rolling(20).std()
47
+ df["LowerBB"] = df["Close"].rolling(20).mean() - 2*df["Close"].rolling(20).std()
48
+
49
+ # Summary stats
50
+ summary = pd.DataFrame({
51
+ "Metric": ["Start Date","End Date","Min Price","Max Price","Mean Price","Total Volume"],
52
+ "Value": [df["Date"].iloc[0], df["Date"].iloc[-1],
53
+ format_large_number(df["Close"].min()),
54
+ format_large_number(df["Close"].max()),
55
+ format_large_number(df["Close"].mean()),
56
+ format_large_number(df["Volume"].sum())]
57
+ })
58
+
59
+ # Plotly figure
60
+ fig = make_subplots(rows=2, cols=1, shared_xaxes=True,
61
+ vertical_spacing=0.1,
62
+ row_heights=[0.7,0.3],
63
+ specs=[[{"secondary_y": False}], [{"secondary_y": False}]])
64
+
65
+ # Candlestick
66
+ fig.add_trace(go.Candlestick(
67
+ x=df["Date"], open=df["Open"], high=df["High"], low=df["Low"], close=df["Close"],
68
+ name="OHLC"), row=1, col=1)
69
+
70
+ # SMA/EMA overlays
71
+ fig.add_trace(go.Scatter(x=df["Date"], y=df["SMA20"], mode="lines", name="SMA20"), row=1, col=1)
72
+ fig.add_trace(go.Scatter(x=df["Date"], y=df["SMA50"], mode="lines", name="SMA50"), row=1, col=1)
73
+ fig.add_trace(go.Scatter(x=df["Date"], y=df["EMA20"], mode="lines", name="EMA20"), row=1, col=1)
74
+
75
+ # Bollinger Bands
76
+ fig.add_trace(go.Scatter(x=df["Date"], y=df["UpperBB"], mode="lines", name="UpperBB", line=dict(dash="dot")), row=1, col=1)
77
+ fig.add_trace(go.Scatter(x=df["Date"], y=df["LowerBB"], mode="lines", name="LowerBB", line=dict(dash="dot")), row=1, col=1)
78
+
79
+ # Volume bar chart
80
+ fig.add_trace(go.Bar(x=df["Date"], y=df["Volume"], name="Volume"), row=2, col=1)
81
+
82
+ fig.update_layout(height=700, width=1000, title=f"{symbol} Daily Analysis",
83
+ xaxis_rangeslider_visible=False)
84
+
85
+ chart_html = fig.to_html(full_html=False, include_plotlyjs='cdn')
86
+
87
+ # Build table HTML
88
+ table_html = wrap_html(f"<h2>Summary</h2>{summary.to_html(index=False, escape=False)}")
89
+ data_table_html = wrap_html(f"<h2>OHLC Table</h2>{df.to_html(index=False, escape=False)}")
90
+
91
+ # Combine full dashboard
92
+ full_html = chart_html + table_html + data_table_html
93
+
94
+ # Cache HTML
95
+ persist.save(key, full_html, "html")
96
+ return full_html
97
+
98
+ except Exception as e:
99
+ return wrap_html(f"<h1>Error fetch_daily: {e}</h1><pre>{traceback.format_exc()}</pre>")