eshan6704 commited on
Commit
1b21664
·
verified ·
1 Parent(s): f5ffea0

Update app/daily.py

Browse files
Files changed (1) hide show
  1. app/daily.py +87 -146
app/daily.py CHANGED
@@ -3,10 +3,12 @@ import yfinance as yf
3
  import pandas as pd
4
  from datetime import datetime as dt
5
  import traceback
 
 
6
  from . import persist
7
 
8
- # ============================================================
9
- # DAILY DATA FETCH (FINALIZED)
10
  # ============================================================
11
  def daily(symbol, date_end, date_start):
12
  start = dt.strptime(date_start, "%d-%m-%Y").strftime("%Y-%m-%d")
@@ -17,13 +19,10 @@ def daily(symbol, date_end, date_start):
17
  if isinstance(df.columns, pd.MultiIndex):
18
  df.columns = df.columns.get_level_values(0)
19
 
20
- df.columns.name = None
21
  df.index.name = "Date"
22
  return df
23
 
24
 
25
- # ============================================================
26
- # DAILY DASHBOARD (FULL HTML)
27
  # ============================================================
28
  def fetch_daily(symbol, date_end, date_start):
29
  key = f"daily_{symbol}"
@@ -35,165 +34,107 @@ def fetch_daily(symbol, date_end, date_start):
35
 
36
  try:
37
  df = daily(symbol, date_end, date_start)
38
- if df is None or df.empty:
39
- return "<h1>No daily data</h1>"
40
 
41
- # -------------------------------
42
- # CLEAN DATA
43
- # -------------------------------
44
  df = df.reset_index()
45
  df["Date"] = pd.to_datetime(df["Date"], errors="coerce")
46
  df = df.dropna(subset=["Date"])
47
 
48
- for c in ["Open", "High", "Low", "Close", "Volume"]:
49
  df[c] = pd.to_numeric(df[c], errors="coerce")
50
 
51
  df = df.dropna()
52
-
53
  df["DateStr"] = df["Date"].dt.strftime("%d-%b-%Y")
 
54
  df["MA20"] = df["Close"].rolling(20).mean()
55
  df["MA50"] = df["Close"].rolling(50).mean()
56
 
57
- # -------------------------------
58
- # HTML TABLE
59
- # -------------------------------
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
  rows = ""
61
- for i, r in df.iterrows():
62
- bg = "#eef6ff" if i % 2 == 0 else "#ffffff"
63
  rows += f"""
64
- <tr style="background:{bg}">
65
- <td>{r['DateStr']}</td>
66
- <td>{r['Open']:.2f}</td>
67
- <td>{r['High']:.2f}</td>
68
- <td>{r['Low']:.2f}</td>
69
- <td>{r['Close']:.2f}</td>
70
- <td>{int(r['Volume'])}</td>
71
  </tr>
72
  """
73
 
74
- table_html = f"""
75
- <div class="table-wrap">
76
- <table>
77
- <thead>
78
- <tr>
79
- <th>Date</th><th>Open</th><th>High</th>
80
- <th>Low</th><th>Close</th><th>Volume</th>
81
- </tr>
82
- </thead>
83
- <tbody>{rows}</tbody>
84
- </table>
85
- </div>
86
- """
87
-
88
- # -------------------------------
89
- # FULL HTML OUTPUT
90
- # -------------------------------
91
  html = f"""
92
- <!DOCTYPE html>
93
- <html>
94
- <head>
95
- <meta charset="utf-8">
96
- <title>{symbol} Daily Dashboard</title>
97
-
98
- <script src="https://cdn.plot.ly/plotly-2.27.0.min.js"></script>
99
-
100
- <style>
101
- body {{
102
- font-family: Arial, sans-serif;
103
- background: #f4f6f9;
104
- margin: 10px;
105
- }}
106
-
107
- .table-wrap {{
108
- max-height: 300px;
109
- overflow-y: auto;
110
- margin-bottom: 20px;
111
- }}
112
-
113
- table {{
114
- width: 100%;
115
- border-collapse: collapse;
116
- background: white;
117
- }}
118
-
119
- th {{
120
- position: sticky;
121
- top: 0;
122
- background: linear-gradient(to right,#1a4f8a,#4a7ac7);
123
- color: white;
124
- padding: 6px;
125
- }}
126
-
127
- td {{
128
- padding: 6px;
129
- text-align: right;
130
- }}
131
-
132
- td:first-child {{
133
- text-align: left;
134
- }}
135
-
136
- .chart {{
137
- margin-bottom: 30px;
138
- }}
139
- </style>
140
- </head>
141
-
142
- <body>
143
-
144
- <h2>{symbol} – Daily Data</h2>
145
- {table_html}
146
-
147
- <h2>Candlestick & Volume</h2>
148
- <div id="candle" class="chart"></div>
149
-
150
- <h2>Moving Averages</h2>
151
- <div id="ma" class="chart"></div>
152
-
153
- <script>
154
- const dates = {df["DateStr"].tolist()};
155
- const openp = {df["Open"].round(2).tolist()};
156
- const highp = {df["High"].round(2).tolist()};
157
- const lowp = {df["Low"].round(2).tolist()};
158
- const closep= {df["Close"].round(2).tolist()};
159
- const volume= {df["Volume"].astype(int).tolist()};
160
-
161
- const ma20 = {df["MA20"].round(2).where(pd.notna(df["MA20"]), None).tolist()};
162
- const ma50 = {df["MA50"].round(2).where(pd.notna(df["MA50"]), None).tolist()};
163
-
164
- Plotly.newPlot("candle", [
165
- {{
166
- x: dates,
167
- open: openp,
168
- high: highp,
169
- low: lowp,
170
- close: closep,
171
- type: "candlestick",
172
- name: "Price"
173
- }},
174
- {{
175
- x: dates,
176
- y: volume,
177
- type: "bar",
178
- yaxis: "y2",
179
- name: "Volume",
180
- opacity: 0.3
181
- }}
182
- ], {{
183
- yaxis: {{title: "Price"}},
184
- yaxis2: {{overlaying: "y", side: "right", title: "Volume"}},
185
- xaxis: {{rangeslider: {{visible:false}}}}
186
- }});
187
-
188
- Plotly.newPlot("ma", [
189
- {{x: dates, y: closep, type:"scatter", name:"Close"}},
190
- {{x: dates, y: ma20, type:"scatter", name:"MA20"}},
191
- {{x: dates, y: ma50, type:"scatter", name:"MA50"}}
192
- ]);
193
- </script>
194
-
195
- </body>
196
- </html>
197
  """
198
 
199
  persist.save(key, html, "html")
 
3
  import pandas as pd
4
  from datetime import datetime as dt
5
  import traceback
6
+ import os
7
+ import plotly.graph_objects as go
8
  from . import persist
9
 
10
+ BASE_STATIC = "/app/app/static/charts/daily"
11
+
12
  # ============================================================
13
  def daily(symbol, date_end, date_start):
14
  start = dt.strptime(date_start, "%d-%m-%Y").strftime("%Y-%m-%d")
 
19
  if isinstance(df.columns, pd.MultiIndex):
20
  df.columns = df.columns.get_level_values(0)
21
 
 
22
  df.index.name = "Date"
23
  return df
24
 
25
 
 
 
26
  # ============================================================
27
  def fetch_daily(symbol, date_end, date_start):
28
  key = f"daily_{symbol}"
 
34
 
35
  try:
36
  df = daily(symbol, date_end, date_start)
37
+ if df.empty:
38
+ return "<h1>No data</h1>"
39
 
 
 
 
40
  df = df.reset_index()
41
  df["Date"] = pd.to_datetime(df["Date"], errors="coerce")
42
  df = df.dropna(subset=["Date"])
43
 
44
+ for c in ["Open","High","Low","Close","Volume"]:
45
  df[c] = pd.to_numeric(df[c], errors="coerce")
46
 
47
  df = df.dropna()
 
48
  df["DateStr"] = df["Date"].dt.strftime("%d-%b-%Y")
49
+
50
  df["MA20"] = df["Close"].rolling(20).mean()
51
  df["MA50"] = df["Close"].rolling(50).mean()
52
 
53
+ # ------------------------------------------------
54
+ # IMAGE PATHS
55
+ # ------------------------------------------------
56
+ sym_dir = f"{BASE_STATIC}/{symbol}"
57
+ os.makedirs(sym_dir, exist_ok=True)
58
+
59
+ candle_path = f"{sym_dir}/candle.png"
60
+ ma_path = f"{sym_dir}/ma.png"
61
+
62
+ candle_url = f"/static/charts/daily/{symbol}/candle.png"
63
+ ma_url = f"/static/charts/daily/{symbol}/ma.png"
64
+
65
+ # ------------------------------------------------
66
+ # CANDLESTICK IMAGE
67
+ # ------------------------------------------------
68
+ fig = go.Figure()
69
+
70
+ fig.add_trace(go.Candlestick(
71
+ x=df["DateStr"],
72
+ open=df["Open"],
73
+ high=df["High"],
74
+ low=df["Low"],
75
+ close=df["Close"]
76
+ ))
77
+
78
+ fig.add_trace(go.Bar(
79
+ x=df["DateStr"],
80
+ y=df["Volume"],
81
+ yaxis="y2",
82
+ opacity=0.3
83
+ ))
84
+
85
+ fig.update_layout(
86
+ height=600,
87
+ yaxis=dict(title="Price"),
88
+ yaxis2=dict(overlaying="y", side="right", title="Volume"),
89
+ xaxis_rangeslider_visible=False
90
+ )
91
+
92
+ fig.write_image(candle_path, scale=2)
93
+
94
+ # ------------------------------------------------
95
+ # MA IMAGE
96
+ # ------------------------------------------------
97
+ fig2 = go.Figure()
98
+ fig2.add_trace(go.Scatter(x=df["DateStr"], y=df["Close"], name="Close"))
99
+ fig2.add_trace(go.Scatter(x=df["DateStr"], y=df["MA20"], name="MA20"))
100
+ fig2.add_trace(go.Scatter(x=df["DateStr"], y=df["MA50"], name="MA50"))
101
+
102
+ fig2.update_layout(height=500)
103
+ fig2.write_image(ma_path, scale=2)
104
+
105
+ # ------------------------------------------------
106
+ # TABLE HTML
107
+ # ------------------------------------------------
108
  rows = ""
109
+ for r in df.tail(100).itertuples():
 
110
  rows += f"""
111
+ <tr>
112
+ <td>{r.DateStr}</td>
113
+ <td>{r.Open:.2f}</td>
114
+ <td>{r.High:.2f}</td>
115
+ <td>{r.Low:.2f}</td>
116
+ <td>{r.Close:.2f}</td>
117
+ <td>{int(r.Volume)}</td>
118
  </tr>
119
  """
120
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
121
  html = f"""
122
+ <h2>{symbol} Daily Dashboard</h2>
123
+
124
+ <h3>Price Table</h3>
125
+ <table border="1" cellpadding="4">
126
+ <tr>
127
+ <th>Date</th><th>Open</th><th>High</th>
128
+ <th>Low</th><th>Close</th><th>Volume</th>
129
+ </tr>
130
+ {rows}
131
+ </table>
132
+
133
+ <h3>Candlestick Chart</h3>
134
+ <img src="{candle_url}" style="width:100%;max-width:1200px;">
135
+
136
+ <h3>Moving Averages</h3>
137
+ <img src="{ma_url}" style="width:100%;max-width:1200px;">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
138
  """
139
 
140
  persist.save(key, html, "html")