jarvisx17 commited on
Commit
81eeead
1 Parent(s): 705f945

Create utils.py

Browse files
Files changed (1) hide show
  1. utils.py +222 -0
utils.py ADDED
@@ -0,0 +1,222 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import pandas as pd
3
+ import datetime
4
+ import pytz
5
+ import numpy as np
6
+ import math
7
+ import ta
8
+
9
+ class StockDataFetcher:
10
+ def __init__(self):
11
+
12
+ self.base_url = "https://groww.in/v1/api/charting_service/v3/chart/exchange/NSE/segment/CASH/"
13
+ self.base_fno_url = "https://groww.in/v1/api/stocks_fo_data/v3/charting_service/chart/exchange/NSE/segment/FNO/"
14
+ self.latest_stock_price = "https://groww.in/v1/api/stocks_data/v1/tr_live_prices/exchange/NSE/segment/CASH/"
15
+ self.latest_option_price = "https://groww.in/v1/api/stocks_fo_data/v1/tr_live_prices/exchange/NSE/segment/FNO/"
16
+ self.option_chain = "https://groww.in/v1/api/option_chain_service/v1/option_chain/derivatives/"
17
+ self.search_url = "https://groww.in/v1/api/search/v1/entity"
18
+ self.news_url = "https://groww.in/v1/api/stocks_company_master/v1/company_news/groww_contract_id/"
19
+ self.all_stocks_url = "https://groww.in/v1/api/stocks_data/v1/all_stocks"
20
+
21
+ self.indian_timezone = pytz.timezone('Asia/Kolkata')
22
+ self.utc_timezone = pytz.timezone('UTC')
23
+ self.headers = {
24
+ 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36 Edg/119.0.0.0'
25
+ }
26
+
27
+ def _get_time_range(self, days=7):
28
+ current_time = datetime.datetime.now(self.indian_timezone)
29
+ start_time = current_time - datetime.timedelta(days=days)
30
+ start_time_utc = start_time.astimezone(pytz.utc)
31
+ current_time_utc = current_time.astimezone(pytz.utc)
32
+ start_time_millis = int(start_time_utc.timestamp() * 1000)
33
+ end_time_millis = int(current_time_utc.timestamp() * 1000)
34
+ return start_time_millis, end_time_millis
35
+
36
+ def fetch_stock_data(self, symbol, interval=15, days=7):
37
+ start_time, end_time = self._get_time_range(days)
38
+ params = {
39
+ 'endTimeInMillis': end_time,
40
+ 'intervalInMinutes': interval,
41
+ 'startTimeInMillis': start_time,
42
+ }
43
+ try:
44
+ print("Downloading data of", symbol.upper())
45
+ if symbol[-2:].upper() == "PE" or symbol[-2:].upper() == "CE" or symbol[-3:].upper() == "FUT":
46
+ response = requests.get(self.base_fno_url + symbol.upper(), params=params, headers=self.headers)
47
+ else:
48
+ response = requests.get(self.base_url + symbol.upper(), params=params, headers=self.headers)
49
+ response.raise_for_status()
50
+ data = response.json()
51
+ columns = ['Date', 'Open', 'High', 'Low', 'Close', 'Volume']
52
+ for row in data['candles']:
53
+ row[0] = datetime.datetime.utcfromtimestamp(row[0])
54
+ df = pd.DataFrame(data['candles'], columns=columns)
55
+ df['Date'] = pd.to_datetime(df['Date'])
56
+ df['Date'] = df['Date'].dt.tz_localize(self.utc_timezone).dt.tz_convert(self.indian_timezone)
57
+ return df
58
+ except requests.exceptions.RequestException as e:
59
+ print(f"Error during API request: {e}")
60
+ return None
61
+
62
+ def fetch_latest_price(self, symbol):
63
+ try:
64
+ if symbol[-2:].upper() == "PE" or symbol[-2:].upper() == "CE" or symbol[-3:].upper() == "FUT":
65
+ response = requests.get(self.latest_option_price + symbol.upper() + "/latest", headers=self.headers)
66
+ else:
67
+ response = requests.get(self.latest_stock_price + symbol.upper() + "/latest", headers=self.headers)
68
+ if response.status_code == 200:
69
+ data = response.json()
70
+ latest_price = data.get('ltp')
71
+ print(symbol, 'Price: ', latest_price)
72
+ return latest_price
73
+ else:
74
+ print(f"Failed to fetch data. Status code: {response.status_code}")
75
+ return None
76
+ except Exception as e:
77
+ print(f"An error occurred: {e}")
78
+ return None
79
+
80
+ def fetch_option_chain(self, symbol):
81
+ response = requests.get(self.option_chain + symbol, headers=self.headers)
82
+ data = response.json()['optionChain']['optionChains']
83
+ ltp = response.json()['livePrice']['value']
84
+
85
+ chain = []
86
+ for i in range(len(data)):
87
+ chain.append({"Symbol_CE": data[i]["callOption"]['growwContractId'], "OI_CALL": data[i]["callOption"]['openInterest'] , "CALL": data[i]["callOption"]['ltp'], "strikePrice": data[i]['strikePrice']/100, "PUT": data[i]["putOption"]['ltp'], "OI_PUT": data[i]["putOption"]['openInterest'], "Symbol_PE": data[i]["putOption"]['growwContractId']}
88
+ )
89
+
90
+ chain = pd.DataFrame(chain)
91
+ index = chain[(chain['strikePrice'] >= ltp)].head(1).index[0]
92
+ print(response.json()['livePrice'])
93
+ chain = chain[index-6:index+7].reset_index(drop=True)
94
+ optin_exp = chain['Symbol_CE'][0][:-7]
95
+ return chain, optin_exp
96
+
97
+ def search_entity(self, symbol, entity=None, page=0, size=1, app=False):
98
+ params = {
99
+ 'app': app,
100
+ 'entity_type': entity,
101
+ 'page': page,
102
+ 'q': f"{symbol}",
103
+ 'size': size
104
+ }
105
+ try:
106
+ response = requests.get(self.search_url, params=params, headers=self.headers)
107
+ response.raise_for_status()
108
+ data = response.json()
109
+ entity = data['content'][0]
110
+ return {"ID": entity['id'], "title": entity['title'], "NSE_Symbol": entity['nse_scrip_code'], "contract_id" : entity["groww_contract_id"]}
111
+ except requests.exceptions.RequestException as e:
112
+ print(f"Error during API request: {e}")
113
+ return None
114
+
115
+ def fetch_stock_news(self, symbol, page=1, size=1):
116
+ params = {
117
+ "page" : page,
118
+ "size" : size
119
+ }
120
+ try:
121
+ symbol_id = self.search_entity(symbol.upper())['contract_id']
122
+ response = requests.get(self.news_url + symbol_id, headers=self.headers, params=params).json()['results']
123
+ print(response)
124
+ news = []
125
+ for i in range(len(response)):
126
+ Title = response[i]['title']
127
+ Summary = response[i]['summary']
128
+ Url = response[i]['url']
129
+ Date = response[i]['pubDate']
130
+ Source = response[i]['source']
131
+ CompanyName = response[i]['companies'][0]['companyName']
132
+ ScripCode = response[i]['companies'][0]['nseScripCode']
133
+ BlogUrl = response[i]['companies'][0]['blogUrl']
134
+ Topics = response[i]['topics'][0]
135
+
136
+ news.append({
137
+ 'title': Title,
138
+ 'summary': Summary,
139
+ 'url': Url,
140
+ 'pubDate': Date,
141
+ 'source': Source,
142
+ 'companyName': CompanyName,
143
+ 'symbol': ScripCode,
144
+ 'blogUrl': BlogUrl,
145
+ 'topics': Topics
146
+ })
147
+
148
+ news_table = pd.DataFrame(news)
149
+ return news_table
150
+ except:
151
+ print("Something went wrong")
152
+ return None
153
+
154
+ def fetch_all_stock(self):
155
+ try:
156
+ params = {
157
+ 'listFilters': {'INDUSTRY': [], 'INDEX': []},
158
+ 'INDEX': ["BSE 100", "Nifty 100", "Nifty Bank", "Nifty Next 50", "Nifty Midcap 100", "SENSEX", "Nifty 50"],
159
+ 'INDUSTRY': [],
160
+ 'objFilters': {'CLOSE_PRICE': {'max': 100000, 'min': 0}, 'MARKET_CAP': {'min': 0, 'max': 2000000000000000}},
161
+ 'CLOSE_PRICE': {'max': 100000, 'min': 0},
162
+ 'MARKET_CAP': {'min': 0, 'max': 2000000000000000},
163
+ 'size': "1000",
164
+ 'sortBy': "NA",
165
+ 'sortType': "ASC"
166
+ }
167
+
168
+ all_data = []
169
+ page = 0
170
+ while True:
171
+ params['page'] = str(page)
172
+ response = requests.post(self.all_stocks_url, headers=self.headers, json=params)
173
+ data = response.json()
174
+ records = data.get('records', [])
175
+ if not records:
176
+ break
177
+ all_data.extend(records)
178
+ page += 1
179
+
180
+ df = pd.DataFrame(all_data)
181
+ live_price_df = pd.json_normalize(df['livePriceDto'])
182
+ df = pd.concat([df, live_price_df], axis=1)
183
+ df = df.drop(columns=['livePriceDto'])
184
+ return df
185
+ except:
186
+ return None
187
+
188
+ def realtime_signal(self, symbol, intervals=15, days=10):
189
+
190
+ rounding_value=None
191
+
192
+ if symbol.upper() == "NIFTY":
193
+ index_symbol = "NIFTY"
194
+ rounding_value = 50
195
+
196
+ elif symbol.upper() == "NIFTY-BANK":
197
+ index_symbol = "BANKNIFTY"
198
+ rounding_value = 100
199
+
200
+ else:
201
+ pass
202
+
203
+ stock_data = self.fetch_stock_data(index_symbol, intervals, days)
204
+ chain, exp = self.fetch_option_chain(symbol.upper())
205
+ stock_data['RSI'] = ta.momentum.rsi(stock_data['Close'], window=14)
206
+ stock_data = stock_data.drop(columns=['Volume'])
207
+ stock_data['Prev_RSI'] = stock_data['RSI'].shift(1)
208
+ stock_data['Signal'] = 0
209
+ call_condition = (stock_data['RSI'] > 60) & (stock_data['Prev_RSI'] < 60)
210
+ put_condition = (stock_data['RSI'] < 40) & (stock_data['Prev_RSI'] > 40)
211
+ stock_data.loc[call_condition, 'Signal'] = 1
212
+ stock_data.loc[put_condition, 'Signal'] = 2
213
+ stock_data = stock_data.dropna().reset_index(drop=True)
214
+
215
+ def floor_to_nearest(value, nearest):
216
+ return math.ceil(value / nearest) * nearest
217
+
218
+ stock_data['Option'] = stock_data['Close'].apply(lambda x: floor_to_nearest(x, rounding_value))
219
+
220
+ stock_data['direction'] = np.where(stock_data['Signal'] == 2, "PE", np.where(stock_data['Signal'] == 1, "CE", ""))
221
+ stock_data['symbol'] = exp + stock_data['Option'].astype(str) + stock_data['direction']
222
+ return stock_data