from nsepython import * import pandas as pd import re def build_preopen_html(key="NIFTY"): # Fetch pre-open data p = nsefetch(f"https://www.nseindia.com/api/market-data-pre-open?key={key}") data_df = df_from_data(p.pop("data")) rem_df = df_from_data([p]) main_df = data_df.iloc[[0]] if not data_df.empty else pd.DataFrame() const_df = data_df.iloc[1:] if len(data_df) > 1 else pd.DataFrame() # ================= REMOVE *_x AND SPECIFIC PATTERNS ================= pattern_remove = re.compile(r"^(price_|buyQty_|sellQty_|iep_)\d+$") def remove_pattern_cols(df): return df[[c for c in df.columns if not pattern_remove.match(c)]] main_df = remove_pattern_cols(main_df) const_df = remove_pattern_cols(const_df) rem_df = remove_pattern_cols(rem_df) # ================= HELPER FUNCTION ================= def df_to_html_color(df, metric_col=None): df_html = df.copy() top3_up, top3_down = [], [] if metric_col and metric_col in df_html.columns and pd.api.types.is_numeric_dtype(df_html[metric_col]): col_numeric = df_html[metric_col].dropna() top3_up = col_numeric.nlargest(3).index.tolist() top3_down = col_numeric.nsmallest(3).index.tolist() for idx, row in df_html.iterrows(): for col in df_html.columns: val = row[col] style = "" if isinstance(val, (int, float)): val_fmt = f"{val:.2f}" if val > 0: style = "numeric-positive" elif val < 0: style = "numeric-negative" if metric_col == col: if idx in top3_up: style += " top-up" elif idx in top3_down: style += " top-down" df_html.at[idx, col] = f'{val_fmt}' else: df_html.at[idx, col] = str(val) return df_html.to_html(index=False, escape=False, classes="compact-table") # ================= MINI-CARDS ================= def merge_info_main_cards(rem_df, main_df): combined = pd.concat([rem_df, main_df], axis=1) combined = combined.loc[:, ~combined.columns.duplicated()] # Remove pattern columns combined = combined[[c for c in combined.columns if not pattern_remove.match(c)]] cards_html = '
' for col in combined.columns: val = combined.at[0, col] if not combined.empty else "" cards_html += f'''
{col}
{val}
''' cards_html += '
' return cards_html info_cards_html = merge_info_main_cards(rem_df, main_df) # ================= Constituents table ================= cons_html = df_to_html_color(const_df) if not const_df.empty else "No pre-open constituents" # ================= Metric tables (restricted to selected columns) ================= metric_cols_allowed = ["pChange", "totalTurnover", "marketCap", "totalTradedVolume"] metric_cols = [c for c in metric_cols_allowed if c in const_df.columns and pd.api.types.is_numeric_dtype(const_df[c])] if not const_df.empty else [] metric_tables = "" for col in metric_cols: df_const = const_df.copy() df_const[col] = pd.to_numeric(df_const[col], errors="ignore") df_const = df_const.sort_values(col, ascending=False) df_html = df_to_html_color(df_const[['symbol', col]] if 'symbol' in df_const.columns else df_const[[col]], metric_col=col) metric_tables += f"""
{col}
{df_html}
""" # ================= FINAL HTML ================= html = f"""

Pre-Open Data: {key}

Info + Main Data

{info_cards_html}

Pre-Open Constituents

{cons_html}

Metric Tables (selected numeric)

{metric_tables}
""" return html