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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +90 -117
app.py CHANGED
@@ -1,129 +1,102 @@
1
- import gradio as gr # UI 框架
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
  """
17
- 计算从第1天到第years*365天的账户余额:
18
- - compounding: 复利频率 (Annual/Monthly/Daily)
19
- - deposit_freq: 定投频率 (Annual/Monthly/Daily)
20
- - stop_deposit_year: 在第几年(含)后停止定投
21
- - display_freq: 结果展示粒度 (Yearly/Monthly/Daily)
 
 
 
 
 
 
 
 
 
 
22
  """
23
- freq_map = {"Annual": 1, "Monthly": 12, "Daily": 365}
24
- m_comp = freq_map[compounding]
25
- m_dep = freq_map[deposit_freq]
26
-
27
- total_days = years * 365
28
- comp_interval = 365 // m_comp
29
- dep_interval = 365 // m_dep
30
- stop_day = stop_deposit_year * 365
31
-
32
- balance = principal
33
- deposit_count = 0
34
- schedule = []
35
-
36
- for day in range(1, total_days + 1):
37
- # 复利:每日或周期性触发
38
- if compounding == "Daily":
39
- balance *= 1 + (annual_rate / 100) / 365
40
- else:
41
- if day % comp_interval == 0:
42
- balance *= 1 + (annual_rate / 100) / m_comp
43
-
44
- # 定投:只在未超过 stop_day 且满足周期时发生
45
- if day <= stop_day and day % dep_interval == 0:
46
- balance += deposit
47
- deposit_count += 1
48
-
49
- # 按展示粒度记录
50
- record = False
51
- if display_freq == "Daily":
52
- record = True
53
- period = day
54
- elif display_freq == "Monthly" and day % (365 // 12) == 0:
55
- record = True
56
- period = day // (365 // 12)
57
- elif display_freq == "Yearly" and day % 365 == 0:
58
- record = True
59
- period = day // 365
60
-
61
- if record:
62
- total_inv = principal + deposit_count * deposit
63
- schedule.append({
64
- display_freq: period,
65
- "Future Value (RMB)": balance,
66
- "Total Invested (RMB)": total_inv
67
- })
68
-
69
- # 构造 DataFrame 并保留两位小数
70
- df = pd.DataFrame(schedule).round(2)
71
- df["Interest Earned (RMB)"] = (df["Future Value (RMB)"] - df["Total Invested (RMB)"]).round(2)
72
-
73
- # 绘制美观折线图
74
- fig = px.line(
75
- df,
76
- x=display_freq,
77
- y="Future Value (RMB)",
78
- title=f"Compound Growth over Time ({display_freq})",
79
- template="plotly_white"
80
- )
81
- fig.update_traces(mode="lines+markers")
82
- fig.update_layout(
83
- title_font_size=20,
84
- xaxis_title=display_freq,
85
- yaxis_title="Future Value (RMB)"
86
- )
87
 
88
- return df, fig
 
 
 
89
 
 
 
90
  with gr.Blocks() as demo:
91
- gr.Markdown("## 复利计算器\n填写参数后点击“计算”查看结果")
92
-
93
- with gr.Row():
94
- principal = gr.Number(label="初始本金 (RMB)", value=20000)
95
- deposit = gr.Number(label="定投 (RMB)", value=5000)
96
- annual_rate = gr.Number(label="益率 (%)", value=10.22)
97
-
 
 
98
  with gr.Row():
99
- compounding = gr.Radio(
100
- choices=["Annual", "Monthly", "Daily"],
101
- label="复利频", value="Monthly"
102
- )
103
- deposit_freq = gr.Radio(
104
- choices=["Annual", "Monthly", "Daily"],
105
- label="定投频率", value="Monthly"
106
- )
107
- display_freq = gr.Radio(
108
- choices=["Yearly", "Monthly", "Daily"],
109
- label="结果展示频率", value="Yearly"
110
- )
111
- years = gr.Slider(1, 50, value=41, label="计算年限 (年)")
112
- stop_deposit_year = gr.Slider(0, 50, value=41, label="何年后停止定投 (年)")
113
-
114
- compute_btn = gr.Button("计算", variant="primary")
115
-
116
- result_table = gr.Dataframe(interactive=False)
117
- result_plot = gr.Plot()
118
-
119
- compute_btn.click(
120
- fn=calculate_schedule,
121
- inputs=[
122
- principal, deposit, annual_rate,
123
- compounding, deposit_freq, display_freq,
124
- years, stop_deposit_year
125
- ],
126
- outputs=[result_table, result_plot]
127
  )
128
 
 
 
129
  demo.launch()
 
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()