eshan6704 commited on
Commit
06d5ee5
·
verified ·
1 Parent(s): 6ef3c72

Update app/build_nse_fno.py

Browse files
Files changed (1) hide show
  1. app/build_nse_fno.py +47 -31
app/build_nse_fno.py CHANGED
@@ -1,30 +1,32 @@
1
- # build_nse_fno_hf.py
2
- import os
3
  import zipfile
4
  import io
5
  import pandas as pd
6
  import requests
7
  from datetime import datetime as dt
 
8
 
9
  NSE_FO_BASE = "https://archives.nseindia.com/content/fo"
10
 
 
 
 
 
 
11
 
12
- # ============================================================
13
- # FETCH FO BHAVCOPY (RAW DF) - HF-friendly
14
- # ============================================================
 
 
 
15
  def fetch_fo_bhavcopy(fo_date: str) -> pd.DataFrame:
16
- """
17
- fo_date format : DD-MM-YYYY
18
- """
19
  date = dt.strptime(fo_date, "%d-%m-%Y").date()
20
  ymd = date.strftime("%Y%m%d")
21
-
22
  file_name = f"BhavCopy_NSE_FO_0_0_0_{ymd}_F_0000.csv"
23
  zip_name = f"{file_name}.zip"
24
  url = f"{NSE_FO_BASE}/{zip_name}"
25
 
26
  headers = {"User-Agent": "Mozilla/5.0"}
27
-
28
  r = requests.get(url, headers=headers, timeout=10)
29
  if r.status_code != 200:
30
  raise RuntimeError(f"FO bhavcopy download failed ({r.status_code})")
@@ -33,12 +35,15 @@ def fetch_fo_bhavcopy(fo_date: str) -> pd.DataFrame:
33
  if file_name not in z.namelist():
34
  raise RuntimeError("FO bhavcopy CSV missing inside zip")
35
  with z.open(file_name) as f:
36
- return pd.read_csv(f)
37
 
 
 
 
38
 
39
- # ============================================================
40
- # OPTION CHAIN BUILDER
41
- # ============================================================
42
  def build_option_chain(df: pd.DataFrame) -> pd.DataFrame:
43
  rename = {
44
  "ClsPric": "close",
@@ -49,7 +54,6 @@ def build_option_chain(df: pd.DataFrame) -> pd.DataFrame:
49
  }
50
 
51
  df = df.rename(columns=rename)
52
-
53
  ce = df[df["OptnTp"] == "CE"].rename(columns={c: f"ce_{c}" for c in df.columns})
54
  pe = df[df["OptnTp"] == "PE"].rename(columns={c: f"pe_{c}" for c in df.columns})
55
 
@@ -59,7 +63,6 @@ def build_option_chain(df: pd.DataFrame) -> pd.DataFrame:
59
  right_on="pe_StrkPric",
60
  how="outer"
61
  )
62
-
63
  chain["StrkPric"] = chain["ce_StrkPric"].combine_first(chain["pe_StrkPric"])
64
 
65
  keep = [
@@ -67,25 +70,34 @@ def build_option_chain(df: pd.DataFrame) -> pd.DataFrame:
67
  "StrkPric",
68
  "pe_pre", "pe_close", "pe_vol", "pe_oi_chg", "pe_oi"
69
  ]
70
-
71
  out = chain[keep].fillna(0).sort_values("StrkPric")
72
-
73
  for c in out.columns:
74
  out[c] = pd.to_numeric(out[c], errors="coerce").fillna(0)
75
-
76
  return out.reset_index(drop=True)
77
 
78
-
79
- # ============================================================
80
- # MAIN LIVE HTML BUILDER
81
- # ============================================================
82
  def nse_fno_html(fo_date: str, symbol: str) -> str:
83
- """
84
- Returns LIVE HTML for NSE F&O for the given date and symbol.
85
- """
86
- fo_df = fetch_fo_bhavcopy(fo_date)
 
 
 
 
 
 
 
 
 
 
 
87
  if fo_df.empty:
88
- return "<h3>FO Bhavcopy empty</h3>"
 
 
89
 
90
  fo = fo_df.copy()
91
  exp = pd.to_datetime(fo["FininstrmActlXpryDt"], errors="coerce")
@@ -93,18 +105,21 @@ def nse_fno_html(fo_date: str, symbol: str) -> str:
93
 
94
  monthly = exp[exp >= today].groupby([exp.dt.year, exp.dt.month]).max()
95
  if monthly.empty:
96
- return "<h3>No valid expiry</h3>"
 
 
97
 
98
  expiry = monthly.iloc[0].strftime("%d-%m-%Y")
99
  fo["EXP"] = exp.dt.strftime("%d-%m-%Y")
100
 
101
  df = fo[(fo["TckrSymb"] == symbol) & (fo["EXP"] == expiry)]
102
  if df.empty:
103
- return f"<h3>No F&O data for {symbol}</h3>"
 
 
104
 
105
  fut_df = df[df["FinInstrmTp"].isin(["STF", "IDF"])]
106
  opt_df = df[df["FinInstrmTp"].isin(["STO", "IDO"])]
107
-
108
  opt_chain = build_option_chain(opt_df)
109
 
110
  html = f"""
@@ -134,4 +149,5 @@ h2,h3,h4 {{ margin:6px 0; }}
134
  </body>
135
  </html>
136
  """
 
137
  return html
 
 
 
1
  import zipfile
2
  import io
3
  import pandas as pd
4
  import requests
5
  from datetime import datetime as dt
6
+ from . import persist # your persist.py
7
 
8
  NSE_FO_BASE = "https://archives.nseindia.com/content/fo"
9
 
10
+ # -------------------------------
11
+ # Helper for FO cache naming
12
+ # -------------------------------
13
+ def fo_cache_name(fo_date: str):
14
+ return f"BHAV_{fo_date.replace('-', '')}"
15
 
16
+ def html_cache_name(symbol: str, fo_date: str):
17
+ return f"HTML_{symbol}_{fo_date.replace('-', '')}"
18
+
19
+ # -------------------------------
20
+ # Fetch FO Bhavcopy (requests)
21
+ # -------------------------------
22
  def fetch_fo_bhavcopy(fo_date: str) -> pd.DataFrame:
 
 
 
23
  date = dt.strptime(fo_date, "%d-%m-%Y").date()
24
  ymd = date.strftime("%Y%m%d")
 
25
  file_name = f"BhavCopy_NSE_FO_0_0_0_{ymd}_F_0000.csv"
26
  zip_name = f"{file_name}.zip"
27
  url = f"{NSE_FO_BASE}/{zip_name}"
28
 
29
  headers = {"User-Agent": "Mozilla/5.0"}
 
30
  r = requests.get(url, headers=headers, timeout=10)
31
  if r.status_code != 200:
32
  raise RuntimeError(f"FO bhavcopy download failed ({r.status_code})")
 
35
  if file_name not in z.namelist():
36
  raise RuntimeError("FO bhavcopy CSV missing inside zip")
37
  with z.open(file_name) as f:
38
+ df = pd.read_csv(f)
39
 
40
+ # Save FO dataframe via persist
41
+ persist.save(fo_cache_name(fo_date), df, "pkl")
42
+ return df
43
 
44
+ # -------------------------------
45
+ # Option Chain Builder
46
+ # -------------------------------
47
  def build_option_chain(df: pd.DataFrame) -> pd.DataFrame:
48
  rename = {
49
  "ClsPric": "close",
 
54
  }
55
 
56
  df = df.rename(columns=rename)
 
57
  ce = df[df["OptnTp"] == "CE"].rename(columns={c: f"ce_{c}" for c in df.columns})
58
  pe = df[df["OptnTp"] == "PE"].rename(columns={c: f"pe_{c}" for c in df.columns})
59
 
 
63
  right_on="pe_StrkPric",
64
  how="outer"
65
  )
 
66
  chain["StrkPric"] = chain["ce_StrkPric"].combine_first(chain["pe_StrkPric"])
67
 
68
  keep = [
 
70
  "StrkPric",
71
  "pe_pre", "pe_close", "pe_vol", "pe_oi_chg", "pe_oi"
72
  ]
 
73
  out = chain[keep].fillna(0).sort_values("StrkPric")
 
74
  for c in out.columns:
75
  out[c] = pd.to_numeric(out[c], errors="coerce").fillna(0)
 
76
  return out.reset_index(drop=True)
77
 
78
+ # -------------------------------
79
+ # Main HTML builder with persist
80
+ # -------------------------------
 
81
  def nse_fno_html(fo_date: str, symbol: str) -> str:
82
+ html_name = html_cache_name(symbol, fo_date)
83
+ fo_name = fo_cache_name(fo_date)
84
+
85
+ # 1️⃣ Check if HTML exists
86
+ if persist.exists(html_name, "html"):
87
+ html = persist.load(html_name, "html")
88
+ if html:
89
+ return html
90
+
91
+ # 2️⃣ Check if FO dataframe exists
92
+ if persist.exists(fo_name, "pkl"):
93
+ fo_df = persist.load(fo_name, "pkl")
94
+ else:
95
+ fo_df = fetch_fo_bhavcopy(fo_date)
96
+
97
  if fo_df.empty:
98
+ html = "<h3>FO Bhavcopy empty</h3>"
99
+ persist.save(html_name, html, "html")
100
+ return html
101
 
102
  fo = fo_df.copy()
103
  exp = pd.to_datetime(fo["FininstrmActlXpryDt"], errors="coerce")
 
105
 
106
  monthly = exp[exp >= today].groupby([exp.dt.year, exp.dt.month]).max()
107
  if monthly.empty:
108
+ html = "<h3>No valid expiry</h3>"
109
+ persist.save(html_name, html, "html")
110
+ return html
111
 
112
  expiry = monthly.iloc[0].strftime("%d-%m-%Y")
113
  fo["EXP"] = exp.dt.strftime("%d-%m-%Y")
114
 
115
  df = fo[(fo["TckrSymb"] == symbol) & (fo["EXP"] == expiry)]
116
  if df.empty:
117
+ html = f"<h3>No F&O data for {symbol}</h3>"
118
+ persist.save(html_name, html, "html")
119
+ return html
120
 
121
  fut_df = df[df["FinInstrmTp"].isin(["STF", "IDF"])]
122
  opt_df = df[df["FinInstrmTp"].isin(["STO", "IDO"])]
 
123
  opt_chain = build_option_chain(opt_df)
124
 
125
  html = f"""
 
149
  </body>
150
  </html>
151
  """
152
+ persist.save(html_name, html, "html")
153
  return html