vibhorag101
commited on
Commit
•
fe61012
1
Parent(s):
c9b69d1
Added SIP step-up
Browse files
app.py
CHANGED
@@ -3,6 +3,7 @@ import pandas as pd
|
|
3 |
import plotly.graph_objects as go
|
4 |
from datetime import datetime, timedelta
|
5 |
import requests
|
|
|
6 |
|
7 |
js_func = """
|
8 |
function refresh() {
|
@@ -15,6 +16,17 @@ function refresh() {
|
|
15 |
}
|
16 |
"""
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
def get_nav_data(scheme_code):
|
19 |
url = f"https://api.mfapi.in/mf/{scheme_code}"
|
20 |
response = requests.get(url)
|
@@ -26,7 +38,7 @@ def get_nav_data(scheme_code):
|
|
26 |
inception_date = df['date'].min()
|
27 |
return df, inception_date
|
28 |
|
29 |
-
def calculate_sip_returns(nav_data, sip_amount, start_date, end_date, SIP_Date):
|
30 |
start_date = pd.Timestamp(start_date)
|
31 |
end_date = pd.Timestamp(end_date)
|
32 |
|
@@ -39,28 +51,31 @@ def calculate_sip_returns(nav_data, sip_amount, start_date, end_date, SIP_Date):
|
|
39 |
else:
|
40 |
last_dates = nav_data_filtered.groupby([nav_data_filtered['date'].dt.year, nav_data_filtered['date'].dt.month]).apply(lambda x: x.iloc[len(x)//2])
|
41 |
|
42 |
-
|
43 |
-
|
44 |
-
|
|
|
|
|
|
|
|
|
|
|
45 |
for _, row in last_dates.iloc[:-1].iterrows():
|
46 |
-
|
|
|
|
|
|
|
|
|
|
|
47 |
units_accumulated += units_bought
|
48 |
-
total_investment +=
|
49 |
-
|
50 |
final_value = units_accumulated * last_dates.iloc[-1]['nav']
|
51 |
total_return = (final_value - total_investment) / total_investment * 100
|
52 |
-
|
53 |
return total_return, final_value, total_investment
|
54 |
|
55 |
-
def create_pie_chart(schemes):
|
56 |
-
labels = list(schemes.keys())
|
57 |
-
values = list(schemes.values())
|
58 |
-
|
59 |
-
fig = go.Figure(data=[go.Pie(labels=labels, values=values)])
|
60 |
-
fig.update_layout(title_text="Scheme Weightages")
|
61 |
-
return fig
|
62 |
|
63 |
-
def calculate_portfolio_returns(schemes, sip_amount, start_date, end_date, SIP_date, schemes_df):
|
64 |
scheme_returns = []
|
65 |
total_investment = 0
|
66 |
final_value = 0
|
@@ -70,8 +85,8 @@ def calculate_portfolio_returns(schemes, sip_amount, start_date, end_date, SIP_d
|
|
70 |
scheme_code = schemes_df[schemes_df['schemeName'] == scheme_name]['schemeCode'].values[0]
|
71 |
nav_data, inception_date = get_nav_data(scheme_code)
|
72 |
inception_dates.append((scheme_name, inception_date))
|
73 |
-
scheme_return, scheme_final_value, scheme_total_investment = calculate_sip_returns(nav_data, sip_amount * scheme_weight / 100, start_date, end_date, SIP_date)
|
74 |
-
scheme_returns.append((scheme_name, scheme_return))
|
75 |
final_value += scheme_final_value
|
76 |
total_investment += scheme_total_investment
|
77 |
|
@@ -84,10 +99,12 @@ def update_sip_calculator(*args):
|
|
84 |
custom_end_date = args[2]
|
85 |
SIP_Date = args[3]
|
86 |
sip_amount = args[4]
|
87 |
-
|
|
|
|
|
88 |
schemes = {}
|
89 |
|
90 |
-
for i in range(
|
91 |
if args[i] and args[i+1]:
|
92 |
schemes[args[i]] = float(args[i+1])
|
93 |
|
@@ -124,7 +141,7 @@ def update_sip_calculator(*args):
|
|
124 |
start_date = end_date - timedelta(days=months*30)
|
125 |
|
126 |
try:
|
127 |
-
portfolio_return, final_value, total_investment, scheme_returns, inception_dates = calculate_portfolio_returns(schemes, sip_amount, start_date, end_date, SIP_Date, schemes_df)
|
128 |
except Exception as e:
|
129 |
return f"Error: {str(e)}", None, None, None
|
130 |
|
@@ -141,12 +158,15 @@ def update_sip_calculator(*args):
|
|
141 |
result += "\n".join(inception_warnings) + "\n\n"
|
142 |
result += f"Possible start date for all chosen schemes is: {earliest_inception_date.date()}\n\n"
|
143 |
|
144 |
-
result += f"
|
145 |
-
result += f"Total investment:
|
146 |
-
result += f"Final value:
|
147 |
result += "Individual scheme returns:\n"
|
148 |
-
for scheme_name, scheme_return in scheme_returns:
|
149 |
-
result += f"{scheme_name}
|
|
|
|
|
|
|
150 |
# pie_chart = create_pie_chart(schemes)
|
151 |
# return result, pie_chart, final_value, total_investment
|
152 |
return result
|
@@ -265,7 +285,10 @@ def create_ui():
|
|
265 |
use_inception_date = gr.Checkbox(label="Use Earliest Inception Date", value=False)
|
266 |
inception_date_display = gr.Textbox(label="Earliest Inception Date", interactive=False)
|
267 |
|
268 |
-
|
|
|
|
|
|
|
269 |
|
270 |
schemes_list = gr.State([])
|
271 |
|
@@ -288,7 +311,7 @@ def create_ui():
|
|
288 |
|
289 |
calculate_button = gr.Button("Calculate Returns")
|
290 |
|
291 |
-
result = gr.Textbox(label="Results")
|
292 |
# pie_chart = gr.Plot(label="Scheme Weightages")
|
293 |
# final_value = gr.Number(label="Final Value (₹)", interactive=False)
|
294 |
# total_investment = gr.Number(label="Total Investment (₹)", interactive=False)
|
@@ -352,8 +375,8 @@ def create_ui():
|
|
352 |
outputs=inception_date_display
|
353 |
)
|
354 |
|
355 |
-
def prepare_inputs_with_inception(period, custom_start, custom_end, SIP_Date, sip_amount, schemes_list, schemes_df, use_inception_date, inception_date_display):
|
356 |
-
inputs = [period, custom_start, custom_end, SIP_Date, sip_amount, schemes_df]
|
357 |
for name, weight in schemes_list:
|
358 |
inputs.extend([name, weight])
|
359 |
|
@@ -365,7 +388,7 @@ def create_ui():
|
|
365 |
|
366 |
calculate_button.click(
|
367 |
lambda *args: update_sip_calculator(*prepare_inputs_with_inception(*args)),
|
368 |
-
inputs=[period, custom_start_date, custom_end_date, SIP_Date, sip_amount,
|
369 |
outputs=[result]
|
370 |
# outputs=[result, final_value, total_investment]
|
371 |
# outputs=[result, pie_chart, final_value, total_investment]
|
|
|
3 |
import plotly.graph_objects as go
|
4 |
from datetime import datetime, timedelta
|
5 |
import requests
|
6 |
+
import locale
|
7 |
|
8 |
js_func = """
|
9 |
function refresh() {
|
|
|
16 |
}
|
17 |
"""
|
18 |
|
19 |
+
locale.setlocale(locale.LC_MONETARY, 'en_IN')
|
20 |
+
|
21 |
+
# def create_pie_chart(schemes):
|
22 |
+
# labels = list(schemes.keys())
|
23 |
+
# values = list(schemes.values())
|
24 |
+
|
25 |
+
# fig = go.Figure(data=[go.Pie(labels=labels, values=values)])
|
26 |
+
# fig.update_layout(title_text="Scheme Weightages")
|
27 |
+
# return fig
|
28 |
+
|
29 |
+
|
30 |
def get_nav_data(scheme_code):
|
31 |
url = f"https://api.mfapi.in/mf/{scheme_code}"
|
32 |
response = requests.get(url)
|
|
|
38 |
inception_date = df['date'].min()
|
39 |
return df, inception_date
|
40 |
|
41 |
+
def calculate_sip_returns(nav_data, sip_amount, upfront_amount, stepup, start_date, end_date, SIP_Date):
|
42 |
start_date = pd.Timestamp(start_date)
|
43 |
end_date = pd.Timestamp(end_date)
|
44 |
|
|
|
51 |
else:
|
52 |
last_dates = nav_data_filtered.groupby([nav_data_filtered['date'].dt.year, nav_data_filtered['date'].dt.month]).apply(lambda x: x.iloc[len(x)//2])
|
53 |
|
54 |
+
total_investment = upfront_amount
|
55 |
+
current_sip_amount = sip_amount
|
56 |
+
|
57 |
+
# do calculation for upfront investment
|
58 |
+
units_bought = upfront_amount / nav_data_filtered.iloc[0]['nav']
|
59 |
+
units_accumulated = units_bought
|
60 |
+
previous_year = start_date.year
|
61 |
+
|
62 |
for _, row in last_dates.iloc[:-1].iterrows():
|
63 |
+
# Check if a year has passed and increase SIP amount accordingly
|
64 |
+
if row['date'].year > previous_year:
|
65 |
+
current_sip_amount += current_sip_amount * (stepup / 100)
|
66 |
+
previous_year = row['date'].year
|
67 |
+
|
68 |
+
units_bought = current_sip_amount / row['nav']
|
69 |
units_accumulated += units_bought
|
70 |
+
total_investment += current_sip_amount
|
71 |
+
|
72 |
final_value = units_accumulated * last_dates.iloc[-1]['nav']
|
73 |
total_return = (final_value - total_investment) / total_investment * 100
|
74 |
+
|
75 |
return total_return, final_value, total_investment
|
76 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
77 |
|
78 |
+
def calculate_portfolio_returns(schemes, sip_amount, upfront_amount, stepup, start_date, end_date, SIP_date, schemes_df):
|
79 |
scheme_returns = []
|
80 |
total_investment = 0
|
81 |
final_value = 0
|
|
|
85 |
scheme_code = schemes_df[schemes_df['schemeName'] == scheme_name]['schemeCode'].values[0]
|
86 |
nav_data, inception_date = get_nav_data(scheme_code)
|
87 |
inception_dates.append((scheme_name, inception_date))
|
88 |
+
scheme_return, scheme_final_value, scheme_total_investment = calculate_sip_returns(nav_data, sip_amount * scheme_weight / 100, upfront_amount * scheme_weight / 100, stepup, start_date, end_date, SIP_date)
|
89 |
+
scheme_returns.append((scheme_name, scheme_return,scheme_final_value,scheme_total_investment))
|
90 |
final_value += scheme_final_value
|
91 |
total_investment += scheme_total_investment
|
92 |
|
|
|
99 |
custom_end_date = args[2]
|
100 |
SIP_Date = args[3]
|
101 |
sip_amount = args[4]
|
102 |
+
upfront_amount = args[5]
|
103 |
+
stepup = args[6]
|
104 |
+
schemes_df = args[7]
|
105 |
schemes = {}
|
106 |
|
107 |
+
for i in range(8, len(args) - 1, 2): # Adjust range to account for use_inception_date
|
108 |
if args[i] and args[i+1]:
|
109 |
schemes[args[i]] = float(args[i+1])
|
110 |
|
|
|
141 |
start_date = end_date - timedelta(days=months*30)
|
142 |
|
143 |
try:
|
144 |
+
portfolio_return, final_value, total_investment, scheme_returns, inception_dates = calculate_portfolio_returns(schemes, sip_amount, upfront_amount,stepup, start_date, end_date, SIP_Date, schemes_df)
|
145 |
except Exception as e:
|
146 |
return f"Error: {str(e)}", None, None, None
|
147 |
|
|
|
158 |
result += "\n".join(inception_warnings) + "\n\n"
|
159 |
result += f"Possible start date for all chosen schemes is: {earliest_inception_date.date()}\n\n"
|
160 |
|
161 |
+
result += f"Portfolio Absolute return: {portfolio_return:.2f}%\n"
|
162 |
+
result += f"Total investment: {locale.currency(total_investment,grouping=True)}\n"
|
163 |
+
result += f"Final value: {locale.currency(final_value,grouping=True)}\n\n"
|
164 |
result += "Individual scheme returns:\n"
|
165 |
+
for scheme_name, scheme_return, scheme_final_value, scheme_total_investment in scheme_returns:
|
166 |
+
result += f"---- {scheme_name} ----:\n"
|
167 |
+
result += f"Return: {scheme_return:.2f}%\n"
|
168 |
+
result += f"Total investment: {locale.currency(scheme_total_investment,grouping=True)}\n"
|
169 |
+
result += f"Final value: {locale.currency(scheme_final_value,grouping=True)}\n\n"
|
170 |
# pie_chart = create_pie_chart(schemes)
|
171 |
# return result, pie_chart, final_value, total_investment
|
172 |
return result
|
|
|
285 |
use_inception_date = gr.Checkbox(label="Use Earliest Inception Date", value=False)
|
286 |
inception_date_display = gr.Textbox(label="Earliest Inception Date", interactive=False)
|
287 |
|
288 |
+
with gr.Row():
|
289 |
+
sip_amount = gr.Number(label="SIP Amount (₹)")
|
290 |
+
upfront_amount = gr.Number(label="Upfront Investment (₹)",value=0)
|
291 |
+
stepup = gr.Number(label="Stepup %",value=0)
|
292 |
|
293 |
schemes_list = gr.State([])
|
294 |
|
|
|
311 |
|
312 |
calculate_button = gr.Button("Calculate Returns")
|
313 |
|
314 |
+
result = gr.Textbox(label="Results",)
|
315 |
# pie_chart = gr.Plot(label="Scheme Weightages")
|
316 |
# final_value = gr.Number(label="Final Value (₹)", interactive=False)
|
317 |
# total_investment = gr.Number(label="Total Investment (₹)", interactive=False)
|
|
|
375 |
outputs=inception_date_display
|
376 |
)
|
377 |
|
378 |
+
def prepare_inputs_with_inception(period, custom_start, custom_end, SIP_Date, sip_amount, upfront_amount,stepup, schemes_list, schemes_df, use_inception_date, inception_date_display):
|
379 |
+
inputs = [period, custom_start, custom_end, SIP_Date, sip_amount, upfront_amount, stepup, schemes_df]
|
380 |
for name, weight in schemes_list:
|
381 |
inputs.extend([name, weight])
|
382 |
|
|
|
388 |
|
389 |
calculate_button.click(
|
390 |
lambda *args: update_sip_calculator(*prepare_inputs_with_inception(*args)),
|
391 |
+
inputs=[period, custom_start_date, custom_end_date, SIP_Date, sip_amount,upfront_amount,stepup,schemes_list, gr.State(schemes_df), use_inception_date, inception_date_display],
|
392 |
outputs=[result]
|
393 |
# outputs=[result, final_value, total_investment]
|
394 |
# outputs=[result, pie_chart, final_value, total_investment]
|