refining AI Suggestions and Drip Forecast UI

This commit is contained in:
Pascal BIBEHE 2025-06-04 16:30:04 +02:00
parent 9d25a01082
commit 1bd98153a8

View File

@ -2110,15 +2110,24 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
st.subheader("📈 Strategy Performance Summary")
col1, col2, col3, col4 = st.columns(4)
drip_variation = (comparison_result['drip_final_value'] - comparison_result['initial_investment']) / comparison_result['initial_investment'] * 100
no_drip_variation = (comparison_result['no_drip_final_value'] - comparison_result['initial_investment']) / comparison_result['initial_investment'] * 100
with col1:
st.metric(
"DRIP Final Value",
f"${comparison_result['drip_final_value']:,.2f}"
f"${comparison_result['drip_final_value']:,.2f}",
delta=f"{drip_variation:+.1f}%",
delta_color="normal" if drip_variation < 0 else "inverse" if drip_variation == 0 else "off" if drip_variation < 0 else "normal" # fallback, but we will override below
)
# Streamlit does not support custom colors, so we use green for >0, grey for <0
# But delta_color="normal" is green for positive, red for negative. We'll use normal for green, off for grey.
with col2:
st.metric(
"No-DRIP Final Value",
f"${comparison_result['no_drip_final_value']:,.2f}"
f"${comparison_result['no_drip_final_value']:,.2f}",
delta=f"{no_drip_variation:+.1f}%",
delta_color="normal" if no_drip_variation > 0 else "off"
)
with col3:
winner = comparison_result['winner']
@ -2882,7 +2891,7 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
# Strategy 2: Income Focus
income_goal = InvestmentGoal(
capital_target=capital_target,
income_target=income_target * 1.2 if income_target > 0 else capital_target * 0.05, # 20% higher income target
income_target=income_target * 1.2 if income_target > 0 else capital_target * 0.06, # 6% target yield
risk_tolerance=RiskTolerance.CONSERVATIVE,
investment_horizon=investment_horizon
)
@ -2891,16 +2900,16 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
# Strategy 3: Growth Focus
growth_goal = InvestmentGoal(
capital_target=capital_target,
income_target=income_target * 0.8 if income_target > 0 else None, # 20% lower income target
income_target=income_target * 0.8 if income_target > 0 else capital_target * 0.03, # 3% target yield
risk_tolerance=RiskTolerance.AGGRESSIVE,
investment_horizon=investment_horizon
)
growth_portfolio = selection_service.select_etfs(growth_goal)
# Strategy 4: Risk-Adjusted
# Strategy 4: Risk-Adjusted (uses user's risk tolerance)
risk_adjusted_goal = InvestmentGoal(
capital_target=capital_target,
income_target=income_target if income_target > 0 else None,
income_target=income_target if income_target > 0 else None, # No default yield target
risk_tolerance=RiskTolerance[risk_tolerance.upper()],
investment_horizon=investment_horizon
)
@ -2917,7 +2926,12 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
# Display Balanced Growth Strategy
with strategy_tabs[0]:
st.write("### Balanced Growth Strategy")
st.write("A balanced approach focusing on both growth and income, suitable for most investors.")
st.write("""
A balanced approach focusing on both growth and income, suitable for most investors.
- Target Yield: 4%
- Risk Level: Moderate
- Focus: Equal balance between growth and income
""")
if balanced_portfolio:
portfolio_df = pd.DataFrame(balanced_portfolio)
portfolio_df['Allocation (%)'] = portfolio_df['allocation'].round().astype(int)
@ -2937,7 +2951,7 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
'Volatility (%)': etf['metrics']['volatility'] * 100,
'Max Drawdown (%)': etf['metrics']['max_drawdown'] * 100,
'Sharpe Ratio': etf['metrics']['sharpe_ratio'],
'Dividend Yield (%)': etf['metrics']['dividend_yield'] * 100
'Dividend Yield (%)': etf['metrics']['dividend_yield']
}
for etf in balanced_portfolio
])
@ -2948,7 +2962,12 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
# Display Income Focus Strategy
with strategy_tabs[1]:
st.write("### Income Focus Strategy")
st.write("Optimized for higher dividend income with lower risk, suitable for income-focused investors.")
st.write("""
Optimized for higher dividend income with lower risk, suitable for income-focused investors.
- Target Yield: 6%
- Risk Level: Conservative
- Focus: Maximizing dividend income
""")
if income_portfolio:
portfolio_df = pd.DataFrame(income_portfolio)
portfolio_df['Allocation (%)'] = portfolio_df['allocation'].round().astype(int)
@ -2968,7 +2987,7 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
'Volatility (%)': etf['metrics']['volatility'] * 100,
'Max Drawdown (%)': etf['metrics']['max_drawdown'] * 100,
'Sharpe Ratio': etf['metrics']['sharpe_ratio'],
'Dividend Yield (%)': etf['metrics']['dividend_yield'] * 100
'Dividend Yield (%)': etf['metrics']['dividend_yield']
}
for etf in income_portfolio
])
@ -2979,7 +2998,12 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
# Display Growth Focus Strategy
with strategy_tabs[2]:
st.write("### Growth Focus Strategy")
st.write("Optimized for capital appreciation with higher risk tolerance, suitable for growth investors.")
st.write("""
Optimized for capital appreciation with higher risk tolerance, suitable for growth investors.
- Target Yield: 3%
- Risk Level: Aggressive
- Focus: Capital appreciation
""")
if growth_portfolio:
portfolio_df = pd.DataFrame(growth_portfolio)
portfolio_df['Allocation (%)'] = portfolio_df['allocation'].round().astype(int)
@ -2999,7 +3023,7 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
'Volatility (%)': etf['metrics']['volatility'] * 100,
'Max Drawdown (%)': etf['metrics']['max_drawdown'] * 100,
'Sharpe Ratio': etf['metrics']['sharpe_ratio'],
'Dividend Yield (%)': etf['metrics']['dividend_yield'] * 100
'Dividend Yield (%)': etf['metrics']['dividend_yield']
}
for etf in growth_portfolio
])
@ -3010,7 +3034,12 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
# Display Risk-Adjusted Strategy
with strategy_tabs[3]:
st.write("### Risk-Adjusted Strategy")
st.write(f"Optimized for your specific risk tolerance ({risk_tolerance}), balancing growth and income.")
st.write(f"""
Optimized for your specific risk tolerance ({risk_tolerance}), with a focus on sustainable income.
- Target Yield: 5%
- Risk Level: {risk_tolerance}
- Focus: Balanced growth with sustainable income
""")
if risk_adjusted_portfolio:
portfolio_df = pd.DataFrame(risk_adjusted_portfolio)
portfolio_df['Allocation (%)'] = portfolio_df['allocation'].round().astype(int)
@ -3030,7 +3059,7 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
'Volatility (%)': etf['metrics']['volatility'] * 100,
'Max Drawdown (%)': etf['metrics']['max_drawdown'] * 100,
'Sharpe Ratio': etf['metrics']['sharpe_ratio'],
'Dividend Yield (%)': etf['metrics']['dividend_yield'] * 100
'Dividend Yield (%)': etf['metrics']['dividend_yield']
}
for etf in risk_adjusted_portfolio
])
@ -3046,7 +3075,7 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
if st.button("Apply Balanced Growth", key="apply_balanced"):
if balanced_portfolio:
st.session_state.etf_allocations = [
{"ticker": etf['ticker'], "allocation": etf['allocation'] * 100}
{"ticker": etf['ticker'], "allocation": int(round(etf['allocation']))}
for etf in balanced_portfolio
]
st.success("Applied Balanced Growth strategy!")
@ -3056,7 +3085,7 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
if st.button("Apply Income Focus", key="apply_income"):
if income_portfolio:
st.session_state.etf_allocations = [
{"ticker": etf['ticker'], "allocation": etf['allocation'] * 100}
{"ticker": etf['ticker'], "allocation": int(round(etf['allocation']))}
for etf in income_portfolio
]
st.success("Applied Income Focus strategy!")
@ -3066,7 +3095,7 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
if st.button("Apply Growth Focus", key="apply_growth"):
if growth_portfolio:
st.session_state.etf_allocations = [
{"ticker": etf['ticker'], "allocation": etf['allocation'] * 100}
{"ticker": etf['ticker'], "allocation": int(round(etf['allocation']))}
for etf in growth_portfolio
]
st.success("Applied Growth Focus strategy!")
@ -3076,7 +3105,7 @@ if st.session_state.simulation_run and st.session_state.df_data is not None:
if st.button("Apply Risk-Adjusted", key="apply_risk_adjusted"):
if risk_adjusted_portfolio:
st.session_state.etf_allocations = [
{"ticker": etf['ticker'], "allocation": etf['allocation'] * 100}
{"ticker": etf['ticker'], "allocation": int(round(etf['allocation']))}
for etf in risk_adjusted_portfolio
]
st.success("Applied Risk-Adjusted strategy!")