Spaces:
Running
Running
import requests | |
import yfinance as yf | |
import pandas as pd | |
from datetime import datetime, timedelta | |
from typing import List, Dict, Any, Optional, Tuple | |
from app.config import settings | |
from app.models.fund_models import FundMeta, NAVData, FundNAVResponse, MarketIndex, MarketIndicesResponse | |
class MutualFundDataFetcher: | |
"""Fetch mutual fund data from MFAPI.in and Yahoo Finance for indices""" | |
def __init__(self): | |
self.mfapi_base = settings.MFAPI_BASE_URL | |
def get_all_schemes(self) -> List[Dict[str, Any]]: | |
"""Fetch all mutual fund schemes""" | |
try: | |
response = requests.get(self.mfapi_base) | |
if response.status_code == 200: | |
return response.json() | |
else: | |
return [] | |
except Exception as e: | |
print(f"Error fetching schemes: {e}") | |
return [] | |
def get_fund_nav_history(self, scheme_code: str) -> Tuple[pd.DataFrame, FundMeta]: | |
"""Fetch NAV history for a specific scheme""" | |
try: | |
url = f"{self.mfapi_base}/{scheme_code}" | |
response = requests.get(url) | |
if response.status_code == 200: | |
data = response.json() | |
nav_data = data.get('data', []) | |
# Convert to DataFrame | |
df = pd.DataFrame(nav_data) | |
if not df.empty: | |
df['date'] = pd.to_datetime(df['date'], format='%d-%m-%Y') | |
df['nav'] = pd.to_numeric(df['nav']) | |
df = df.sort_values('date') | |
# Create FundMeta object | |
meta_data = data.get('meta', {}) | |
fund_meta = FundMeta( | |
fund_house=meta_data.get('fund_house'), | |
scheme_type=meta_data.get('scheme_type'), | |
scheme_category=meta_data.get('scheme_category'), | |
scheme_code=str(meta_data.get('scheme_code', scheme_code)) | |
) | |
return df, fund_meta | |
else: | |
return pd.DataFrame(), FundMeta() | |
except Exception as e: | |
print(f"Error fetching NAV data: {e}") | |
return pd.DataFrame(), FundMeta() | |
def get_market_indices(self) -> MarketIndicesResponse: | |
"""Fetch Indian market indices using Yahoo Finance""" | |
indices = { | |
'^NSEI': 'Nifty 50', | |
'^BSESN': 'BSE Sensex', | |
'^NSEBANK': 'Nifty Bank', | |
'^CNXIT': 'Nifty IT', | |
'^NSEMDCP50': 'Nifty Midcap 50', | |
'NIFTYSMLCAP50.NS': 'Nifty Smallcap 50', | |
'^CNXPHARMA': 'Nifty Pharma', | |
'^CNXAUTO': 'Nifty Auto', | |
'^CNXFMCG': 'Nifty FMCG', | |
'^CNXENERGY': 'Nifty Energy', | |
'^CNXREALTY': 'Nifty Realty', | |
'^NSMIDCP': 'Nifty Next 50', | |
} | |
indices_data = [] | |
for symbol, name in indices.items(): | |
try: | |
ticker = yf.Ticker(symbol) | |
hist = ticker.history(period="5d") | |
if not hist.empty: | |
current_price = hist['Close'].iloc[-1] | |
previous_close = hist['Close'].iloc[-2] if len(hist) > 1 else current_price | |
change = current_price - previous_close | |
change_pct = (change / previous_close) * 100 | |
indices_data.append(MarketIndex( | |
name=name, | |
symbol=symbol, | |
current_price=current_price, | |
change=change, | |
change_pct=change_pct | |
)) | |
except Exception as e: | |
print(f"Could not fetch {name}: {e}") | |
return MarketIndicesResponse( | |
indices=indices_data, | |
last_updated=datetime.now() | |
) |