eshan6704 commited on
Commit
62d151c
·
verified ·
1 Parent(s): 3714a53

Update index_live_html.py

Browse files
Files changed (1) hide show
  1. index_live_html.py +76 -100
index_live_html.py CHANGED
@@ -1,24 +1,49 @@
1
-
2
  from nsepython import *
3
  import pandas as pd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
4
 
 
5
  def build_index_live_html():
 
 
 
 
 
6
  index_name = "NIFTY 50"
7
  p = nse_index_live(index_name)
8
 
9
  full_df = p.get("data", pd.DataFrame())
10
  rem_df = p.get("rem", pd.DataFrame())
11
- print(rem_df)
12
- print(full_df)
13
 
14
  if full_df.empty:
15
  main_df = pd.DataFrame()
16
  const_df = pd.DataFrame()
17
  else:
18
  main_df = full_df.iloc[[0]]
19
- const_df = full_df.iloc[1:] # Constituents
 
20
  if not const_df.empty:
21
- const_df = const_df.iloc[:, 1:] # Remove first column
22
 
23
  # Move segment / time cols
24
  move_to_info = [c for c in ['segment', 'equityTime', 'preOpenTime'] if c in const_df.columns]
@@ -28,37 +53,37 @@ def build_index_live_html():
28
 
29
  # Drop cols (constituents)
30
  drop_cols_const = [
31
- "identifier", "ffmc", "stockIndClosePrice", "lastUpdateTime",
32
- "chartTodayPath", "chart30dPath", "chart365dPath", "series",
33
- "symbol_meta", "activeSeries", "debtSeries", "isFNOSec",
34
- "isCASec", "isSLBSec", "isDebtSec", "isSuspended",
35
- "tempSuspendedSeries", "isETFSec", "isDelisted",
36
- "slb_isin", "isMunicipalBond", "isHybridSymbol", "QuotePreOpenFlag"
37
  ]
38
  const_df = const_df.drop(columns=[c for c in drop_cols_const if c in const_df.columns])
39
 
40
  # Drop cols (main)
41
  drop_cols_main = [
42
- "series", "symbol_meta", "companyName", "industry", "activeSeries", "debtSeries",
43
- "isFNOSec", "isCASec", "isSLBSec", "isDebtSec", "isSuspended", "tempSuspendedSeries",
44
- "isETFSec", "isDelisted", "isin", "slb_isin", "listingDate", "isMunicipalBond",
45
- "isHybridSymbol", "segment", "equityTime", "preOpenTime", "QuotePreOpenFlag"
 
 
46
  ]
47
  main_df = main_df.drop(columns=[c for c in drop_cols_main if c in main_df.columns])
48
 
49
- # Sort by pChange
50
  if 'pChange' in const_df.columns:
51
  const_df['pChange'] = pd.to_numeric(const_df['pChange'], errors='coerce')
52
  const_df = const_df.sort_values('pChange', ascending=False)
53
 
54
- # ===== Helper: Convert DF to color-coded HTML =====
55
  def df_to_html_color(df, metric_col=None):
56
  df_html = df.copy()
57
- top3_up = []
58
- top3_down = []
59
 
60
- if metric_col and metric_col in df_html.columns and pd.api.types.is_numeric_dtype(df_html[metric_col]):
61
- col_numeric = df_html[metric_col].dropna()
62
  top3_up = col_numeric.nlargest(3).index.tolist()
63
  top3_down = col_numeric.nsmallest(3).index.tolist()
64
 
@@ -66,31 +91,22 @@ def build_index_live_html():
66
  for col in df_html.columns:
67
  val = row[col]
68
  style = ""
69
-
70
- if isinstance(val, (int, float)) or pd.api.types.is_number(val):
71
  val_fmt = f"{val:.2f}"
72
- if val > 0:
73
- style = "numeric-positive"
74
- elif val < 0:
75
- style = "numeric-negative"
76
-
77
  if metric_col and col == metric_col:
78
- if idx in top3_up:
79
- style += " top-up"
80
- elif idx in top3_down:
81
- style += " top-down"
82
-
83
  df_html.at[idx, col] = f'<span class="{style.strip()}">{val_fmt}</span>'
84
  else:
85
  df_html.at[idx, col] = str(val)
86
 
87
  return df_html.to_html(index=False, escape=False, classes="compact-table")
88
 
89
- # ===== Merge info + main into cards =====
90
  def merge_info_main_cards(rem_df, main_df):
91
  combined = pd.concat([rem_df, main_df], axis=1)
92
  combined = combined.loc[:, ~combined.columns.duplicated()]
93
-
94
  html = '<div class="mini-card-container">'
95
  for col in combined.columns:
96
  val = combined.at[0, col] if not combined.empty else ""
@@ -106,27 +122,19 @@ def build_index_live_html():
106
  info_cards_html = merge_info_main_cards(rem_df, main_df)
107
  cons_html = df_to_html_color(const_df)
108
 
109
- # ===== Metric tables =====
110
- metric_cols = [
111
- "pChange", "totalTradedValue", "nearWKH", "nearWKL",
112
- "perChange365d", "perChange30d"
113
- ]
114
-
115
  metric_tables = ""
 
116
  for col in metric_cols:
117
  if col not in const_df.columns:
118
  continue
119
-
120
- df_const = const_df.copy()
121
- df_const[col] = pd.to_numeric(df_const[col], errors="ignore")
122
  df_const = df_const.sort_values(col, ascending=False)
123
-
124
- df_html = df_to_html_color(df_const[['symbol', col]], metric_col=col)
125
-
126
  metric_tables += f"""
127
  <div class="small-table">
128
  <div class="st-title">{col}</div>
129
- <div class="st-body">{df_html}</div>
130
  </div>
131
  """
132
 
@@ -137,72 +145,40 @@ def build_index_live_html():
137
  <head>
138
  <meta charset="UTF-8">
139
  <style>
140
- /* CSS unchanged */
141
- body {{
142
- font-family: Arial;
143
- margin: 12px;
144
- background: #f5f5f5;
145
- color: #222;
146
- font-size: 14px;
147
- }}
148
- table {{
149
- border-collapse: collapse;
150
- width: 100%;
151
- }}
152
- th, td {{
153
- border: 1px solid #bbb;
154
- padding: 5px 8px;
155
- }}
156
- .compact-table td.numeric-positive {{ color: green; font-weight: bold; }}
157
- .compact-table td.numeric-negative {{ color: red; font-weight: bold; }}
158
- .compact-table td.top-up {{ background: #a8f0a5; }}
159
- .compact-table td.top-down {{ background: #f0a8a8; }}
160
  .mini-card-container {{ display: flex; flex-wrap: wrap; gap: 10px; }}
161
- .mini-card {{
162
- background: #fff; padding: 8px; border-radius: 6px;
163
- box-shadow: 0 1px 3px rgba(0,0,0,0.12);
164
- }}
165
- .card-key {{ font-weight: bold; }}
166
  .grid {{ display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; }}
167
- .small-table {{
168
- background: white;
169
- border-radius: 6px;
170
- padding: 8px;
171
- box-shadow: 0px 1px 4px rgba(0,0,0,0.15);
172
- }}
173
- .st-title {{
174
- text-align: center;
175
- background: #222;
176
- color: white;
177
- padding: 5px;
178
- border-radius: 4px;
179
- }}
180
- .st-body {{
181
- max-height: 300px;
182
- overflow-y: auto;
183
- }}
184
  </style>
185
  </head>
186
  <body>
187
 
188
  <h2>Live Index Data: NIFTY 50</h2>
189
 
190
- <div class="compact-section">
191
- <h3>Index Info + Main Data</h3>
192
- {info_cards_html}
193
- </div>
194
 
195
- <div class="compact-section">
196
- <h3>Constituents</h3>
197
- {cons_html}
198
- </div>
199
 
200
- <h3>Metric Tables (All Symbols)</h3>
201
  <div class="grid">
202
- {metric_tables}
203
  </div>
204
 
205
  </body>
206
  </html>
207
  """
 
 
 
208
  return html
 
 
1
  from nsepython import *
2
  import pandas as pd
3
+ import os
4
+ from datetime import datetime
5
+
6
+ # ----------------- CACHE CONFIG -----------------
7
+ CACHE_DIR = "./cache_html"
8
+ os.makedirs(CACHE_DIR, exist_ok=True)
9
+ CACHE_FILE = os.path.join(CACHE_DIR, "index_NIFTY50.html")
10
+
11
+ def _is_valid_daily(path):
12
+ if not os.path.exists(path):
13
+ return False
14
+ mtime = datetime.fromtimestamp(os.path.getmtime(path))
15
+ return mtime.date() == datetime.now().date()
16
+
17
+ def _read_html(path):
18
+ with open(path, "r", encoding="utf-8") as f:
19
+ return f.read()
20
+
21
+ def _write_html(path, html):
22
+ with open(path, "w", encoding="utf-8") as f:
23
+ f.write(html)
24
 
25
+ # ----------------- MAIN FUNCTION -----------------
26
  def build_index_live_html():
27
+ # ===== 1️⃣ CACHE CHECK =====
28
+ if _is_valid_daily(CACHE_FILE):
29
+ return _read_html(CACHE_FILE)
30
+
31
+ # ===== 2️⃣ LIVE FETCH =====
32
  index_name = "NIFTY 50"
33
  p = nse_index_live(index_name)
34
 
35
  full_df = p.get("data", pd.DataFrame())
36
  rem_df = p.get("rem", pd.DataFrame())
 
 
37
 
38
  if full_df.empty:
39
  main_df = pd.DataFrame()
40
  const_df = pd.DataFrame()
41
  else:
42
  main_df = full_df.iloc[[0]]
43
+ const_df = full_df.iloc[1:]
44
+
45
  if not const_df.empty:
46
+ const_df = const_df.iloc[:, 1:]
47
 
48
  # Move segment / time cols
49
  move_to_info = [c for c in ['segment', 'equityTime', 'preOpenTime'] if c in const_df.columns]
 
53
 
54
  # Drop cols (constituents)
55
  drop_cols_const = [
56
+ "identifier","ffmc","stockIndClosePrice","lastUpdateTime",
57
+ "chartTodayPath","chart30dPath","chart365dPath","series",
58
+ "symbol_meta","activeSeries","debtSeries","isFNOSec",
59
+ "isCASec","isSLBSec","isDebtSec","isSuspended",
60
+ "tempSuspendedSeries","isETFSec","isDelisted",
61
+ "slb_isin","isMunicipalBond","isHybridSymbol","QuotePreOpenFlag"
62
  ]
63
  const_df = const_df.drop(columns=[c for c in drop_cols_const if c in const_df.columns])
64
 
65
  # Drop cols (main)
66
  drop_cols_main = [
67
+ "series","symbol_meta","companyName","industry",
68
+ "activeSeries","debtSeries","isFNOSec","isCASec",
69
+ "isSLBSec","isDebtSec","isSuspended","tempSuspendedSeries",
70
+ "isETFSec","isDelisted","isin","slb_isin","listingDate",
71
+ "isMunicipalBond","isHybridSymbol",
72
+ "segment","equityTime","preOpenTime","QuotePreOpenFlag"
73
  ]
74
  main_df = main_df.drop(columns=[c for c in drop_cols_main if c in main_df.columns])
75
 
 
76
  if 'pChange' in const_df.columns:
77
  const_df['pChange'] = pd.to_numeric(const_df['pChange'], errors='coerce')
78
  const_df = const_df.sort_values('pChange', ascending=False)
79
 
80
+ # ===== Helper: Color HTML =====
81
  def df_to_html_color(df, metric_col=None):
82
  df_html = df.copy()
83
+ top3_up, top3_down = [], []
 
84
 
85
+ if metric_col and metric_col in df_html.columns:
86
+ col_numeric = pd.to_numeric(df_html[metric_col], errors="coerce").dropna()
87
  top3_up = col_numeric.nlargest(3).index.tolist()
88
  top3_down = col_numeric.nsmallest(3).index.tolist()
89
 
 
91
  for col in df_html.columns:
92
  val = row[col]
93
  style = ""
94
+ if isinstance(val, (int, float)):
 
95
  val_fmt = f"{val:.2f}"
96
+ if val > 0: style = "numeric-positive"
97
+ elif val < 0: style = "numeric-negative"
 
 
 
98
  if metric_col and col == metric_col:
99
+ if idx in top3_up: style += " top-up"
100
+ elif idx in top3_down: style += " top-down"
 
 
 
101
  df_html.at[idx, col] = f'<span class="{style.strip()}">{val_fmt}</span>'
102
  else:
103
  df_html.at[idx, col] = str(val)
104
 
105
  return df_html.to_html(index=False, escape=False, classes="compact-table")
106
 
 
107
  def merge_info_main_cards(rem_df, main_df):
108
  combined = pd.concat([rem_df, main_df], axis=1)
109
  combined = combined.loc[:, ~combined.columns.duplicated()]
 
110
  html = '<div class="mini-card-container">'
111
  for col in combined.columns:
112
  val = combined.at[0, col] if not combined.empty else ""
 
122
  info_cards_html = merge_info_main_cards(rem_df, main_df)
123
  cons_html = df_to_html_color(const_df)
124
 
125
+ metric_cols = ["pChange","totalTradedValue","nearWKH","nearWKL","perChange365d","perChange30d"]
 
 
 
 
 
126
  metric_tables = ""
127
+
128
  for col in metric_cols:
129
  if col not in const_df.columns:
130
  continue
131
+ df_const = const_df[['symbol', col]].copy()
132
+ df_const[col] = pd.to_numeric(df_const[col], errors="coerce")
 
133
  df_const = df_const.sort_values(col, ascending=False)
 
 
 
134
  metric_tables += f"""
135
  <div class="small-table">
136
  <div class="st-title">{col}</div>
137
+ <div class="st-body">{df_to_html_color(df_const, col)}</div>
138
  </div>
139
  """
140
 
 
145
  <head>
146
  <meta charset="UTF-8">
147
  <style>
148
+ body {{ font-family: Arial; margin: 12px; background: #f5f5f5; font-size: 14px; }}
149
+ table {{ border-collapse: collapse; width: 100%; }}
150
+ th, td {{ border: 1px solid #bbb; padding: 5px 8px; }}
151
+ .numeric-positive {{ color: green; font-weight: bold; }}
152
+ .numeric-negative {{ color: red; font-weight: bold; }}
153
+ .top-up {{ background: #a8f0a5; }}
154
+ .top-down {{ background: #f0a8a8; }}
 
 
 
 
 
 
 
 
 
 
 
 
 
155
  .mini-card-container {{ display: flex; flex-wrap: wrap; gap: 10px; }}
156
+ .mini-card {{ background: #fff; padding: 8px; border-radius: 6px; }}
 
 
 
 
157
  .grid {{ display: grid; grid-template-columns: repeat(5, 1fr); gap: 12px; }}
158
+ .small-table {{ background: white; padding: 8px; border-radius: 6px; }}
159
+ .st-title {{ background: #222; color: white; text-align: center; padding: 5px; }}
160
+ .st-body {{ max-height: 300px; overflow-y: auto; }}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
161
  </style>
162
  </head>
163
  <body>
164
 
165
  <h2>Live Index Data: NIFTY 50</h2>
166
 
167
+ <h3>Index Info + Main Data</h3>
168
+ {info_cards_html}
 
 
169
 
170
+ <h3>Constituents</h3>
171
+ {cons_html}
 
 
172
 
173
+ <h3>Metric Tables</h3>
174
  <div class="grid">
175
+ {metric_tables}
176
  </div>
177
 
178
  </body>
179
  </html>
180
  """
181
+
182
+ # ===== 3️⃣ SAVE CACHE =====
183
+ _write_html(CACHE_FILE, html)
184
  return html