Skip to content

Commit c1791f1

Browse files
addedmore
1 parent 9e52ee1 commit c1791f1

20 files changed

Lines changed: 1674 additions & 207 deletions

File tree

-104 Bytes
Binary file not shown.
4.75 KB
Binary file not shown.

pythonModel/api.py

Lines changed: 48 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,49 @@
44

55
app = FastAPI()
66

7+
# @app.get("/predict")
8+
# def predict(
9+
# ticker: str = Query(..., description="Ticker symbol, e.g. 'ADANIENT.NS'"),
10+
# symbol: str = Query(..., description="Stock symbol, e.g. 'ADANIENT'"),
11+
# period: str = Query(..., description="Data period for stock, e.g. '2mo'"),
12+
# interval: str = Query(..., description="Data interval for stock, e.g. '1h'"),
13+
# days_to_fetch: int = Query(..., ge=1, description="Number of days to fetch options data"),
14+
# ):
15+
# try:
16+
# result = main_pipeline(
17+
# ticker=ticker,
18+
# symbol=symbol,
19+
# days_to_fetch=days_to_fetch,
20+
# period=period,
21+
# interval=interval
22+
# )
23+
24+
# # Handle different possible return types
25+
# if isinstance(result, dict):
26+
# return result
27+
# elif isinstance(result, str):
28+
# try:
29+
# return json.loads(result)
30+
# except json.JSONDecodeError:
31+
# return {"result": result}
32+
# elif hasattr(result, "to_dict"): # pandas DataFrame
33+
# return result.to_dict(orient="records")
34+
# else:
35+
# return {"result": str(result)}
36+
37+
# except Exception as e:
38+
# raise HTTPException(status_code=500, detail=str(e))
39+
40+
41+
42+
743
@app.get("/predict")
844
def predict(
9-
ticker: str = Query(..., description="Ticker symbol, e.g. 'ADANIENT.NS'"),
10-
symbol: str = Query(..., description="Stock symbol, e.g. 'ADANIENT'"),
11-
period: str = Query(..., description="Data period for stock, e.g. '2mo'"),
12-
interval: str = Query(..., description="Data interval for stock, e.g. '1h'"),
13-
days_to_fetch: int = Query(..., ge=1, description="Number of days to fetch options data"),
45+
ticker: str = Query(...),
46+
symbol: str = Query(...),
47+
period: str = Query(...),
48+
interval: str = Query(...),
49+
days_to_fetch: int = Query(..., ge=1),
1450
):
1551
try:
1652
result = main_pipeline(
@@ -21,21 +57,26 @@ def predict(
2157
interval=interval
2258
)
2359

24-
# Handle different possible return types
2560
if isinstance(result, dict):
2661
return result
2762
elif isinstance(result, str):
2863
try:
2964
return json.loads(result)
3065
except json.JSONDecodeError:
3166
return {"result": result}
32-
elif hasattr(result, "to_dict"): # pandas DataFrame
67+
elif hasattr(result, "to_dict"):
3368
return result.to_dict(orient="records")
3469
else:
3570
return {"result": str(result)}
3671

3772
except Exception as e:
73+
# 🔹 Print full traceback to console
74+
import traceback
75+
traceback.print_exc()
76+
# 🔹 Return the error detail in JSON
3877
raise HTTPException(status_code=500, detail=str(e))
3978

79+
80+
4081
# Run with:
4182
# uvicorn api:app --reload

pythonModel/pipline.py

Lines changed: 208 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,27 +24,36 @@ def clean_column_names(df):
2424
return df
2525

2626

27-
def fetch_stock_data(ticker, period, interval):
28-
data = yf.download(tickers=ticker, period=period, interval=interval)
29-
data = data.reset_index()
30-
if isinstance(data.columns, pd.MultiIndex):
31-
data.columns = ['_'.join(filter(None, col)).strip() for col in data.columns]
32-
data = clean_column_names(data)
33-
if 'Date' in data.columns:
34-
data.rename(columns={'Date': 'Datetime'}, inplace=True)
35-
elif 'Datetime' not in data.columns:
36-
data.rename(columns={data.columns[0]: 'Datetime'}, inplace=True)
37-
data = data.set_index('Datetime').asfreq('h')
38-
for col in ['Open', 'High', 'Low', 'Close']:
39-
if col in data.columns:
40-
data[col] = data[col].ffill()
41-
if 'Volume' in data.columns:
42-
data['Volume'] = data['Volume'].fillna(0)
43-
data.reset_index(inplace=True)
44-
return data
27+
# def fetch_stock_data(ticker, period, interval):
28+
# data = yf.download(tickers=ticker, period=period, interval=interval)
29+
# data = data.reset_index()
4530

31+
# if data.empty:
32+
# raise ValueError(f"No stock data fetched for ticker '{ticker}' with period '{period}' and interval '{interval}'")
4633

47-
def fetch_options_data(symbol, days_to_fetch):
34+
# if isinstance(data.columns, pd.MultiIndex):
35+
# data.columns = ['_'.join(filter(None, col)).strip() for col in data.columns]
36+
# data = clean_column_names(data)
37+
# if 'Date' in data.columns:
38+
# data.rename(columns={'Date': 'Datetime'}, inplace=True)
39+
# elif 'Datetime' not in data.columns:
40+
# data.rename(columns={data.columns[0]: 'Datetime'}, inplace=True)
41+
# data = data.set_index('Datetime').asfreq('h')
42+
# for col in ['Open', 'High', 'Low', 'Close']:
43+
# if col in data.columns:
44+
# data[col] = data[col].ffill()
45+
# if 'Volume' in data.columns:
46+
# data['Volume'] = data['Volume'].fillna(0)
47+
# data.reset_index(inplace=True)
48+
# return data
49+
50+
51+
52+
53+
54+
55+
56+
# def fetch_options_data(symbol, days_to_fetch):
4857
all_data = []
4958
for i in range(days_to_fetch):
5059
date = datetime.now() - timedelta(days=i)
@@ -72,11 +81,24 @@ def fetch_options_data(symbol, days_to_fetch):
7281
pass
7382
time.sleep(2)
7483
options_df = pd.DataFrame(all_data)
84+
if options_df.empty:
85+
raise ValueError(f"No options data fetched for symbol '{symbol}' in the last {days_to_fetch} days")
7586
options_df['date'] = pd.to_datetime(options_df['date'], errors='coerce')
7687
return options_df
7788

7889

79-
def clean_and_merge(stock_df, options_df):
90+
91+
92+
93+
94+
# options_df['date'] = pd.to_datetime(options_df['date'], errors='coerce')
95+
# return options_df
96+
97+
98+
99+
100+
101+
# def clean_and_merge(stock_df, options_df):
80102
if 'Datetime' not in stock_df.columns:
81103
possible = [col for col in stock_df.columns if 'datetime' in col.lower()]
82104
if possible:
@@ -118,6 +140,141 @@ def clean_and_merge(stock_df, options_df):
118140
return merged
119141

120142

143+
144+
145+
def fetch_stock_data(ticker, period, interval):
146+
import yfinance as yf
147+
import pandas as pd
148+
149+
data = yf.download(tickers=ticker, period=period, interval=interval, auto_adjust=False, progress=False)
150+
151+
# If empty, fallback to daily interval
152+
if data.empty and interval != "1d":
153+
data = yf.download(tickers=ticker, period=period, interval="1d", auto_adjust=False, progress=False)
154+
interval = "1d"
155+
156+
# If still empty, create placeholder DataFrame
157+
if data.empty:
158+
print(f"⚠️ No stock data fetched for {ticker}. Returning placeholder DataFrame.")
159+
dates = pd.date_range(end=pd.Timestamp.now(), periods=period_to_hours(period))
160+
data = pd.DataFrame({
161+
'Datetime': dates,
162+
'Open': 0, 'High': 0, 'Low': 0, 'Close': 0, 'Volume': 0
163+
})
164+
else:
165+
data = data.reset_index()
166+
if isinstance(data.columns, pd.MultiIndex):
167+
data.columns = ['_'.join(filter(None, col)).strip() for col in data.columns]
168+
if 'Date' in data.columns:
169+
data.rename(columns={'Date':'Datetime'}, inplace=True)
170+
elif 'Datetime' not in data.columns:
171+
data.rename(columns={data.columns[0]:'Datetime'}, inplace=True)
172+
data['Datetime'] = pd.to_datetime(data['Datetime'], errors='coerce')
173+
for col in ['Open','High','Low','Close','Volume']:
174+
if col in data.columns:
175+
data[col] = pd.to_numeric(data[col], errors='coerce').ffill().fillna(0)
176+
177+
return data
178+
179+
def fetch_options_data(symbol, days_to_fetch):
180+
all_data = []
181+
for i in range(days_to_fetch):
182+
date = datetime.now() - timedelta(days=i)
183+
if date.weekday() >= 5:
184+
continue
185+
try:
186+
opt_data = nse_optionchain_scrapper(symbol)
187+
records = opt_data['records']['data']
188+
for rec in records:
189+
ce = rec.get('CE', {})
190+
pe = rec.get('PE', {})
191+
all_data.append({
192+
'date': date.strftime('%Y-%m-%d'),
193+
'strikePrice': rec['strikePrice'],
194+
'CE_openInterest': ce.get('openInterest',0),
195+
'CE_changeinOpenInterest': ce.get('changeinOpenInterest',0),
196+
'CE_volume': ce.get('totalTradedVolume',0),
197+
'CE_ltp': ce.get('lastPrice',0),
198+
'PE_openInterest': pe.get('openInterest',0),
199+
'PE_changeinOpenInterest': pe.get('changeinOpenInterest',0),
200+
'PE_volume': pe.get('totalTradedVolume',0),
201+
'PE_ltp': pe.get('lastPrice',0)
202+
})
203+
except Exception:
204+
continue
205+
time.sleep(1)
206+
207+
if len(all_data) == 0:
208+
print(f"⚠️ No options data fetched for {symbol}. Returning placeholder DataFrame.")
209+
columns = ['date','strikePrice','CE_openInterest','CE_changeinOpenInterest','CE_volume','CE_ltp',
210+
'PE_openInterest','PE_changeinOpenInterest','PE_volume','PE_ltp']
211+
options_df = pd.DataFrame(columns=columns)
212+
else:
213+
options_df = pd.DataFrame(all_data)
214+
options_df['date'] = pd.to_datetime(options_df['date'], errors='coerce')
215+
216+
return options_df
217+
218+
def clean_and_merge(stock_df, options_df):
219+
# Ensure OHLC columns exist
220+
for col in ['Open','High','Low','Close','Volume']:
221+
if col not in stock_df.columns:
222+
stock_df[col] = 0
223+
224+
stock_df['Return'] = stock_df['Close'].pct_change().fillna(0)
225+
stock_df['MA_5'] = stock_df['Close'].rolling(5).mean().fillna(method='bfill')
226+
stock_df['MA_10'] = stock_df['Close'].rolling(10).mean().fillna(method='bfill')
227+
stock_df['Volatility'] = stock_df['Return'].rolling(5).std().fillna(0)
228+
229+
# Clean options
230+
for col in ['CE_openInterest','PE_openInterest','CE_changeinOpenInterest','PE_changeinOpenInterest','CE_volume','PE_volume']:
231+
if col not in options_df.columns:
232+
options_df[col] = 0
233+
else:
234+
options_df[col] = pd.to_numeric(options_df[col], errors='coerce').fillna(0)
235+
236+
if not options_df.empty:
237+
options_agg = options_df.groupby('date').agg({
238+
'CE_openInterest':'sum','PE_openInterest':'sum',
239+
'CE_changeinOpenInterest':'sum','PE_changeinOpenInterest':'sum',
240+
'CE_volume':'sum','PE_volume':'sum'
241+
}).reset_index()
242+
options_agg['PCR'] = options_agg['PE_openInterest'] / (options_agg['CE_openInterest'] + 1e-6)
243+
stock_df['date'] = stock_df['Datetime'].dt.date
244+
options_agg['date_only'] = options_agg['date'].dt.date
245+
merged = pd.merge(stock_df, options_agg, left_on='date', right_on='date_only', how='left').fillna(0)
246+
else:
247+
merged = stock_df.copy()
248+
merged['CE_openInterest'] = 0
249+
merged['PE_openInterest'] = 0
250+
merged['CE_changeinOpenInterest'] = 0
251+
merged['PE_changeinOpenInterest'] = 0
252+
merged['CE_volume'] = 0
253+
merged['PE_volume'] = 0
254+
merged['PCR'] = 0
255+
256+
merged['hour'] = merged['Datetime'].dt.hour
257+
merged['day'] = merged['Datetime'].dt.day
258+
merged['weekday'] = merged['Datetime'].dt.weekday
259+
260+
return merged
261+
262+
def period_to_hours(period_str):
263+
# Convert period like '1mo', '2mo' to approximate hours for placeholder
264+
unit = period_str[-1]
265+
num = int(period_str[:-1])
266+
if unit == 'd':
267+
return num * 1
268+
if unit == 'mo':
269+
return num * 30
270+
if unit == 'y':
271+
return num * 365
272+
return num
273+
274+
275+
276+
277+
121278
def train_and_predict(merged_df, sequence_length=10, epochs=30, use_transfer_learning=True):
122279
"""
123280
Train LSTM model with optional transfer learning.
@@ -146,6 +303,11 @@ def train_and_predict(merged_df, sequence_length=10, epochs=30, use_transfer_lea
146303
X_scaled = scaler_X.fit_transform(X)
147304
y_scaled = scaler_y.fit_transform(y)
148305

306+
if len(X_scaled) <= sequence_length:
307+
raise ValueError(
308+
f"Not enough data to create sequences. Got {len(X_scaled)} rows, sequence_length={sequence_length}. "
309+
f"Try using a longer period or a lower interval (e.g., 1d instead of 1h)."
310+
)
149311
X_seq, y_seq = [], []
150312
for i in range(len(X_scaled) - sequence_length):
151313
X_seq.append(X_scaled[i:i+sequence_length])
@@ -252,15 +414,41 @@ def summarize_predictions(pred_df):
252414
return summary_features
253415

254416

417+
# def main_pipeline(ticker, symbol, period, interval, days_to_fetch):
418+
# stock_df = fetch_stock_data(ticker=ticker, period=period, interval=interval)
419+
# options_df = fetch_options_data(symbol=symbol, days_to_fetch=days_to_fetch)
420+
# merged_df = clean_and_merge(stock_df, options_df)
421+
# pred_df = train_and_predict(merged_df)
422+
# summary_dict = summarize_predictions(pred_df)
423+
# return json.dumps(summary_dict, indent=4)
424+
425+
426+
255427
def main_pipeline(ticker, symbol, period, interval, days_to_fetch):
428+
# 1️⃣ Check if ticker is valid
429+
try:
430+
info = yf.Ticker(ticker).info
431+
if 'regularMarketPrice' not in info:
432+
raise ValueError(f"Ticker {ticker} seems invalid or data unavailable")
433+
except Exception as e:
434+
raise ValueError(f"Failed to fetch ticker info: {e}")
435+
436+
# 2️⃣ Fetch stock and options data
256437
stock_df = fetch_stock_data(ticker=ticker, period=period, interval=interval)
257438
options_df = fetch_options_data(symbol=symbol, days_to_fetch=days_to_fetch)
439+
440+
# 3️⃣ Merge and clean
258441
merged_df = clean_and_merge(stock_df, options_df)
442+
443+
# 4️⃣ Train LSTM and predict
259444
pred_df = train_and_predict(merged_df)
445+
446+
# 5️⃣ Summarize predictions
260447
summary_dict = summarize_predictions(pred_df)
261448
return json.dumps(summary_dict, indent=4)
262449

263450

451+
264452
if __name__ == "__main__":
265453
import sys
266454

tradefront/app/api/freechats/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export async function POST(req:NextRequest,res:NextResponse) {
2929
const user = await Users.findOne({email:decoded.email}).exec();
3030

3131

32-
return NextResponse.json({chats:user.freechats},{ status: 200 })
32+
return NextResponse.json({chats:user.freechats,paidacc:user.paidacc},{ status: 200 })
3333

3434
} catch (e) {
3535
console.error(e);

0 commit comments

Comments
 (0)