vibhorag101
commited on
Commit
•
f823eaa
1
Parent(s):
dfbd37e
Added indicator like sd and sharpe
Browse files- .gitignore +2 -0
- app.py +4 -18
- indicators.py +38 -0
- portfolio.py +30 -12
- 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 |
-
|
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="
|
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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
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
|
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
|