pranit144 commited on
Commit
04a8c30
·
verified ·
1 Parent(s): b471d50

Update src/app.py

Browse files
Files changed (1) hide show
  1. src/app.py +563 -0
src/app.py CHANGED
@@ -0,0 +1,563 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import pandas as pd
3
+ import numpy as np
4
+ import matplotlib.pyplot as plt
5
+ import datetime
6
+ from dateutil.relativedelta import relativedelta
7
+ import plotly.express as px
8
+ import plotly.graph_objects as go
9
+ import plotly.figure_factory as ff
10
+ from plotly.subplots import make_subplots
11
+ import yfinance as yf
12
+ import seaborn as sns
13
+ from scipy import stats
14
+ from typing import Dict, Optional, List
15
+ import warnings
16
+ warnings.filterwarnings('ignore')
17
+
18
+ # Try importing mftool, handle if not available
19
+ try:
20
+ from mftool import Mftool
21
+
22
+ mftool_available = True
23
+ except ImportError:
24
+ mftool_available = False
25
+
26
+ try:
27
+ from yahooquery import Ticker
28
+
29
+ yahooquery_available = True
30
+ except ImportError:
31
+ yahooquery_available = False
32
+
33
+ # Set page configuration
34
+ st.set_page_config(
35
+ page_title="Mutual Fund Analytics Suite",
36
+ page_icon="📈",
37
+ layout="wide",
38
+ initial_sidebar_state="expanded"
39
+ )
40
+
41
+ # Custom CSS styling
42
+ st.markdown("""
43
+ <style>
44
+ .main {
45
+ padding: 2rem;
46
+ }
47
+ .stButton>button {
48
+ width: 100%;
49
+ background-color: #1f77b4;
50
+ color: white;
51
+ }
52
+ .reportview-container .main .block-container {
53
+ padding-top: 2rem;
54
+ }
55
+ h1 {
56
+ color: #1f77b4;
57
+ }
58
+ .stMetric {
59
+ background-color: #f8f9fa;
60
+ padding: 1rem;
61
+ border-radius: 5px;
62
+ box-shadow: 0 2px 4px rgba(0,0,0,0.1);
63
+ }
64
+ .stAlert {
65
+ padding: 1rem;
66
+ margin: 1rem 0;
67
+ border-radius: 0.5rem;
68
+ }
69
+ </style>
70
+ """, unsafe_allow_html=True)
71
+
72
+ # Cache data fetching functions
73
+ @st.cache_data(ttl=3600)
74
+ def fetch_mutual_fund_data(mutual_fund_code: str) -> Optional[pd.DataFrame]:
75
+ """Fetch mutual fund data from mftool."""
76
+ try:
77
+ mf = Mftool()
78
+ df = (mf.get_scheme_historical_nav(mutual_fund_code, as_Dataframe=True)
79
+ .reset_index()
80
+ .assign(nav=lambda x: x['nav'].astype(float),
81
+ date=lambda x: pd.to_datetime(x['date'], format='%d-%m-%Y'))
82
+ .sort_values('date')
83
+ .reset_index(drop=True))
84
+ return df
85
+ except Exception as e:
86
+ st.error(f"Error fetching mutual fund data: {str(e)}")
87
+ return None
88
+
89
+ @st.cache_data(ttl=3600)
90
+ def load_yahoo_finance_data(ticker_symbol: str, start_date: datetime.date, end_date: datetime.date) -> Optional[pd.DataFrame]:
91
+ """Fetch data from Yahoo Finance."""
92
+ try:
93
+ data = yf.download(ticker_symbol, start=start_date, end=end_date)
94
+ data = data.reset_index()
95
+ data = data.rename(columns={'Date': 'date', 'Close': 'nav', 'Volume': 'volume'})
96
+ return data
97
+ except Exception as e:
98
+ st.error(f"Error fetching Yahoo Finance data: {str(e)}")
99
+ return None
100
+
101
+ def calculate_risk_metrics(returns: pd.Series) -> Dict[str, float]:
102
+ """Calculate comprehensive risk metrics for the fund."""
103
+ try:
104
+ metrics = {
105
+ 'volatility': returns.std() * np.sqrt(252),
106
+ 'sharpe_ratio': (returns.mean() * 252) / (returns.std() * np.sqrt(252)),
107
+ 'sortino_ratio': (returns.mean() * 252) / (returns[returns < 0].std() * np.sqrt(252)),
108
+ 'max_drawdown': (1 - (1 + returns).cumprod() / (1 + returns).cumprod().cummax()).max(),
109
+ 'skewness': stats.skew(returns),
110
+ 'kurtosis': stats.kurtosis(returns),
111
+ 'var_95': np.percentile(returns, 5),
112
+ 'cvar_95': returns[returns <= np.percentile(returns, 5)].mean(),
113
+ 'positive_days': (returns > 0).mean() * 100,
114
+ 'negative_days': (returns < 0).mean() * 100,
115
+ 'avg_gain': returns[returns > 0].mean(),
116
+ 'avg_loss': returns[returns < 0].mean()
117
+ }
118
+ return metrics
119
+ except Exception as e:
120
+ st.error(f"Error calculating risk metrics: {str(e)}")
121
+ return {}
122
+
123
+ def plot_price_volume_chart(df: pd.DataFrame) -> go.Figure:
124
+ """Create an interactive price and volume chart."""
125
+ try:
126
+ fig = make_subplots(rows=2, cols=1, shared_xaxes=True,
127
+ vertical_spacing=0.03,
128
+ row_heights=[0.7, 0.3])
129
+
130
+ fig.add_trace(go.Candlestick(x=df['date'],
131
+ open=df['Open'],
132
+ high=df['High'],
133
+ low=df['Low'],
134
+ close=df['nav'],
135
+ name='Price'),
136
+ row=1, col=1)
137
+
138
+ fig.add_trace(go.Bar(x=df['date'],
139
+ y=df['volume'],
140
+ name='Volume'),
141
+ row=2, col=1)
142
+
143
+ fig.update_layout(
144
+ title='Price and Volume Analysis',
145
+ yaxis_title='Price',
146
+ yaxis2_title='Volume',
147
+ height=800,
148
+ template='plotly_white'
149
+ )
150
+
151
+ return fig
152
+ except Exception as e:
153
+ st.error(f"Error creating price-volume chart: {str(e)}")
154
+ return None
155
+
156
+ def plot_returns_distribution(returns: pd.Series) -> go.Figure:
157
+ """Create an interactive returns distribution plot."""
158
+ try:
159
+ fig = go.Figure()
160
+
161
+ # Actual returns distribution
162
+ fig.add_trace(go.Histogram(
163
+ x=returns,
164
+ name='Actual Returns',
165
+ nbinsx=50,
166
+ histnorm='probability'
167
+ ))
168
+
169
+ # Normal distribution overlay
170
+ x_range = np.linspace(returns.min(), returns.max(), 100)
171
+ normal_dist = stats.norm.pdf(x_range, returns.mean(), returns.std())
172
+
173
+ fig.add_trace(go.Scatter(
174
+ x=x_range,
175
+ y=normal_dist,
176
+ name='Normal Distribution',
177
+ line=dict(color='red')
178
+ ))
179
+
180
+ fig.update_layout(
181
+ title='Returns Distribution Analysis',
182
+ xaxis_title='Returns',
183
+ yaxis_title='Probability',
184
+ barmode='overlay',
185
+ showlegend=True,
186
+ template='plotly_white'
187
+ )
188
+
189
+ return fig
190
+ except Exception as e:
191
+ st.error(f"Error creating returns distribution plot: {str(e)}")
192
+ return None
193
+
194
+ def plot_rolling_metrics(df: pd.DataFrame, window: int = 30) -> go.Figure:
195
+ """Create rolling metrics visualization with confidence bands."""
196
+ try:
197
+ rolling_returns = df['daily_returns'].rolling(window=window)
198
+ rolling_vol = rolling_returns.std() * np.sqrt(252)
199
+ rolling_mean = rolling_returns.mean() * 252
200
+ rolling_sharpe = rolling_mean / (rolling_returns.std() * np.sqrt(252))
201
+
202
+ fig = go.Figure()
203
+
204
+ # Add rolling volatility with confidence bands
205
+ vol_std = rolling_vol.std()
206
+ fig.add_trace(go.Scatter(
207
+ x=df['date'],
208
+ y=rolling_vol + 2*vol_std,
209
+ fill=None,
210
+ mode='lines',
211
+ line_color='rgba(0,100,80,0.2)',
212
+ name='Volatility Upper Band'
213
+ ))
214
+
215
+ fig.add_trace(go.Scatter(
216
+ x=df['date'],
217
+ y=rolling_vol - 2*vol_std,
218
+ fill='tonexty',
219
+ mode='lines',
220
+ line_color='rgba(0,100,80,0.2)',
221
+ name='Volatility Lower Band'
222
+ ))
223
+
224
+ fig.add_trace(go.Scatter(
225
+ x=df['date'],
226
+ y=rolling_vol,
227
+ name='Rolling Volatility',
228
+ line=dict(color='rgb(0,100,80)')
229
+ ))
230
+
231
+ fig.add_trace(go.Scatter(
232
+ x=df['date'],
233
+ y=rolling_sharpe,
234
+ name='Rolling Sharpe Ratio',
235
+ yaxis='y2',
236
+ line=dict(color='rgb(200,30,30)')
237
+ ))
238
+
239
+ fig.update_layout(
240
+ title=f'Rolling Metrics (Window: {window} days)',
241
+ yaxis=dict(title='Annualized Volatility'),
242
+ yaxis2=dict(title='Sharpe Ratio', overlaying='y', side='right'),
243
+ showlegend=True,
244
+ height=600,
245
+ template='plotly_white'
246
+ )
247
+
248
+ return fig
249
+ except Exception as e:
250
+ st.error(f"Error creating rolling metrics plot: {str(e)}")
251
+ return None
252
+
253
+ def plot_comparative_analysis(dfs: Dict[str, pd.DataFrame]) -> List[go.Figure]:
254
+ """Create comparative analysis plots."""
255
+ try:
256
+ # Normalize all fund values to 100
257
+ normalized_dfs = {}
258
+ for name, df in dfs.items():
259
+ normalized_dfs[name] = df.copy()
260
+ normalized_dfs[name]['normalized_nav'] = df['nav'] / df['nav'].iloc[0] * 100
261
+
262
+ # Create comparative performance plot
263
+ perf_fig = go.Figure()
264
+ for name, df in normalized_dfs.items():
265
+ perf_fig.add_trace(go.Scatter(
266
+ x=df['date'],
267
+ y=df['normalized_nav'],
268
+ name=name,
269
+ mode='lines'
270
+ ))
271
+
272
+ perf_fig.update_layout(
273
+ title='Comparative Performance Analysis',
274
+ xaxis_title='Date',
275
+ yaxis_title='Normalized Value (Base=100)',
276
+ template='plotly_white'
277
+ )
278
+
279
+ # Create correlation heatmap
280
+ returns_df = pd.DataFrame()
281
+ for name, df in dfs.items():
282
+ returns_df[name] = df['nav'].pct_change()
283
+
284
+ corr_matrix = returns_df.corr()
285
+
286
+ corr_fig = go.Figure(data=go.Heatmap(
287
+ z=corr_matrix,
288
+ x=corr_matrix.columns,
289
+ y=corr_matrix.columns,
290
+ colorscale='RdBu',
291
+ zmin=-1,
292
+ zmax=1
293
+ ))
294
+
295
+ corr_fig.update_layout(
296
+ title='Returns Correlation Matrix',
297
+ template='plotly_white'
298
+ )
299
+
300
+ return [perf_fig, corr_fig]
301
+ except Exception as e:
302
+ st.error(f"Error creating comparative analysis plots: {str(e)}")
303
+ return []
304
+
305
+ def plot_risk_analytics(df: pd.DataFrame) -> List[go.Figure]:
306
+ """Create risk analytics plots."""
307
+ try:
308
+ returns = df['nav'].pct_change()
309
+
310
+ # Create drawdown plot
311
+ cum_returns = (1 + returns).cumprod()
312
+ rolling_max = cum_returns.cummax()
313
+ drawdowns = (cum_returns - rolling_max) / rolling_max
314
+
315
+ drawdown_fig = go.Figure()
316
+ drawdown_fig.add_trace(go.Scatter(
317
+ x=df['date'],
318
+ y=drawdowns,
319
+ fill='tozeroy',
320
+ name='Drawdown'
321
+ ))
322
+
323
+ drawdown_fig.update_layout(
324
+ title='Historical Drawdown Analysis',
325
+ xaxis_title='Date',
326
+ yaxis_title='Drawdown',
327
+ template='plotly_white'
328
+ )
329
+
330
+ # Create risk-return scatter plot
331
+ rolling_windows = [30, 60, 90, 180, 252]
332
+ risk_return_data = []
333
+
334
+ for window in rolling_windows:
335
+ rolling_returns = returns.rolling(window=window)
336
+ risk = rolling_returns.std() * np.sqrt(252)
337
+ ret = rolling_returns.mean() * 252
338
+ risk_return_data.append({
339
+ 'window': f'{window} days',
340
+ 'risk': risk.mean(),
341
+ 'return': ret.mean()
342
+ })
343
+
344
+ risk_return_df = pd.DataFrame(risk_return_data)
345
+
346
+ risk_return_fig = px.scatter(
347
+ risk_return_df,
348
+ x='risk',
349
+ y='return',
350
+ text='window',
351
+ title='Risk-Return Analysis Across Different Time Windows'
352
+ )
353
+
354
+ risk_return_fig.update_traces(textposition='top center')
355
+ risk_return_fig.update_layout(template='plotly_white')
356
+
357
+ return [drawdown_fig, risk_return_fig]
358
+ except Exception as e:
359
+ st.error(f"Error creating risk analytics plots: {str(e)}")
360
+ return []
361
+
362
+ def main():
363
+ st.title("📊 Advanced Mutual Fund Analytics Platform")
364
+
365
+ st.markdown("""
366
+ ### Professional-Grade Investment Analysis Tool
367
+ This platform provides comprehensive mutual fund analytics with advanced risk metrics,
368
+ interactive visualizations, and comparative analysis capabilities.
369
+ """)
370
+
371
+ # Sidebar controls
372
+ st.sidebar.header("Analysis Controls")
373
+
374
+ analysis_type = st.sidebar.selectbox(
375
+ "Select Analysis Type",
376
+ ["Single Fund Analysis", "Comparative Analysis", "Risk Analytics"]
377
+ )
378
+
379
+ # Date range selection
380
+ col1, col2 = st.sidebar.columns(2)
381
+ with col1:
382
+ start_date = st.date_input(
383
+ "Start Date",
384
+ datetime.date.today() - relativedelta(years=3)
385
+ )
386
+ with col2:
387
+ end_date = st.date_input(
388
+ "End Date",
389
+ datetime.date.today()
390
+ )
391
+
392
+ if analysis_type == "Single Fund Analysis":
393
+ st.header("Single Fund Analysis")
394
+
395
+ input_type = st.radio(
396
+ "Select Input Type",
397
+ ["Yahoo Finance Ticker", "Mutual Fund Code (Indian)"]
398
+ )
399
+
400
+ if input_type == "Yahoo Finance Ticker":
401
+ fund_id = st.text_input("Enter Yahoo Finance Ticker", "0P0000XW8F.BO")
402
+ if st.button("Analyze Fund"):
403
+ with st.spinner("Fetching and analyzing data..."):
404
+ df = load_yahoo_finance_data(fund_id, start_date, end_date)
405
+ if df is not None:
406
+ df['daily_returns'] = df['nav'].pct_change()
407
+
408
+ metrics = calculate_risk_metrics(df['daily_returns'].dropna())
409
+
410
+ # Display metrics in a clean format
411
+ col1, col2, col3, col4 = st.columns(4)
412
+ with col1:
413
+ st.metric("Annualized Volatility", f"{metrics['volatility']:.2%}")
414
+ st.metric("Sharpe Ratio", f"{metrics['sharpe_ratio']:.2f}")
415
+ with col2:
416
+ st.metric("Maximum Drawdown", f"{metrics['max_drawdown']:.2%}")
417
+ st.metric("Value at Risk (95%)", f"{metrics['var_95']:.2%}")
418
+ with col3:
419
+ st.metric("Positive Days", f"{metrics['positive_days']:.1f}%")
420
+ st.metric("Average Daily Gain", f"{metrics['avg_gain']:.2%}")
421
+ with col4:
422
+ st.metric("Negative Days", f"{metrics['negative_days']:.1f}%")
423
+ st.metric("Average Daily Loss", f"{metrics['avg_loss']:.2%}")
424
+
425
+ # Create tabs for different visualizations
426
+ tab1, tab2, tab3 = st.tabs(["Price Analysis", "Returns Analysis", "Risk Metrics"])
427
+
428
+ with tab1:
429
+ if 'Open' in df.columns:
430
+ price_vol_fig = plot_price_volume_chart(df)
431
+ if price_vol_fig:
432
+ st.plotly_chart(price_vol_fig, use_container_width=True)
433
+
434
+ with tab2:
435
+ returns_dist_fig = plot_returns_distribution(df['daily_returns'].dropna())
436
+ if returns_dist_fig:
437
+ st.plotly_chart(returns_dist_fig, use_container_width=True)
438
+
439
+ with tab3:
440
+ window = st.slider("Rolling Window (days)", 10, 252, 30)
441
+ rolling_fig = plot_rolling_metrics(df, window)
442
+ if rolling_fig:
443
+ st.plotly_chart(rolling_fig, use_container_width=True)
444
+
445
+ else:
446
+ fund_code = st.text_input("Enter Mutual Fund Code", "118989")
447
+ if st.button("Analyze Fund"):
448
+ with st.spinner("Fetching and analyzing data..."):
449
+ df = fetch_mutual_fund_data(fund_code)
450
+ if df is not None:
451
+ df['daily_returns'] = df['nav'].pct_change()
452
+ # Perform the same analysis as above
453
+ metrics = calculate_risk_metrics(df['daily_returns'].dropna())
454
+
455
+ # Display metrics and charts (same as above)
456
+ col1, col2, col3, col4 = st.columns(4)
457
+ with col1:
458
+ st.metric("Annualized Volatility", f"{metrics['volatility']:.2%}")
459
+ st.metric("Sharpe Ratio", f"{metrics['sharpe_ratio']:.2f}")
460
+ with col2:
461
+ st.metric("Maximum Drawdown", f"{metrics['max_drawdown']:.2%}")
462
+ st.metric("Value at Risk (95%)", f"{metrics['var_95']:.2%}")
463
+ with col3:
464
+ st.metric("Positive Days", f"{metrics['positive_days']:.1f}%")
465
+ st.metric("Average Daily Gain", f"{metrics['avg_gain']:.2%}")
466
+ with col4:
467
+ st.metric("Negative Days", f"{metrics['negative_days']:.1f}%")
468
+ st.metric("Average Daily Loss", f"{metrics['avg_loss']:.2%}")
469
+
470
+ tab1, tab2 = st.tabs(["Returns Analysis", "Risk Metrics"])
471
+
472
+ with tab1:
473
+ returns_dist_fig = plot_returns_distribution(df['daily_returns'].dropna())
474
+ if returns_dist_fig:
475
+ st.plotly_chart(returns_dist_fig, use_container_width=True)
476
+
477
+ with tab2:
478
+ window = st.slider("Rolling Window (days)", 10, 252, 30)
479
+ rolling_fig = plot_rolling_metrics(df, window)
480
+ if rolling_fig:
481
+ st.plotly_chart(rolling_fig, use_container_width=True)
482
+
483
+ elif analysis_type == "Comparative Analysis":
484
+ st.header("Comparative Analysis")
485
+
486
+ num_funds = st.number_input("Number of funds to compare", min_value=2, max_value=5, value=2)
487
+
488
+ funds_data = {}
489
+
490
+ for i in range(num_funds):
491
+ st.subheader(f"Fund {i + 1}")
492
+ input_type = st.radio(
493
+ f"Select Input Type for Fund {i + 1}",
494
+ ["Yahoo Finance Ticker", "Mutual Fund Code (Indian)"],
495
+ key=f"input_type_{i}"
496
+ )
497
+
498
+ if input_type == "Yahoo Finance Ticker":
499
+ fund_id = st.text_input(f"Enter Yahoo Finance Ticker {i + 1}",
500
+ value=f"0P0000XW8F.BO" if i == 0 else "",
501
+ key=f"yahoo_{i}")
502
+ fund_name = st.text_input(f"Enter Fund Name {i + 1}",
503
+ value=f"Fund {i + 1}",
504
+ key=f"name_{i}")
505
+ funds_data[fund_name] = {'id': fund_id, 'type': 'yahoo'}
506
+ else:
507
+ fund_id = st.text_input(f"Enter Mutual Fund Code {i + 1}",
508
+ value="118989" if i == 0 else "",
509
+ key=f"mf_{i}")
510
+ fund_name = st.text_input(f"Enter Fund Name {i + 1}",
511
+ value=f"Fund {i + 1}",
512
+ key=f"name_{i}")
513
+ funds_data[fund_name] = {'id': fund_id, 'type': 'mf'}
514
+
515
+ if st.button("Compare Funds"):
516
+ with st.spinner("Fetching and comparing data..."):
517
+ dfs = {}
518
+ for name, info in funds_data.items():
519
+ if info['type'] == 'yahoo':
520
+ df = load_yahoo_finance_data(info['id'], start_date, end_date)
521
+ else:
522
+ df = fetch_mutual_fund_data(info['id'])
523
+
524
+ if df is not None:
525
+ dfs[name] = df
526
+
527
+ if len(dfs) > 1:
528
+ comparison_figs = plot_comparative_analysis(dfs)
529
+ if comparison_figs:
530
+ st.subheader("Comparative Performance")
531
+ st.plotly_chart(comparison_figs[0], use_container_width=True)
532
+
533
+ st.subheader("Correlation Analysis")
534
+ st.plotly_chart(comparison_figs[1], use_container_width=True)
535
+
536
+ else: # Risk Analytics
537
+ st.header("Risk Analytics")
538
+
539
+ input_type = st.radio(
540
+ "Select Input Type",
541
+ ["Yahoo Finance Ticker", "Mutual Fund Code (Indian)"]
542
+ )
543
+
544
+ if input_type == "Yahoo Finance Ticker":
545
+ fund_id = st.text_input("Enter Yahoo Finance Ticker", "0P0000XW8F.BO")
546
+ else:
547
+ fund_id = st.text_input("Enter Mutual Fund Code", "118989")
548
+
549
+ if st.button("Analyze Risk"):
550
+ with st.spinner("Performing risk analysis..."):
551
+ df = load_yahoo_finance_data(fund_id, start_date, end_date) if input_type == "Yahoo Finance Ticker" else fetch_mutual_fund_data(fund_id)
552
+
553
+ if df is not None:
554
+ risk_figs = plot_risk_analytics(df)
555
+ if risk_figs:
556
+ st.subheader("Drawdown Analysis")
557
+ st.plotly_chart(risk_figs[0], use_container_width=True)
558
+
559
+ st.subheader("Risk-Return Analysis")
560
+ st.plotly_chart(risk_figs[1], use_container_width=True)
561
+
562
+ if __name__ == "__main__":
563
+ main()