Hakureirm commited on
Commit
a0d4a3a
·
verified ·
1 Parent(s): 28aa0af

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +104 -91
app.py CHANGED
@@ -1,102 +1,115 @@
1
- # Compound Interest Calculator for Hugging Face Demo
2
- # -------------------------------------------------
3
- # This script uses Gradio to create a simple web UI
4
- to calculate compound interest with regular monthly contributions.
5
- # It can be deployed directly as a Hugging Face Spaces app.
6
-
7
- import math
8
- import pandas as pd
9
  import gradio as gr
 
 
 
10
 
11
-
12
- def calculate_compound(
13
  principal: float,
14
- monthly_contrib: float,
15
  annual_rate: float,
16
- years_input: str
17
- ) -> pd.DataFrame:
18
- """
19
- Calculate future value, total contributions, and interest earned
20
- for a list of investment periods under compound interest.
21
-
22
- Parameters:
23
- - principal: Initial lump-sum investment (RMB).
24
- - monthly_contrib: Amount invested each month (RMB).
25
- - annual_rate: Annual effective interest rate in percent (e.g., 10.22 for 10.22%).
26
- - years_input: Comma-separated years (e.g., "1,3,5,7,9,41").
27
-
28
- Returns:
29
- - pd.DataFrame with columns:
30
- * Years
31
- * Total Contributions (RMB)
32
- * Future Value (RMB)
33
- * Interest Earned (RMB)
34
- """
35
- # Convert annual rate percentage to decimal
36
- r_annual = annual_rate / 100.0
37
- # Compute equivalent monthly rate
38
- r_monthly = (1 + r_annual) ** (1/12) - 1
39
-
40
- # Parse the years input into a sorted list of unique integers
41
- try:
42
- years = sorted({int(y.strip()) for y in years_input.split(",") if y.strip()})
43
- except ValueError:
44
- raise ValueError("Years must be a comma-separated list of integers.")
45
-
46
- data = []
47
- for t in years:
48
- n = t * 12 # total months
49
- # Future value of initial principal
50
- fv_principal = principal * (1 + r_monthly) ** n
51
- # Future value of series of monthly contributions
52
- fv_contrib = monthly_contrib * (((1 + r_monthly) ** n - 1) / r_monthly)
53
- fv_total = fv_principal + fv_contrib
54
- total_contrib = principal + monthly_contrib * n
55
- interest = fv_total - total_contrib
56
-
57
- data.append({
58
- "Years": t,
59
- "Total Contributions (RMB)": round(total_contrib, 2),
60
- "Future Value (RMB)": round(fv_total, 2),
61
- "Interest Earned (RMB)": round(interest, 2)
62
- })
63
-
64
- # Create DataFrame
65
- df = pd.DataFrame(data)
66
- df = df.sort_values(by="Years").reset_index(drop=True)
67
- return df
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
68
 
 
69
 
70
- # Gradio UI definition
71
  with gr.Blocks() as demo:
72
- gr.Markdown(
73
- """
74
- # 复利计算器
75
-
76
- 输入初始本金、每月定投金额、年化收益率(%),以及一个以逗号分隔的年限列表,
77
- 即可计算每个年限下的复利终值、总投入与利息收入。
78
- """
79
- )
80
-
81
  with gr.Row():
82
- principal_input = gr.Number(value=20000, label="初始本金 (RMB)")
83
- monthly_input = gr.Number(value=5000, label="每月定投 (RMB)")
84
- rate_input = gr.Number(value=10.22, label="年化收益率 (%)")
85
-
86
- years_input = gr.Text(value="1,3,5,7,9,11,13,15,17,19,21,23,25,27,29,31,33,35,37,39,41",
87
- label="年限列表 (逗号分隔)")
88
-
89
- output_table = gr.Dataframe(headers=["Years", "Total Contributions (RMB)",
90
- "Future Value (RMB)", "Interest Earned (RMB)"],
91
- label="计算结果")
92
-
93
- calculate_btn = gr.Button("计算")
94
- calculate_btn.click(
95
- fn=calculate_compound,
96
- inputs=[principal_input, monthly_input, rate_input, years_input],
97
- outputs=output_table
 
 
 
 
 
 
 
 
98
  )
99
 
100
- # 启动 Gradio 服务
101
- if __name__ == "__main__":
102
  demo.launch()
 
 
 
 
 
 
 
 
 
1
  import gradio as gr
2
+ import pandas as pd
3
+ import numpy as np
4
+ import plotly.express as px
5
 
6
+ def calculate_schedule(
 
7
  principal: float,
8
+ deposit: float,
9
  annual_rate: float,
10
+ compounding: str,
11
+ deposit_freq: str,
12
+ display_freq: str,
13
+ years: int,
14
+ stop_deposit_year: int
15
+ ):
16
+ freq_map = {"Annual": 1, "Monthly": 12, "Daily": 365}
17
+ m_comp = freq_map[compounding]
18
+ m_dep = freq_map[deposit_freq]
19
+
20
+ total_days = years * 365
21
+ comp_interval = 365 // m_comp
22
+ dep_interval = 365 // m_dep
23
+ stop_day = stop_deposit_year * 365
24
+
25
+ balance = principal
26
+ deposit_count = 0
27
+ schedule = []
28
+
29
+ for day in range(1, total_days + 1):
30
+ # 复利增长
31
+ if compounding == "Daily":
32
+ balance *= 1 + (annual_rate / 100) / 365
33
+ else:
34
+ if day % comp_interval == 0:
35
+ balance *= 1 + (annual_rate / 100) / m_comp
36
+
37
+ # 定投执行
38
+ if day <= stop_day and day % dep_interval == 0:
39
+ balance += deposit
40
+ deposit_count += 1
41
+
42
+ # 数据记录粒度
43
+ record = False
44
+ if display_freq == "Daily":
45
+ record = True
46
+ period = day
47
+ elif display_freq == "Monthly" and day % (365 // 12) == 0:
48
+ record = True
49
+ period = day // (365 // 12)
50
+ elif display_freq == "Yearly" and day % 365 == 0:
51
+ record = True
52
+ period = day // 365
53
+
54
+ if record:
55
+ total_inv = principal + deposit_count * deposit
56
+ fv = balance
57
+ schedule.append({
58
+ display_freq: period,
59
+ "Future Value (RMB)": fv,
60
+ "Total Invested (RMB)": total_inv,
61
+ "Interest Earned (RMB)": fv - total_inv,
62
+ })
63
+
64
+ # 构造 DataFrame 并新增“利息增量”列
65
+ df = pd.DataFrame(schedule).round(2)
66
+ df["Interest Increment (RMB)"] = df["Interest Earned (RMB)"].diff().fillna(0).round(2)
67
+
68
+ # 绘图
69
+ fig = px.line(
70
+ df,
71
+ x=display_freq,
72
+ y="Future Value (RMB)",
73
+ title=f"Compound Growth over Time ({display_freq})",
74
+ template="plotly_white"
75
+ )
76
+ fig.update_traces(mode="lines+markers")
77
+ fig.update_layout(
78
+ title_font_size=20,
79
+ xaxis_title=display_freq,
80
+ yaxis_title="Future Value (RMB)"
81
+ )
82
 
83
+ return df, fig
84
 
 
85
  with gr.Blocks() as demo:
86
+ gr.Markdown("## 复利计算器\n填写参数后点击“计算”查看结果")
87
+
 
 
 
 
 
 
 
88
  with gr.Row():
89
+ principal = gr.Number(label="初始本金 (RMB)", value=20000)
90
+ deposit = gr.Number(label="每次定投 (RMB)", value=5000)
91
+ annual_rate = gr.Number(label="年化收益率 (%)", value=10.22)
92
+
93
+ with gr.Row():
94
+ compounding = gr.Radio(choices=["Annual", "Monthly", "Daily"], label="复利频率", value="Monthly")
95
+ deposit_freq = gr.Radio(choices=["Annual", "Monthly", "Daily"], label="定投频率", value="Monthly")
96
+ display_freq = gr.Radio(choices=["Yearly", "Monthly", "Daily"], label="结果展示频率", value="Yearly")
97
+ years = gr.Slider(1, 50, value=41, label="计算年限 ()")
98
+ stop_deposit_year = gr.Slider(0, 50, value=41, label="何年后停止定投 (年)")
99
+
100
+ compute_btn = gr.Button("计算", variant="primary")
101
+
102
+ result_table = gr.Dataframe(interactive=False)
103
+ result_plot = gr.Plot()
104
+
105
+ compute_btn.click(
106
+ fn=calculate_schedule,
107
+ inputs=[
108
+ principal, deposit, annual_rate,
109
+ compounding, deposit_freq, display_freq,
110
+ years, stop_deposit_year
111
+ ],
112
+ outputs=[result_table, result_plot]
113
  )
114
 
 
 
115
  demo.launch()