lucifer7210's picture
Upload 21 files
eb606e1 verified
from fastapi import APIRouter, Depends, HTTPException, Query
from typing import List, Dict, Any, Optional
from app.services.data_fetcher import MutualFundDataFetcher
from app.services.sip_calculator import SIPCalculator
from app.models.fund_models import (
FundNAVResponse, FundAnalysisRequest, FundAnalysisResponse
)
from app.models.goal_models import (
SIPCalculationRequest, SIPCalculationResponse,
RequiredSIPRequest, RequiredSIPResponse
)
# Popular mutual fund categories with scheme codes
POPULAR_FUNDS = {
'Large Cap Equity': {
'HDFC Top 100 Fund': '120503',
'ICICI Pru Bluechip Fund': '120505',
'SBI Bluechip Fund': '125497',
'Axis Bluechip Fund': '120503',
'Kotak Bluechip Fund': '118989'
},
'Mid Cap Equity': {
'HDFC Mid-Cap Opportunities Fund': '118551',
'ICICI Pru Mid Cap Fund': '120544',
'Kotak Emerging Equity Fund': '118999',
'SBI Magnum Mid Cap Fund': '100281',
'DSP Mid Cap Fund': '112618'
},
'Small Cap Equity': {
'SBI Small Cap Fund': '122639',
'DSP Small Cap Fund': '112618',
'HDFC Small Cap Fund': '118551',
'Axis Small Cap Fund': '125487',
'Kotak Small Cap Fund': '119028'
},
'ELSS (Tax Saving)': {
'Axis Long Term Equity Fund': '125494',
'HDFC Tax Saver': '100277',
'SBI Tax Saver': '125497',
'ICICI Pru ELSS Tax Saver': '120503',
'Kotak Tax Saver': '118989'
},
'Debt Funds': {
'HDFC Corporate Bond Fund': '101762',
'ICICI Pru Corporate Bond Fund': '120503',
'SBI Corporate Bond Fund': '125497',
'Kotak Corporate Bond Fund': '118989',
'Axis Corporate Debt Fund': '125494'
},
'Hybrid Funds': {
'HDFC Hybrid Equity Fund': '118551',
'ICICI Pru Balanced Advantage Fund': '120505',
'SBI Equity Hybrid Fund': '125497',
'Kotak Equity Hybrid Fund': '118999',
'Axis Hybrid Fund': '125494'
}
}
router = APIRouter()
@router.get("/schemes")
async def get_all_schemes():
"""
Get all available mutual fund schemes
"""
try:
fetcher = MutualFundDataFetcher()
schemes = fetcher.get_all_schemes()
return {"schemes": schemes}
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error fetching schemes: {str(e)}")
@router.get("/nav/{scheme_code}", response_model=FundNAVResponse)
async def get_fund_nav_history(scheme_code: str):
"""
Get NAV history for a specific mutual fund scheme
"""
try:
fetcher = MutualFundDataFetcher()
nav_data, fund_meta = fetcher.get_fund_nav_history(scheme_code)
return FundNAVResponse(
meta=fund_meta,
data=nav_data.to_dict('records')
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error fetching NAV data: {str(e)}")
@router.get("/popular")
async def get_popular_funds():
"""
Get list of popular mutual funds by category
"""
return POPULAR_FUNDS
@router.post("/sip-calculate", response_model=SIPCalculationResponse)
async def calculate_sip(request: SIPCalculationRequest,
include_yearly_breakdown: bool = Query(False, description="Include yearly breakdown in response")):
"""
Calculate SIP maturity amount based on monthly investment, expected return, and time period
"""
try:
calculator = SIPCalculator()
result = calculator.get_sip_calculation(request, include_yearly_breakdown)
return result
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error calculating SIP: {str(e)}")
@router.post("/required-sip", response_model=RequiredSIPResponse)
async def calculate_required_sip(request: RequiredSIPRequest):
"""
Calculate required SIP amount to reach a target amount
"""
try:
calculator = SIPCalculator()
result = calculator.get_required_sip(request)
return result
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error calculating required SIP: {str(e)}")
@router.post("/analyze", response_model=FundAnalysisResponse)
async def analyze_funds(request: FundAnalysisRequest):
"""
Analyze performance of selected mutual funds over a specified period
"""
try:
fetcher = MutualFundDataFetcher()
calculator = SIPCalculator()
analysis_results = []
for fund_name in request.fund_names:
# Find scheme code for the fund
scheme_code = None
fund_category = None
for category, funds in POPULAR_FUNDS.items():
if fund_name in funds:
scheme_code = funds[fund_name]
fund_category = category
break
if not scheme_code:
continue
# Fetch NAV data
nav_data, fund_meta = fetcher.get_fund_nav_history(scheme_code)
if not nav_data.empty:
returns_data = calculator.calculate_fund_returns(
nav_data, request.investment_amount, request.start_date, request.end_date
)
if returns_data:
analysis_results.append({
'fund_name': fund_name,
'category': fund_category,
'scheme_code': scheme_code,
'fund_house': fund_meta.fund_house,
'returns_data': returns_data,
'nav_data': nav_data.to_dict('records'),
'fund_meta': fund_meta.dict()
})
# Prepare comparison data
comparison_data = []
for result in analysis_results:
returns = result['returns_data']
comparison_data.append({
'Fund Name': result['fund_name'],
'Category': result['category'],
'Fund House': result['fund_house'],
'Investment': f"₹{returns['investment_amount']:,.0f}",
'Current Value': f"₹{returns['final_value']:,.0f}",
'Total Return': f"{returns['total_return']:.2f}%",
'Absolute Gain': f"₹{returns['final_value'] - returns['investment_amount']:,.0f}"
})
return FundAnalysisResponse(
results=analysis_results,
comparison_data=comparison_data
)
except Exception as e:
raise HTTPException(status_code=500, detail=f"Error analyzing funds: {str(e)}")