vibhorag101 commited on
Commit
f823eaa
1 Parent(s): dfbd37e

Added indicator like sd and sharpe

Browse files
Files changed (5) hide show
  1. .gitignore +2 -0
  2. app.py +4 -18
  3. indicators.py +38 -0
  4. portfolio.py +30 -12
  5. returns.py +4 -1
.gitignore ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ #ignore python cache files
2
+ *.pyc
app.py CHANGED
@@ -35,8 +35,8 @@ def get_portfolio_report(*args):
35
  stepup = args[6]
36
  schemes_df = args[7]
37
 
 
38
  scheme_name_and_weight = {}
39
-
40
  for i in range(8, len(args) - 1, 2):
41
  if args[i] and args[i+1]:
42
  scheme_name_and_weight[args[i]] = float(args[i+1])
@@ -71,22 +71,8 @@ def get_portfolio_report(*args):
71
  months = int(period_parts[0])
72
  start_date = end_date - DateOffset(months=months)
73
 
74
- portfolio_return_string, inception_dates, scheme_individual_returns = calculate_portfolio_returns(scheme_name_and_weight, sip_amount, lumpsum_amount, stepup, start_date, end_date, SIP_Date, schemes_df)
75
-
76
- inception_warnings = []
77
- for scheme_name, inception_date in inception_dates:
78
- if start_date < inception_date:
79
- inception_warnings.append(f"Warning: {scheme_name} inception date ({inception_date.date()}) is after the chosen start date ({start_date.date()}).")
80
-
81
- result_string = f"""
82
- {portfolio_return_string}
83
- ------------------------------------
84
- Individual Scheme Returns
85
- ------------------------------------
86
- {''.join(scheme_individual_returns)}
87
- {''.join(inception_warnings)}
88
- """
89
- return result_string
90
 
91
 
92
  def quick_search_schemes(query, schemes_df):
@@ -191,7 +177,7 @@ def create_ui():
191
  period = gr.Dropdown(choices=["YTD", "1 month","3 months","6 months","1 year", "3 years", "5 years", "7 years", "10 years","15 years","20 years", "Custom"], label="Select Period",value="YTD")
192
  custom_start_date = gr.Textbox(label="Custom Start Date (YYYY-MM-DD)", visible=False)
193
  custom_end_date = gr.Textbox(label="Custom End Date (YYYY-MM-DD)", visible=False)
194
- SIP_Date = gr.Dropdown(label="Monthly SIP Date", choices=["start","middle","end"],value="end")
195
  with gr.Column():
196
  use_inception_date = gr.Checkbox(label="Use Earliest Inception Date", value=False)
197
  inception_date_display = gr.Textbox(label="Earliest Inception Date", interactive=False)
 
35
  stepup = args[6]
36
  schemes_df = args[7]
37
 
38
+ # Extract scheme names and weights, into a dictionary from the args
39
  scheme_name_and_weight = {}
 
40
  for i in range(8, len(args) - 1, 2):
41
  if args[i] and args[i+1]:
42
  scheme_name_and_weight[args[i]] = float(args[i+1])
 
71
  months = int(period_parts[0])
72
  start_date = end_date - DateOffset(months=months)
73
 
74
+ portfolio_report_string = calculate_portfolio_returns(scheme_name_and_weight, sip_amount, lumpsum_amount, stepup, start_date, end_date, SIP_Date, schemes_df)
75
+ return portfolio_report_string
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
 
78
  def quick_search_schemes(query, schemes_df):
 
177
  period = gr.Dropdown(choices=["YTD", "1 month","3 months","6 months","1 year", "3 years", "5 years", "7 years", "10 years","15 years","20 years", "Custom"], label="Select Period",value="YTD")
178
  custom_start_date = gr.Textbox(label="Custom Start Date (YYYY-MM-DD)", visible=False)
179
  custom_end_date = gr.Textbox(label="Custom End Date (YYYY-MM-DD)", visible=False)
180
+ SIP_Date = gr.Dropdown(label="Monthly SIP Date", choices=["start","middle","end"],value="start")
181
  with gr.Column():
182
  use_inception_date = gr.Checkbox(label="Use Earliest Inception Date", value=False)
183
  inception_date_display = gr.Textbox(label="Earliest Inception Date", interactive=False)
indicators.py ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from utils import get_monthly_sip_nav_df
2
+ import numpy as np
3
+ import pandas as pd
4
+
5
+ def get_investment_sd(investment_df,start_date, end_date, SIP_date):
6
+ return_df = pd.DataFrame()
7
+ investment_monthly_df = get_monthly_sip_nav_df(investment_df, start_date, end_date, SIP_date=SIP_date)
8
+ return_df['monthly_return'] = investment_monthly_df['nav'].pct_change()
9
+ return_df['monthly_return'] = return_df['monthly_return'].dropna()
10
+
11
+ # calculate annualized standard deviation of monthly returns
12
+ return (return_df['monthly_return'].std()*np.sqrt(12)) * 100
13
+
14
+ def get_investment_sharpe_ratio(investment_df, start_date, end_date, SIP_date,risk_free_rate=6.86):
15
+ return_df = pd.DataFrame()
16
+ investment_monthly_df = get_monthly_sip_nav_df(investment_df, start_date, end_date, SIP_date=SIP_date)
17
+ return_df['monthly_return'] = investment_monthly_df['nav'].pct_change()*100
18
+ return_df['monthly_return'] = return_df['monthly_return'].dropna()
19
+
20
+ # calculate annualized standard deviation of monthly returns
21
+ annualized_sd = return_df['monthly_return'].std()*np.sqrt(12)
22
+ monthly_mean_return = return_df['monthly_return'].mean()
23
+ print(monthly_mean_return)
24
+ annualized_return = ((1+monthly_mean_return/100)**12 - 1)*100
25
+ print(annualized_return)
26
+
27
+ # calculate Sharpe Ratio
28
+ return ((annualized_return - risk_free_rate) / annualized_sd)
29
+
30
+ def get_investment_indicator_report(investment_df, start_date,end_date,SIP_date="start",risk_free_rate=6.86):
31
+ investment_monthly_df = get_monthly_sip_nav_df(investment_df, start_date, end_date, SIP_date)
32
+ investment_sd = get_investment_sd(investment_monthly_df, start_date, end_date, SIP_date)
33
+ investment_sharpe_ratio = get_investment_sharpe_ratio(investment_monthly_df, start_date, end_date, SIP_date,risk_free_rate)
34
+ return (f"""
35
+ Standard Deviation: {investment_sd}
36
+ Sharpe Ratio: {investment_sharpe_ratio}""")
37
+
38
+
portfolio.py CHANGED
@@ -1,6 +1,7 @@
1
  import pandas as pd
2
  from utils import get_mf_scheme_data
3
  from returns import get_investment_xirr, get_investment_sip_absolute_returns
 
4
 
5
  def get_portfolio_nav_df(schemes_name_and_weight, start_date, end_date, schemes_df):
6
  # start_date = pd.to_datetime(start_date)
@@ -41,6 +42,12 @@ def get_invdividual_scheme_returns(scheme_df, scheme_name,scheme_sip_amount, sch
41
  """
42
  return (scheme_string)
43
 
 
 
 
 
 
 
44
 
45
 
46
  def calculate_portfolio_returns(scheme_name_and_weight, sip_amount, lumpsum_amount, stepup, start_date, end_date, SIP_date, schemes_df):
@@ -48,7 +55,19 @@ def calculate_portfolio_returns(scheme_name_and_weight, sip_amount, lumpsum_amou
48
  scheme_individual_returns = []
49
  portfolio_df = get_portfolio_nav_df(scheme_name_and_weight, start_date, end_date,schemes_df)
50
  portfolio_absolute_return, portfolio_final_value, portfolio_invested_value = get_portfolio_absolute_returns(portfolio_df, sip_amount, lumpsum_amount, stepup, start_date, end_date, SIP_date)
51
- portfolio_return_string = f"""
 
 
 
 
 
 
 
 
 
 
 
 
52
  Portfolio
53
  ------------------------------------
54
  SIP Amount: {sip_amount}
@@ -59,21 +78,20 @@ def calculate_portfolio_returns(scheme_name_and_weight, sip_amount, lumpsum_amou
59
  SIP Date: {SIP_date}
60
  Total Investment: {portfolio_invested_value}
61
  ------------------------------------
62
- Portfolio Returns
63
  XIRR = {get_portfolio_xirr_returns(portfolio_df, start_date, end_date, SIP_date, lumpsum_amount, sip_amount)}%
64
  Absolute Returns = {portfolio_absolute_return}%
65
  Portfolio Final Value = {portfolio_final_value}
 
 
 
 
 
 
 
 
66
  """
67
-
68
- for scheme_name, scheme_weight in scheme_name_and_weight.items():
69
- scheme_code = schemes_df[schemes_df['schemeName'] == scheme_name]['schemeCode'].values[0]
70
- scheme_df, scheme_inception_date = get_mf_scheme_data(scheme_code)
71
- inception_dates.append((scheme_name, scheme_inception_date))
72
- scheme_sip_amount = sip_amount * scheme_weight / 100
73
- scheme_lumpsum_amount = lumpsum_amount * scheme_weight / 100
74
- scheme_individual_returns.append(get_invdividual_scheme_returns(scheme_df, scheme_name, scheme_sip_amount, scheme_lumpsum_amount, stepup, start_date, end_date, SIP_date))
75
-
76
- return portfolio_return_string, inception_dates, scheme_individual_returns
77
 
78
 
79
 
 
1
  import pandas as pd
2
  from utils import get_mf_scheme_data
3
  from returns import get_investment_xirr, get_investment_sip_absolute_returns
4
+ from indicators import get_investment_sd, get_investment_sharpe_ratio, get_investment_indicator_report
5
 
6
  def get_portfolio_nav_df(schemes_name_and_weight, start_date, end_date, schemes_df):
7
  # start_date = pd.to_datetime(start_date)
 
42
  """
43
  return (scheme_string)
44
 
45
+ def get_inception_date_warnings(inception_dates, start_date):
46
+ warnings = []
47
+ for scheme_name, scheme_inception_date in inception_dates:
48
+ if scheme_inception_date > start_date:
49
+ warnings.append(f"{scheme_name} has an inception date of {scheme_inception_date} which is after the start date of the portfolio.")
50
+ return warnings
51
 
52
 
53
  def calculate_portfolio_returns(scheme_name_and_weight, sip_amount, lumpsum_amount, stepup, start_date, end_date, SIP_date, schemes_df):
 
55
  scheme_individual_returns = []
56
  portfolio_df = get_portfolio_nav_df(scheme_name_and_weight, start_date, end_date,schemes_df)
57
  portfolio_absolute_return, portfolio_final_value, portfolio_invested_value = get_portfolio_absolute_returns(portfolio_df, sip_amount, lumpsum_amount, stepup, start_date, end_date, SIP_date)
58
+ portfolio_indicators_string = get_investment_indicator_report(portfolio_df, start_date, end_date)
59
+
60
+ for scheme_name, scheme_weight in scheme_name_and_weight.items():
61
+ scheme_code = schemes_df[schemes_df['schemeName'] == scheme_name]['schemeCode'].values[0]
62
+ scheme_df, scheme_inception_date = get_mf_scheme_data(scheme_code)
63
+ inception_dates.append((scheme_name, scheme_inception_date))
64
+ scheme_sip_amount = sip_amount * scheme_weight / 100
65
+ scheme_lumpsum_amount = lumpsum_amount * scheme_weight / 100
66
+ scheme_individual_returns.append(get_invdividual_scheme_returns(scheme_df, scheme_name, scheme_sip_amount, scheme_lumpsum_amount, stepup, start_date, end_date, SIP_date))
67
+
68
+ inception_date_warnings = get_inception_date_warnings(inception_dates, start_date)
69
+
70
+ portfolio_report_string = f"""
71
  Portfolio
72
  ------------------------------------
73
  SIP Amount: {sip_amount}
 
78
  SIP Date: {SIP_date}
79
  Total Investment: {portfolio_invested_value}
80
  ------------------------------------
81
+ Portfolio Report
82
  XIRR = {get_portfolio_xirr_returns(portfolio_df, start_date, end_date, SIP_date, lumpsum_amount, sip_amount)}%
83
  Absolute Returns = {portfolio_absolute_return}%
84
  Portfolio Final Value = {portfolio_final_value}
85
+ {portfolio_indicators_string}
86
+ ------------------------------------
87
+ Individual Scheme Returns
88
+ ------------------------------------
89
+ {''.join(scheme_individual_returns)}
90
+ ------------------------------------
91
+ Warnings
92
+ {''.join(inception_date_warnings)}
93
  """
94
+ return portfolio_report_string
 
 
 
 
 
 
 
 
 
95
 
96
 
97
 
returns.py CHANGED
@@ -10,8 +10,11 @@ def calculate_xnpv(rate, cashflows):
10
  def calculate_xirr(cashflows, guess=0.1):
11
  return optimize.newton(lambda r: calculate_xnpv(r,cashflows), guess)
12
 
13
- def get_investment_xirr(investment_df, start_date, end_date, SIP_date, lumpsum_amount=0, sip_amount=1000):
14
  # Get the monthly NAVs
 
 
 
15
  monthly_nav_df = get_monthly_sip_nav_df(investment_df, start_date, end_date, SIP_date)
16
 
17
  # Initialize lists to store cash flows and their corresponding dates
 
10
  def calculate_xirr(cashflows, guess=0.1):
11
  return optimize.newton(lambda r: calculate_xnpv(r,cashflows), guess)
12
 
13
+ def get_investment_xirr(investment_df, start_date, end_date, SIP_date, lumpsum_amount, sip_amount):
14
  # Get the monthly NAVs
15
+ if(sip_amount == 0):
16
+ sip_amount = 1000
17
+
18
  monthly_nav_df = get_monthly_sip_nav_df(investment_df, start_date, end_date, SIP_date)
19
 
20
  # Initialize lists to store cash flows and their corresponding dates