eshan6704 commited on
Commit
b3eb208
·
verified ·
1 Parent(s): b749b01

Create app.py

Browse files
Files changed (1) hide show
  1. app/app.py +226 -0
app/app.py ADDED
@@ -0,0 +1,226 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from fastapi.responses import HTMLResponse
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ from fastapi.middleware.gzip import GZipMiddleware
5
+ from pydantic import BaseModel
6
+
7
+ # -------------------------------------------------------
8
+ # Local modules
9
+ # -------------------------------------------------------
10
+ from . import common
11
+ from . import stock
12
+ from . import indices_html as indices
13
+ from . import index_live_html as live
14
+ from . import preopen_html as pre
15
+ from . import eq_html as eq
16
+ from . import bhavcopy_html as bhav
17
+ from . import build_nse_fno as fno
18
+ from . import nsepythonmodified as ns
19
+ from . import yahooinfo
20
+ from . import screener # screener owns its map
21
+
22
+ # -------------------------------------------------------
23
+ # FastAPI app
24
+ # -------------------------------------------------------
25
+ app = FastAPI(title="Stock / Index Backend")
26
+
27
+ # -------------------------------------------------------
28
+ # Middleware
29
+ # -------------------------------------------------------
30
+ app.add_middleware(
31
+ CORSMiddleware,
32
+ allow_origins=["*"],
33
+ allow_methods=["*"],
34
+ allow_headers=["*"],
35
+ )
36
+ app.add_middleware(GZipMiddleware, minimum_size=1000)
37
+
38
+ # -------------------------------------------------------
39
+ # Request model
40
+ # -------------------------------------------------------
41
+ class FetchRequest(BaseModel):
42
+ mode: str
43
+ req_type: str
44
+ name: str = ""
45
+ date_start: str = ""
46
+ date_end: str = ""
47
+
48
+ # -------------------------------------------------------
49
+ # Health
50
+ # -------------------------------------------------------
51
+ @app.get("/")
52
+ def health():
53
+ return {"status": "ok", "service": "backend alive"}
54
+
55
+ # -------------------------------------------------------
56
+ # REQ TYPE MAP (stock & index only)
57
+ # -------------------------------------------------------
58
+ REQ_TYPE_MAP = {
59
+ "stock": [
60
+ "info", "intraday", "daily", "nse_eq", "qresult",
61
+ "result", "balance", "cashflow", "dividend",
62
+ "split", "other", "stock_hist", "nse_bhav"
63
+ ],
64
+ "index": [
65
+ "indices", "nse_open", "nse_preopen", "nse_fno",
66
+ "nse_fiidii", "nse_events", "nse_future",
67
+ "nse_highlow", "stock_highlow", "nse_largedeals",
68
+ "nse_bulkdeals", "nse_blockdeals", "nse_most_active",
69
+ "index_history", "largedeals_historical",
70
+ "index_pe_pb_div", "index_total_returns"
71
+ ],
72
+ }
73
+
74
+ # -------------------------------------------------------
75
+ # Name lists for frontend
76
+ # -------------------------------------------------------
77
+ FNO_STOCK_LIST = yahooinfo.FNOSTOCK_LIST # stock & nse_bhav
78
+ OPEN_INDICES_LIST = indices.NSE_OPEN_INDEX_LIST # nse_open
79
+ PREOPEN_INDICES_LIST = indices.NSE_PREOPEN_LIST # nse_preopen
80
+
81
+ # -------------------------------------------------------
82
+ # HTML builder for req_type discovery
83
+ # -------------------------------------------------------
84
+ def build_req_type_list_html():
85
+ html = ["<div id='req_type_list'>"]
86
+
87
+ # STOCK
88
+ html.append("<h3>STOCK</h3><ul>")
89
+ for t in REQ_TYPE_MAP["stock"]:
90
+ if t in ["stock_hist", "nse_bhav"]:
91
+ names = ",".join(FNO_STOCK_LIST)
92
+ else:
93
+ names = ""
94
+ html.append(
95
+ f"<li class='stock-req' data-mode='stock' data-type='{t}' data-names='{names}'>{t}</li>"
96
+ )
97
+ html.append("</ul>")
98
+
99
+ # INDEX
100
+ html.append("<h3>INDEX</h3><ul>")
101
+ for t in REQ_TYPE_MAP["index"]:
102
+ if t == "nse_open":
103
+ names = ",".join(OPEN_INDICES_LIST)
104
+ elif t == "nse_preopen":
105
+ names = ",".join(PREOPEN_INDICES_LIST)
106
+ else:
107
+ names = ""
108
+ html.append(
109
+ f"<li class='index-req' data-mode='index' data-type='{t}' data-names='{names}'>{t}</li>"
110
+ )
111
+ html.append("</ul>")
112
+
113
+ # SCREENER
114
+ html.append("<h3>SCREENER</h3><ul>")
115
+ for key in screener.SCREENER_MAP.keys():
116
+ html.append(
117
+ f"<li class='screener-req' data-mode='screener' data-type='{key}'>{key}</li>"
118
+ )
119
+ html.append("</ul></div>")
120
+
121
+ return "".join(html)
122
+
123
+ # -------------------------------------------------------
124
+ # STOCK handler
125
+ # -------------------------------------------------------
126
+ def handle_stock(req: FetchRequest):
127
+ t = req.req_type.lower()
128
+
129
+ if t == "info":
130
+ return yahooinfo.fetch_info(req.name)
131
+ if t == "intraday":
132
+ return stock.fetch_intraday(req.name)
133
+ if t == "daily":
134
+ return stock.fetch_daily(req.name, req.date_end)
135
+ if t == "nse_eq":
136
+ return eq.build_eq_html(req.name)
137
+ if t == "qresult":
138
+ return stock.fetch_qresult(req.name)
139
+ if t == "result":
140
+ return stock.fetch_result(req.name)
141
+ if t == "balance":
142
+ return stock.fetch_balance(req.name)
143
+ if t == "cashflow":
144
+ return stock.fetch_cashflow(req.name)
145
+ if t == "dividend":
146
+ return stock.fetch_dividend(req.name)
147
+ if t == "split":
148
+ return stock.fetch_split(req.name)
149
+ if t == "other":
150
+ return stock.fetch_other(req.name)
151
+ if t in ["stock_hist", "nse_bhav"]:
152
+ return ns.nse_stock_hist(req.date_start, req.date_end, req.name).to_html()
153
+
154
+ return common.wrap(f"<h3>Unhandled stock req_type: {t}</h3>")
155
+
156
+ # -------------------------------------------------------
157
+ # INDEX handler
158
+ # -------------------------------------------------------
159
+ def handle_index(req: FetchRequest):
160
+ t = req.req_type.lower()
161
+
162
+ if t == "indices":
163
+ return indices.build_indices_html()
164
+ if t == "nse_open":
165
+ return live.build_index_live_html()
166
+ if t == "nse_preopen":
167
+ return pre.build_preopen_html()
168
+ if t == "nse_fno":
169
+ return fno.nse_fno_html(req.date_end, req.name)
170
+ if t == "nse_fiidii":
171
+ return ns.nse_fiidii()
172
+ if t == "nse_events":
173
+ return ns.nse_events()
174
+ if t == "nse_future":
175
+ return ns.nse_future(req.name)
176
+ if t == "nse_highlow":
177
+ return ns.nse_highlow(req.date_end)
178
+ if t == "stock_highlow":
179
+ return ns.stock_highlow(req.date_end)
180
+ if t == "nse_largedeals":
181
+ return ns.nse_largedeals()
182
+ if t == "nse_bulkdeals":
183
+ return ns.nse_bulkdeals()
184
+ if t == "nse_blockdeals":
185
+ return ns.nse_blockdeals()
186
+ if t == "nse_most_active":
187
+ return ns.nse_most_active()
188
+ if t == "index_history":
189
+ return ns.index_history("NIFTY", req.date_start, req.date_end)
190
+ if t == "largedeals_historical":
191
+ return ns.nse_largedeals_historical(req.date_start, req.date_end)
192
+ if t == "index_pe_pb_div":
193
+ return ns.index_pe_pb_div("NIFTY", req.date_start, req.date_end)
194
+ if t == "index_total_returns":
195
+ return ns.index_total_returns("NIFTY", req.date_start, req.date_end)
196
+
197
+ return common.wrap(f"<h3>Unhandled index req_type: {t}</h3>")
198
+
199
+ # -------------------------------------------------------
200
+ # SCREENER handler
201
+ # -------------------------------------------------------
202
+ def handle_screener(req: FetchRequest):
203
+ return screener.fetch_screener(req.req_type.lower())
204
+
205
+ # -------------------------------------------------------
206
+ # Main API
207
+ # -------------------------------------------------------
208
+ @app.post("/api/fetch", response_class=HTMLResponse)
209
+ def fetch_data(req: FetchRequest):
210
+ mode = req.mode.lower()
211
+
212
+ # ✅ Used by frontend on page load
213
+ if mode == "list":
214
+ return HTMLResponse(content=build_req_type_list_html())
215
+
216
+ if mode == "stock":
217
+ html = handle_stock(req)
218
+ elif mode == "index":
219
+ html = handle_index(req)
220
+ elif mode == "screener":
221
+ html = handle_screener(req)
222
+ else:
223
+ raise HTTPException(status_code=400, detail="Invalid mode")
224
+
225
+ # 🔒 Always return HTML
226
+ return HTMLResponse(content=str(html))