File size: 8,634 Bytes
53072ae
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
# services/analyzer.py
import numpy as np
import pandas as pd
from typing import Dict, Any, Optional
from services.economic_data import EconomicDataFetcher
from models.analysis import StockAnalysisResponse, InvestmentRecommendationResponse
from models.market_data import StockDataResponse

class IndianFinancialAnalyzer:
    """Analyze Indian market financial data"""

    def __init__(self):
        self.economic_data_fetcher = EconomicDataFetcher()
        self.rbi_repo_rate = self.economic_data_fetcher.get_rbi_repo_rate()
        self.indian_inflation_rate = self.economic_data_fetcher.get_indian_inflation_rate()

    def analyze_indian_stock(self, stock_data: StockDataResponse, company_name: str) -> StockAnalysisResponse:
        """Comprehensive analysis of Indian stock"""
        # Convert history dict back to DataFrame for analysis (basic reconstruction)
        # This assumes the dict keys are column names and values are lists of values
        try:
            hist_df = pd.DataFrame(stock_data.history)
            if 'Date' in hist_df.columns:
                 hist_df['Date'] = pd.to_datetime(hist_df['Date'])
                 hist_df.set_index('Date', inplace=True)
        except Exception as e:
             print(f"Error reconstructing DataFrame for analysis: {e}")
             hist_df = pd.DataFrame() # Return empty DataFrame on error

        if hist_df.empty:
            analysis_text = "No data available for analysis"
        else:
            # Current metrics
            current_price = hist_df['Close'].iloc[-1]
            year_high = hist_df['High'].max()
            year_low = hist_df['Low'].min()

            # Calculate returns
            returns_1m = ((current_price - hist_df['Close'].iloc[-21]) / hist_df['Close'].iloc[-21]) * 100 if len(hist_df) >= 21 else 0
            returns_3m = ((current_price - hist_df['Close'].iloc[-63]) / hist_df['Close'].iloc[-63]) * 100 if len(hist_df) >= 63 else 0
            returns_1y = ((current_price - hist_df['Close'].iloc[0]) / hist_df['Close'].iloc[0]) * 100

            # Volatility (standard deviation of daily returns)
            daily_returns = hist_df['Close'].pct_change().dropna()
            volatility = daily_returns.std() * np.sqrt(252) * 100  # Annualized volatility

            # Technical indicators
            sma_20 = hist_df['Close'].rolling(20).mean().iloc[-1] if len(hist_df) >= 20 else np.nan
            sma_50 = hist_df['Close'].rolling(50).mean().iloc[-1] if len(hist_df) >= 50 else np.nan
            ema_20 = hist_df['Close'].ewm(span=20, adjust=False).mean().iloc[-1] if len(hist_df) >= 20 else np.nan
            ema_50 = hist_df['Close'].ewm(span=50, adjust=False).mean().iloc[-1] if len(hist_df) >= 50 else np.nan
            rsi = hist_df['Close'].diff().ewm(span=14, adjust=False).mean() / hist_df['Close'].diff().ewm(span=14, adjust=False).std()
            macd = hist_df['Close'].ewm(span=12, adjust=False).mean() - hist_df['Close'].ewm(span=26, adjust=False).mean()
            macd_signal = macd.ewm(span=9, adjust=False).mean()
            macd_hist = macd - macd_signal
            macd_cross = 'Bullish' if macd.iloc[-1] > macd_signal.iloc[-1] else 'Bearish'
            stochastic_k = ((hist_df['Close'].iloc[-1] - hist_df['Low'].rolling(14).min().iloc[-1]) /
                            (hist_df['High'].rolling(14).max().iloc[-1] - hist_df['Low'].rolling(14).min().iloc[-1]) * 100) if len(hist_df) >= 14 else np.nan
            stochastic_d = pd.Series(stochastic_k).rolling(3).mean().iloc[-1] if not pd.isna(stochastic_k) else np.nan
            stochastic_cross = 'Bullish' if stochastic_k > stochastic_d else 'Bearish'
            atr = hist_df['High'].combine(hist_df['Low'], max) - hist_df['Low'].combine(hist_df['Close'].shift(), min)
            atr = atr.rolling(14).mean().iloc[-1] if len(hist_df) >= 14 else np.nan
            obv = (np.sign(hist_df['Close'].diff()) * hist_df['Volume']).fillna(0).cumsum().iloc[-1]
            mfi = 100 - (100 / (1 + (hist_df['Close'].diff().fillna(0) * hist_df['Volume']).rolling(14).sum() /
                                (-hist_df['Close'].diff().fillna(0) * hist_df['Volume']).rolling(14).sum())).iloc[-1] if len(hist_df) >= 14 else np.nan
            adx = pd.Series(np.abs(hist_df['High'].diff()) - np.abs(hist_df['Low'].diff())).rolling(14).mean().iloc[-1] if len(hist_df) >= 14 else np.nan
            

            # Determine trend
            if pd.notna(current_price) and pd.notna(sma_20) and pd.notna(sma_50):
                if current_price > sma_20 > sma_50:
                    trend = 'Bullish'
                elif current_price < sma_20 < sma_50:
                    trend = 'Bearish'
                else:
                    trend = 'Neutral'
            else:
                trend = 'Insufficient Data'

            # Indian market specific analysis
            analysis = f"""
## Indian Market Analysis for {company_name}

### Current Market Position
- **Current Price**: ₹{current_price:.2f}
- **52-Week High**: ₹{year_high:.2f}
- **52-Week Low**: ₹{year_low:.2f}
- **Distance from High**: {((current_price - year_high) / year_high * 100):.1f}%

### Returns Performance
- **1 Month Return**: {returns_1m:.2f}%
- **3 Month Return**: {returns_3m:.2f}%
- **1 Year Return**: {returns_1y:.2f}%
- **Annualized Volatility**: {volatility:.2f}%

### Technical Analysis
- **20-Day SMA**: ₹{sma_20:.2f}
- **50-Day SMA**: ₹{sma_50:.2f}
- **20-Day EMA**: ₹{ema_20:.2f}
- **50-Day EMA**: ₹{ema_50:.2f}
- **RSI (14-day)**: {rsi.iloc[-1]:.2f}'
- **MACD**: {macd.iloc[-1]:.2f} ({macd_cross})
- **MACD HIST**: {macd_hist.iloc[-1]:.2f}
- **Stochastic %K**: {stochastic_k:.2f} ({stochastic_cross})
- **ATR (14-day)**: ₹{atr:.2f}'
- **OBV**: {obv:.2f}
- **MFI (14-day)**: {mfi:.2f}'
- **ADX (14-day)**: {adx:.2f}'
- **Trend**: {trend}

### Indian Market Context
- **Relative to RBI Repo Rate ({self.rbi_repo_rate}%)**: {'Attractive' if returns_1y > self.rbi_repo_rate else 'Underperforming'}
- **Inflation Adjusted Return**: {returns_1y - self.indian_inflation_rate:.2f}%

### Key Company Metrics
            """

            # Add company-specific info if available
            info = stock_data.info
            if info:
                market_cap = info.get('marketCap', 'N/A')
                pe_ratio = info.get('forwardPE', info.get('trailingPE', 'N/A'))
                dividend_yield = info.get('dividendYield', 0) * 100 if info.get('dividendYield') else 'N/A'

                market_cap_str = f"₹{market_cap/10000000:.0f} Cr." if isinstance(market_cap, (int, float)) else market_cap
                pe_str = f"{pe_ratio:.2f}" if isinstance(pe_ratio, (int, float)) else 'N/A'
                div_yield_str = f"{dividend_yield:.2f}%" if isinstance(dividend_yield, (int, float)) else 'N/A'

                analysis += f"""
- **Market Cap**: {market_cap_str}
- **P/E Ratio**: {pe_str}
- **Dividend Yield**: {div_yield_str}
                """
            analysis_text = analysis

        return StockAnalysisResponse(basic_analysis=analysis_text)

    def generate_investment_recommendation(self) -> InvestmentRecommendationResponse:
        """Generate investment recommendation based on Indian market conditions"""

        recommendation = f"""
## 📊 Investment Recommendation (Indian Market Context)

### Risk Assessment
- **Market Risk**: Indian equity markets are subject to high volatility
- **Currency Risk**: INR fluctuations affect returns for foreign investors
- **Regulatory Risk**: SEBI regulations and policy changes impact

### Recommendation Framework
Based on current Indian market conditions:

1. **Conservative Investors**: Consider Large Cap stocks with dividend yield
2. **Moderate Risk**: Mid Cap stocks with strong fundamentals
3. **Aggressive**: Small Cap and sector-specific opportunities

### Indian Market Specific Factors
- **Monsoon Impact**: Agricultural and rural demand dependency
- **Festival Season**: Seasonal consumption patterns
- **Government Policy**: Budget announcements and reforms
- **FII/DII Flows**: Foreign and domestic institutional investor sentiment

### Economic Context
- **RBI Repo Rate**: {self.rbi_repo_rate}%
- **Inflation Rate**: {self.indian_inflation_rate}%

### Tax Implications (Indian Investors)
- **Short Term Capital Gains**: 15% (< 1 year)
- **Long Term Capital Gains**: 10% on gains > ₹1 Lakh (> 1 year)
- **Dividend Tax**: TDS as per income tax slab

**Disclaimer**: This is for educational purposes only. Please consult a SEBI registered investment advisor.
        """

        return InvestmentRecommendationResponse(recommendation=recommendation)