From 1fc54d5ea9b6dbba00b15fc2bc233bc800881709 Mon Sep 17 00:00:00 2001 From: Pascal Date: Tue, 27 May 2025 23:53:08 +0200 Subject: [PATCH] revert: restore original portfolio allocation logic --- pages/ETF_Portfolio_Builder.py | 61 +++++++++++++++++++++++----------- 1 file changed, 41 insertions(+), 20 deletions(-) diff --git a/pages/ETF_Portfolio_Builder.py b/pages/ETF_Portfolio_Builder.py index a8753d0..e37c3d5 100644 --- a/pages/ETF_Portfolio_Builder.py +++ b/pages/ETF_Portfolio_Builder.py @@ -473,11 +473,6 @@ def optimize_portfolio_allocation(etf_metrics: List[Dict[str, Any]], risk_tolera logger.info(f"Optimizing portfolio allocation for {risk_tolerance} risk tolerance") logger.info(f"ETF metrics: {etf_metrics}") - # Calculate risk scores for each ETF - for etf in etf_metrics: - etf['risk_score'] = calculate_etf_risk_score(etf) - logger.info(f"Risk score for {etf['Ticker']}: {etf['risk_score']:.2f}") - # Sort ETFs by yield (higher yield = higher risk) sorted_etfs = sorted(etf_metrics, key=lambda x: x.get('Yield (%)', 0), reverse=True) logger.info(f"Sorted ETFs by yield: {[etf['Ticker'] for etf in sorted_etfs]}") @@ -489,29 +484,55 @@ def optimize_portfolio_allocation(etf_metrics: List[Dict[str, Any]], risk_tolera if risk_tolerance == "Conservative": # For conservative, allocate more to lower yielding ETFs - # This will require more capital to achieve the same income - base_allocations = [0.4] + [0.3] + [0.2] + [0.1] + [0.0] * (num_etfs - 4) + # This naturally requires more capital for the same income + base_allocations = [] + remaining_alloc = 100 + for i in range(num_etfs): + if i < num_etfs - 1: + # Allocate more to lower yielding ETFs + alloc = remaining_alloc * 0.4 # 40% of remaining + base_allocations.append(alloc) + remaining_alloc -= alloc + else: + # Last ETF gets remaining allocation + base_allocations.append(remaining_alloc) + elif risk_tolerance == "Moderate": - # For moderate, balance between yield and risk - base_allocations = [0.3] + [0.3] + [0.2] + [0.2] + [0.0] * (num_etfs - 4) + # For moderate, allocate more to middle yielding ETFs + # This naturally requires medium capital for the same income + base_allocations = [] + remaining_alloc = 100 + for i in range(num_etfs): + if i < num_etfs - 1: + # Allocate more to middle yielding ETFs + alloc = remaining_alloc * 0.5 # 50% of remaining + base_allocations.append(alloc) + remaining_alloc -= alloc + else: + # Last ETF gets remaining allocation + base_allocations.append(remaining_alloc) + else: # Aggressive # For aggressive, allocate more to higher yielding ETFs - # This will require less capital to achieve the same income - base_allocations = [0.4] + [0.3] + [0.2] + [0.1] + [0.0] * (num_etfs - 4) - - # Adjust allocations based on number of ETFs - if num_etfs < len(base_allocations): - base_allocations = base_allocations[:num_etfs] - # Normalize to ensure sum is 1 - total = sum(base_allocations) - base_allocations = [alloc/total for alloc in base_allocations] + # This naturally requires less capital for the same income + base_allocations = [] + remaining_alloc = 100 + for i in range(num_etfs): + if i < num_etfs - 1: + # Allocate more to higher yielding ETFs + alloc = remaining_alloc * 0.6 # 60% of remaining + base_allocations.append(alloc) + remaining_alloc -= alloc + else: + # Last ETF gets remaining allocation + base_allocations.append(remaining_alloc) # Create final allocation list final_allocations = [] for etf, allocation in zip(sorted_etfs, base_allocations): final_allocations.append({ "ticker": etf["Ticker"], - "allocation": allocation * 100 # Convert to percentage + "allocation": allocation # Already in percentage }) logger.info(f"Final allocations: {final_allocations}") @@ -1217,7 +1238,7 @@ def allocate_for_income(df: pd.DataFrame, target: float, etf_allocations: List[D logger.error("Weighted yield is zero") return None - # Calculate required capital + # Calculate required capital based on weighted yield required_capital = (annual_income / weighted_yield) * 100 # Calculate capital allocation and income