eshan6704 commited on
Commit
03ea2b0
·
verified ·
1 Parent(s): a36de40

Create preopen_html.py

Browse files
Files changed (1) hide show
  1. preopen_html.py +186 -0
preopen_html.py ADDED
@@ -0,0 +1,186 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from nsepython import *
2
+ import pandas as pd
3
+
4
+ def build_preopen_html(key="NIFTY"):
5
+ # Fetch pre-open data
6
+ p = nsefetch("https://www.nseindia.com/api/market-data-pre-open?key=" + key)
7
+
8
+ data_df = df_from_data(p.pop("data"))
9
+ rem_df = df_from_data([p])
10
+
11
+ main_df = data_df.iloc[[0]] if not data_df.empty else pd.DataFrame()
12
+ const_df = data_df.iloc[1:] if len(data_df) > 1 else pd.DataFrame()
13
+
14
+ # ================= HELPER FUNCTION =================
15
+ def df_to_html_color(df, metric_col=None):
16
+ df_html = df.copy()
17
+ top3_up = []
18
+ top3_down = []
19
+ if metric_col and metric_col in df_html.columns and pd.api.types.is_numeric_dtype(df_html[metric_col]):
20
+ col_numeric = df_html[metric_col].dropna()
21
+ top3_up = col_numeric.nlargest(3).index.tolist()
22
+ top3_down = col_numeric.nsmallest(3).index.tolist()
23
+
24
+ for idx, row in df_html.iterrows():
25
+ for col in df_html.columns:
26
+ val = row[col]
27
+ style = ""
28
+ if pd.api.types.is_numeric_dtype(type(val)) or isinstance(val, (int, float)):
29
+ val_fmt = f"{val:.2f}"
30
+ if val > 0:
31
+ style = "numeric-positive"
32
+ elif val < 0:
33
+ style = "numeric-negative"
34
+ if metric_col and col == metric_col:
35
+ if idx in top3_up:
36
+ style += " top-up"
37
+ elif idx in top3_down:
38
+ style += " top-down"
39
+ df_html.at[idx, col] = f'<span class="{style.strip()}">{val_fmt}</span>'
40
+ else:
41
+ df_html.at[idx, col] = str(val)
42
+ return df_html.to_html(index=False, escape=False, classes="compact-table")
43
+
44
+ # ================= MERGE INFO + MAIN INTO MINI-CARDS =================
45
+ def merge_info_main_cards(rem_df, main_df):
46
+ combined = pd.concat([rem_df, main_df], axis=1)
47
+ combined = combined.loc[:, ~combined.columns.duplicated()]
48
+ cards_html = '<div class="mini-card-container">'
49
+ for col in combined.columns:
50
+ val = combined.at[0, col] if not combined.empty else ""
51
+ cards_html += f'''
52
+ <div class="mini-card">
53
+ <div class="card-key">{col}</div>
54
+ <div class="card-val">{val}</div>
55
+ </div>
56
+ '''
57
+ cards_html += '</div>'
58
+ return cards_html
59
+
60
+ info_cards_html = merge_info_main_cards(rem_df, main_df)
61
+
62
+ # Constituents table
63
+ cons_html = df_to_html_color(const_df) if not const_df.empty else "<i>No pre-open constituents</i>"
64
+
65
+ # Metric tables (for numeric columns)
66
+ metric_cols = [c for c in const_df.columns if pd.api.types.is_numeric_dtype(const_df[c])] if not const_df.empty else []
67
+ metric_tables = ""
68
+ for col in metric_cols:
69
+ df_const = const_df.copy()
70
+ df_const[col] = pd.to_numeric(df_const[col], errors="ignore")
71
+ df_const = df_const.sort_values(col, ascending=False)
72
+ df_html = df_to_html_color(df_const[['symbol', col]] if 'symbol' in df_const.columns else df_const[[col]], metric_col=col)
73
+ metric_tables += f"""
74
+ <div class="small-table">
75
+ <div class="st-title">{col}</div>
76
+ <div class="st-body">{df_html}</div>
77
+ </div>
78
+ """
79
+
80
+ # ================= FINAL HTML =================
81
+ html = f"""
82
+ <!DOCTYPE html>
83
+ <html>
84
+ <head>
85
+ <meta charset="UTF-8">
86
+ <style>
87
+ body {{
88
+ font-family: Arial;
89
+ margin: 12px;
90
+ background: #f5f5f5;
91
+ color: #222;
92
+ font-size: 14px;
93
+ }}
94
+ h2, h3 {{
95
+ margin: 12px 0 6px 0;
96
+ font-weight: 600;
97
+ }}
98
+ table {{
99
+ border-collapse: collapse;
100
+ width: 100%;
101
+ table-layout: auto;
102
+ }}
103
+ th, td {{
104
+ border: 1px solid #bbb;
105
+ padding: 5px 8px;
106
+ text-align: left;
107
+ font-size: 13px;
108
+ }}
109
+ th {{
110
+ background: #333;
111
+ color: white;
112
+ font-weight: 600;
113
+ }}
114
+ .compact-table td.numeric-positive {{ color: green; font-weight: bold; }}
115
+ .compact-table td.numeric-negative {{ color: red; font-weight: bold; }}
116
+ .compact-table td.top-up {{ background: #a8f0a5; }}
117
+ .compact-table td.top-down {{ background: #f0a8a8; }}
118
+ .small-table {{
119
+ background: white;
120
+ border-radius: 6px;
121
+ padding: 8px;
122
+ box-shadow: 0px 1px 4px rgba(0,0,0,0.15);
123
+ border: 1px solid #ddd;
124
+ overflow-y: auto;
125
+ }}
126
+ .st-title {{
127
+ font-size: 14px;
128
+ text-align: center;
129
+ margin-bottom: 6px;
130
+ font-weight: bold;
131
+ background: #222;
132
+ color: white;
133
+ padding: 5px 0;
134
+ border-radius: 4px;
135
+ }}
136
+ .st-body {{
137
+ max-height: 300px;
138
+ overflow-y: auto;
139
+ font-size: 12px;
140
+ }}
141
+ .grid {{
142
+ display: grid;
143
+ grid-template-columns: repeat(5, 1fr);
144
+ gap: 12px;
145
+ margin-top: 12px;
146
+ }}
147
+ .mini-card-container {{
148
+ display: flex;
149
+ flex-wrap: wrap;
150
+ gap: 10px;
151
+ }}
152
+ .mini-card {{
153
+ background: #fff;
154
+ padding: 8px 10px;
155
+ border-radius: 6px;
156
+ box-shadow: 0 1px 3px rgba(0,0,0,0.12);
157
+ min-width: 120px;
158
+ font-size: 13px;
159
+ }}
160
+ .card-key {{ font-weight: bold; color: #333; margin-bottom: 2px; }}
161
+ .card-val {{ color: #222; }}
162
+ </style>
163
+ </head>
164
+ <body>
165
+
166
+ <h2>Pre-Open Data: {key}</h2>
167
+
168
+ <div class="compact-section">
169
+ <h3>Info + Main Data</h3>
170
+ {info_cards_html}
171
+ </div>
172
+
173
+ <div class="compact-section">
174
+ <h3>Pre-Open Constituents</h3>
175
+ {cons_html}
176
+ </div>
177
+
178
+ <h3>Metric Tables (if numeric)</h3>
179
+ <div class="grid">
180
+ {metric_tables}
181
+ </div>
182
+
183
+ </body>
184
+ </html>
185
+ """
186
+ return html