⚡ 储能投资决策 数学模型 · 电力设计

输入项目基本参数,快速计算收益率、回收周期并获得投资建议
⏳ 计算中...

📈 测算结果

静态回收期
动态回收期
净现值 (NPV)
万元
内部收益率 (IRR)
%
年均投资收益率
%
💡 投资建议
计算后显示
* 动态指标基于基准折现率计算,内部收益率为近似值。
from js import document # 关键修复:显式导入 document import math # ---------- 核心计算 ---------- def calculate_investment(I, A, N, S, r): # 静态回收期 if A > 0: static_payback = I / A else: static_payback = float('inf') # 动态回收期 cum_pv = 0.0 dynamic_payback = float('inf') for t in range(1, N + 1): pv = A / ((1 + r) ** t) cum_pv += pv if cum_pv >= I: prev_cum = cum_pv - pv dynamic_payback = t - 1 + (I - prev_cum) / (cum_pv - prev_cum) if pv != 0 else t break # NPV npv = -I for t in range(1, N + 1): npv += A / ((1 + r) ** t) npv += S / ((1 + r) ** N) # IRR (二分法) def npv_func(rate): val = -I for t in range(1, N + 1): val += A / ((1 + rate) ** t) val += S / ((1 + rate) ** N) return val irr = None if npv_func(0) > 0: low, high = 0.0, 2.0 for _ in range(100): if npv_func(high) < 0: break high *= 1.5 if high > 5.0: break if npv_func(high) < 0: for _ in range(200): mid = (low + high) / 2 if npv_func(mid) > 0: low = mid else: high = mid if high - low < 0.00001: break irr = (low + high) / 2 else: irr = float('inf') else: irr = 0.0 avg_return = (A / I) * 100 if I > 0 else 0.0 # 投资建议 advice = "" if npv > 0 and irr is not None and irr > r: advice = "✅ 建议投资:项目净现值为正,内部收益率高于基准折现率,具有较好的投资价值。" elif npv > 0: advice = "⚠️ 项目净现值为正,但内部收益率低于基准折现率,需结合其他因素谨慎考虑。" else: advice = "❌ 不建议投资:项目净现值为负,投资回报低于基准要求。" if static_payback > N: advice += " 注意:静态回收期超过项目运营年限,资金回收风险较高。" elif static_payback > N * 0.7: advice += " 注意:静态回收期较长,占运营年限的较大比例,需关注现金流稳定性。" return { 'static': static_payback, 'dynamic': dynamic_payback, 'npv': npv, 'irr': irr, 'avg_return': avg_return, 'advice': advice } # ---------- DOM 操作 ---------- def show_error(msg): err = document.getElementById('error-msg') err.style.display = 'block' err.innerText = msg def hide_error(): document.getElementById('error-msg').style.display = 'none' def set_loading(show): el = document.getElementById('loading-indicator') el.style.display = 'inline' if show else 'none' def update_result(result): document.getElementById('result-area').style.display = 'block' def set_text(id, text): document.getElementById(id).innerHTML = text if math.isinf(result['static']): set_text('res-static', '∞ ') else: set_text('res-static', f'{result["static"]:.2f} ') if math.isinf(result['dynamic']): set_text('res-dynamic', '> N ') else: set_text('res-dynamic', f'{result["dynamic"]:.2f} ') set_text('res-npv', f'{result["npv"]:.2f} 万元') if result['irr'] is None: set_text('res-irr', '-- %') elif math.isinf(result['irr']): set_text('res-irr', '>200 %') else: set_text('res-irr', f'{result["irr"]*100:.2f} %') set_text('res-return', f'{result["avg_return"]:.2f} %') document.getElementById('advice-text').innerText = result['advice'] # ---------- 计算 ---------- def on_calculate(event=None): hide_error() set_loading(True) try: I = float(document.getElementById('invest').value) A = float(document.getElementById('annual_net').value) N = int(document.getElementById('years').value) S = float(document.getElementById('salvage').value) r_percent = float(document.getElementById('discount').value) except ValueError: show_error("⚠️ 请输入有效的数字,检查所有输入框是否为空或包含非数字字符。") set_loading(False) return if I <= 0: show_error("⚠️ 初始投资必须大于 0。") set_loading(False) return if A < 0: show_error("⚠️ 年净收益不能为负数。") set_loading(False) return if N <= 0: show_error("⚠️ 运营年限至少为 1 年。") set_loading(False) return if r_percent < 0: show_error("⚠️ 基准折现率不能为负数。") set_loading(False) return r = r_percent / 100.0 result = calculate_investment(I, A, N, S, r) update_result(result) set_loading(False) def on_reset(event=None): document.getElementById('invest').value = '5000' document.getElementById('annual_net').value = '800' document.getElementById('years').value = '15' document.getElementById('salvage').value = '200' document.getElementById('discount').value = '8' hide_error() document.getElementById('result-area').style.display = 'none' document.getElementById('advice-text').innerText = '计算后显示' set_loading(False) # ---------- 绑定事件 ---------- document.getElementById('calc-btn').onclick = on_calculate document.getElementById('reset-btn').onclick = on_reset # 页面加载后自动执行一次 on_calculate()
📊 已访问