Problem: AttributeError: 'Series' object has no attribute 'style'
Traceback:
File "/usr/local/lib/python3.10/dist-packages/streamlit/runtime/scriptrunner/exec_code.py", line 88, in exec_func_with_error_handling
result = func()
File "/usr/local/lib/python3.10/dist-packages/streamlit/runtime/scriptrunner/script_runner.py", line 579, in code_to_exec
exec(code, module.dict)
File "/content/portfolio_optimizer.py", line 4293, in
display_backtest_results(result["backtest_results"], comparison_type, portfolio1)
File "/content/portfolio_optimizer.py", line 598, in display_backtest_results
display_portfolio_vs_benchmark(results)
File "/content/portfolio_optimizer.py", line 750, in display_portfolio_vs_benchmark
styled_metrics = metrics_comparison.apply(row_formatter, axis=1).style.applymap(
File "/usr/local/lib/python3.10/dist-packages/pandas/core/generic.py", line 6299, in getattr
return object.getattribute(self, name)

if the segments code need update, please return the full updated segments code, no need import or other stuff, only the full version of the updated segment

def display_portfolio_vs_benchmark(results):
    """
    Enhanced display function for Portfolio vs Benchmark comparison with improved visualizations and UX.
    """
    # Extract data from results
    returns = results['returns']
    cum_returns = results['cum_returns']
    weights = results['weights']
    price_data = results['price_data']
    available_selected = results['available_selected']
    metrics = results['metrics']
    benchmark_metrics = results['benchmark_metrics']
    benchmark_returns = results['benchmark_returns']
    benchmark_cum_returns = results['benchmark_cum_returns']

    # Define a consistent theme for all plots
    THEMES = {
        'plotly_dark': 'plotly_dark',
        'plotly_light': 'plotly_white'
    }
    selected_theme = THEMES.get('plotly_light')  # Change as needed

    # Create tabs for better organization
    main_tab, metrics_tab, risk_tab, analysis_tab, insights_tab = st.tabs([
        "📈 Main Charts", "📊 Performance Metrics", "🎯 Risk Analysis", "🔍 Deep Analysis", "🧠 Metric-Based Insights"
    ])

    with main_tab:
        st.header("🔹 Portfolio vs Benchmark Overview")
        col1, col2 = st.columns([2, 1])
        with col1:
            st.subheader("Portfolio Composition")
            fig_composition = px.pie(
                values=weights,
                names=price_data.columns,
                title="Current Portfolio Allocation",
                template=selected_theme,
                hole=0.4
            )
            fig_composition.update_traces(textinfo='percent+label')
            st.plotly_chart(fig_composition, use_container_width=True)

        with col2:
            st.subheader("Key Performance Indicators")
            metrics_display = {
                "Total Return": f"{(cum_returns.iloc[-1] - 1) * 100:.2f}%",
                "Annualized Return": metrics.get('Annualized Return (CAGR)', 'N/A'),
                "Sharpe Ratio": metrics.get('Sharpe Ratio', 'N/A'),
                "Max Drawdown": metrics.get('Maximum Drawdown', 'N/A')
            }
            for metric, value in metrics_display.items():
                st.metric(metric, value)

        # Enhanced Cumulative Returns Plot with Interactive Features
        st.subheader("Cumulative Returns Comparison")
        fig_returns = go.Figure()
        fig_returns.add_trace(go.Scatter(
            x=cum_returns.index,
            y=cum_returns,
            name="Portfolio",
            line=dict(color='cyan', width=2),
            hovertemplate='%{y:.2f}'
        ))
        fig_returns.add_trace(go.Scatter(
            x=benchmark_cum_returns.index,
            y=benchmark_cum_returns,
            name="Benchmark",
            line=dict(color='orange', width=2, dash='dash'),
            hovertemplate='%{y:.2f}'
        ))
        fig_returns.update_layout(
            template=selected_theme,
            hovermode='x unified',
            height=500,
            xaxis_title='Date',
            yaxis_title='Cumulative Returns',
            legend=dict(x=0.01, y=0.99)
        )
        st.plotly_chart(fig_returns, use_container_width=True)

        # Interactive Summary Recommendations
        create_summary_recommendations('overview', metrics=metrics)

    with metrics_tab:
        st.header("📊 Detailed Performance Metrics")
        st.subheader("Performance Comparison Table")

        # Create comparison metrics table assuming both metrics and benchmark_metrics have same keys
        portfolio_metrics_df = pd.DataFrame(metrics.items(), columns=['Metric', 'Portfolio'])
        benchmark_metrics_df = pd.DataFrame(benchmark_metrics.items(), columns=['Metric', 'Benchmark'])
        metrics_comparison = pd.merge(portfolio_metrics_df, benchmark_metrics_df, on='Metric', how='outer')

        # Define which metrics are percentage-based
        percentage_metrics = [
            'Total Return', 'Annualized Return (CAGR)', 'Best Year', 'Worst Year',
            'Arithmetic Mean (Monthly)', 'Arithmetic Mean (Annualized)',
            'Geometric Mean (Monthly)', 'Geometric Mean (Annualized)',
            'Standard Deviation (Monthly)', 'Standard Deviation (Annualized)',
            'Downside Deviation (Monthly)', 'Maximum Drawdown',
            'Alpha (annualized)', 'Calmar Ratio',
            'Tracking Error', 'Active Return',
            'Upside Capture Ratio', 'Downside Capture Ratio'
        ]

        # Style the metrics table
        def highlight_better(row):
            styles = [''] * len(row)
            portfolio_val = row["Portfolio"]
            benchmark_val = row["Benchmark"]
            # Skip if either is N/A
            if portfolio_val == "N/A" or benchmark_val == "N/A":
                return styles
            # Convert to float if possible
            try:
                # Remove '%' and other symbols for comparison
                portfolio_num = float(str(portfolio_val).strip('%').strip('$').replace(',', ''))
                benchmark_num = float(str(benchmark_val).strip('%').strip('$').replace(',', ''))
            except:
                return styles
            # Determine if higher is better or lower is better based on metric name
            metric_name = row['Metric']
            if any(keyword in metric_name for keyword in ['Drawdown', 'Deviation', 'Tracking Error']):
                better = portfolio_num < benchmark_num
            else:
                better = portfolio_num > benchmark_num
            styles[1] = 'background-color: #d4f7d4' if better else 'background-color: #f7d4d4'
            return styles

        styled_metrics = metrics_comparison.style.apply(highlight_better, axis=1)

        # Apply the custom formatter only to numeric cells
        def custom_formatter(x, metric):
            try:
                # Attempt to convert to float after stripping possible symbols
                value = float(str(x).strip('%').strip('$').replace(',', ''))
                if metric in percentage_metrics:
                    return f"{value:.2f}%"
                else:
                    return f"{value:.2f}"
            except (ValueError, TypeError):
                return x  # Return the original value if conversion fails

        # Apply formatter row-wise to access metric name
        def row_formatter(row):
            metric = row['Metric']
            return [custom_formatter(row[col], metric) if col in ['Portfolio', 'Benchmark'] else row[col] for col in row.index]

        styled_metrics = metrics_comparison.apply(row_formatter, axis=1).style.applymap(
            lambda x: 'background-color: #d4f7d4' if 'd4f7d4' in x else ('background-color: #f7d4d4' if 'f7d4d4' in x else ''),
            subset=['Portfolio', 'Benchmark']
        )

        st.dataframe(styled_metrics, height=400)

        # Interactive Summary Recommendations
        create_summary_recommendations('comparison', metrics=metrics)

    with risk_tab:
        st.header("🎯 Risk Analysis")
        col1, col2 = st.columns([1,1])
        
        with col1:
            # Rolling Volatility with Threshold Highlighting
            st.subheader("Rolling Volatility (30-Day)")
            rolling_vol = returns.rolling(window=30).std() * np.sqrt(252)
            rolling_vol_bench = benchmark_returns.rolling(window=30).std() * np.sqrt(252)
            
            fig_vol = go.Figure()
            fig_vol.add_trace(go.Scatter(
                x=rolling_vol.index,
                y=rolling_vol,
                name="Portfolio Volatility",
                line=dict(color='cyan', width=2)
            ))
            fig_vol.add_trace(go.Scatter(
                x=rolling_vol_bench.index,
                y=rolling_vol_bench,
                name="Benchmark Volatility",
                line=dict(color='orange', width=2, dash='dash')
            ))
            fig_vol.update_layout(
                template=selected_theme,
                hovermode='x unified',
                height=400,
                xaxis_title='Date',
                yaxis_title='Annualized Volatility',
                legend=dict(x=0.01, y=0.99)
            )
            st.plotly_chart(fig_vol, use_container_width=True)

        with col2:
            # Rolling Beta with Interactive Thresholds
            st.subheader("Rolling Beta (30-Day)")
            # Rolling correlation is used to compute beta
            rolling_cov = returns.rolling(window=30).cov(benchmark_returns)
            rolling_var = benchmark_returns.rolling(window=30).var()
            rolling_beta = rolling_cov / rolling_var
            
            fig_beta = px.line(
                rolling_beta,
                title="30-Day Rolling Beta",
                labels={"index": "Date", "value": "Beta"},
                template=selected_theme
            )
            fig_beta.update_traces(line=dict(color='green'))
            fig_beta.update_layout(
                hovermode='x unified',
                height=400,
                xaxis_title='Date',
                yaxis_title='Beta'
            )
            st.plotly_chart(fig_beta, use_container_width=True)

        # Risk Contribution Analysis with Interactive Filters
        st.subheader("Risk Contribution Analysis")
        col3, col4 = st.columns([1,1])
        
        with col3:
            # Risk Contribution for Portfolio
            risk_contrib = calculate_risk_contribution(price_data[available_selected].pct_change().dropna(), weights)
            risk_contrib_df = pd.DataFrame({
                'Asset': price_data.columns,
                'Risk Contribution (%)': risk_contrib * 100
            }).sort_values(by='Risk Contribution (%)', ascending=False)
            
            fig_risk = px.bar(
                risk_contrib_df,
                x='Asset',
                y='Risk Contribution (%)',
                title="Risk Contribution by Asset",
                labels={'Risk Contribution (%)': 'Risk Contribution (%)'},
                template=selected_theme,
                color='Risk Contribution (%)',
                color_continuous_scale='Viridis'
            )
            fig_risk.update_layout(
                xaxis_title='Asset',
                yaxis_title='Risk Contribution (%)',
                height=400
            )
            st.plotly_chart(fig_risk, use_container_width=True)

        with col4:
            # Diversification Index
            st.subheader("Diversification Overview")
            diversification = calculate_diversification_index(risk_contrib)
            st.metric("Diversification Index", f"{diversification:.2f}/1.00", help="Higher values indicate better diversification.")
            
            # Optional: Display diversification gauge
            fig_diversification = go.Figure(go.Indicator(
                mode = "gauge+number",
                value = diversification,
                title = {'text': "Diversification Index"},
                gauge = {
                    'axis': {'range': [0, 1]},
                    'bar': {'color': "darkblue"},
                    'steps' : [
                        {'range': [0, 0.5], 'color': "lightcoral"},
                        {'range': [0.5, 1], 'color': "lightgreen"}],
                    'threshold': {
                        'line': {'color': "black", 'width': 4},
                        'thickness': 0.75,
                        'value': diversification}
                }
            ))
            fig_diversification.update_layout(template=selected_theme, height=300)
            st.plotly_chart(fig_diversification, use_container_width=True)

        # Interactive Summary Recommendations
        create_summary_recommendations('risk', metrics=metrics)

    with analysis_tab:
        st.header("🔍 Deep Analysis")
        col1, col2 = st.columns([1,1])
        
        with col1:
            # Monthly Returns Heatmap with Enhanced Color Scale
            st.subheader("Monthly Returns Heatmap")
            monthly_returns = returns.resample('M').agg(lambda x: (1 + x).prod() - 1)
            monthly_returns_matrix = monthly_returns.groupby([monthly_returns.index.year, monthly_returns.index.month]).first().unstack()
            
            fig_heatmap = px.imshow(
                monthly_returns_matrix,
                labels=dict(x="Month", y="Year", color="Returns"),
                color_continuous_scale="RdYlGn",
                title="Monthly Returns Heatmap",
                template=selected_theme
            )
            fig_heatmap.update_layout(
                xaxis_title='Month',
                yaxis_title='Year',
                height=500
            )
            st.plotly_chart(fig_heatmap, use_container_width=True)

        with col2:
            # Rolling Correlation with Benchmark
            st.subheader("Rolling Correlation with Benchmark (30-Day)")
            rolling_corr = returns.rolling(window=30).corr(benchmark_returns)
            
            fig_corr = px.line(
                rolling_corr,
                title="30-Day Rolling Correlation with Benchmark",
                labels={"index": "Date", "value": "Correlation"},
                template=selected_theme
            )
            fig_corr.update_traces(line=dict(color='purple'))
            fig_corr.update_layout(
                hovermode='x unified',
                height=500,
                xaxis_title='Date',
                yaxis_title='Correlation'
            )
            st.plotly_chart(fig_corr, use_container_width=True)

        # Risk Contribution Detailed Analysis
        st.subheader("Detailed Risk Contribution Analysis")
        risk_contrib = calculate_risk_contribution(price_data[available_selected].pct_change().dropna(), weights)
        fig_risk_detailed = px.scatter(
            x=price_data.columns,
            y=risk_contrib * 100,
            size=(risk_contrib * 100),
            color=price_data.columns,
            hover_name=price_data.columns,
            title="Risk Contribution by Asset",
            labels={'x': 'Asset', 'y': 'Risk Contribution (%)'},
            template=selected_theme
        )
        fig_risk_detailed.update_layout(
            xaxis_title='Asset',
            yaxis_title='Risk Contribution (%)',
            height=600
        )
        st.plotly_chart(fig_risk_detailed, use_container_width=True)

        # Interactive Summary Recommendations
        create_summary_recommendations('deep', metrics=metrics)

    with insights_tab:
        st.header("🧠 Metric-Based Insights")
        st.subheader("Performance Insights")

        # Example Insights Based on Metrics
        insights = []

        # Insight on Sharpe Ratio
        sharpe_ratio = metrics.get('Sharpe Ratio', None)
        if sharpe_ratio and sharpe_ratio != "N/A":
            if float(sharpe_ratio) > 1:
                insights.append("Your portfolio has an excellent Sharpe Ratio, indicating a favorable risk-adjusted return.")
            elif 0.5 < float(sharpe_ratio) <= 1:
                insights.append("Your portfolio has a good Sharpe Ratio, suggesting a reasonable risk-adjusted return.")
            else:
                insights.append("Consider reviewing your portfolio's risk and return balance, as the Sharpe Ratio is below optimal levels.")

        # Insight on Maximum Drawdown
        max_drawdown = metrics.get('Maximum Drawdown', None)
        if max_drawdown and max_drawdown != "N/A":
            if float(max_drawdown.strip('%')) < 10:
                insights.append("Your portfolio experienced minimal drawdowns, indicating strong capital preservation.")
            elif 10 <= float(max_drawdown.strip('%')) < 20:
                insights.append("Your portfolio has moderate drawdowns. Monitoring and risk management could enhance performance.")
            else:
                insights.append("Significant drawdowns observed. Evaluating risk management strategies is recommended.")

        # Insight on Beta
        beta = metrics.get('Beta', None)
        if beta and beta != "N/A":
            if float(beta) > 1:
                insights.append("Your portfolio is more volatile than the benchmark, which may amplify returns and losses.")
            elif float(beta) < 1:
                insights.append("Your portfolio is less volatile than the benchmark, providing some downside protection.")
            else:
                insights.append("Your portfolio's volatility matches that of the benchmark.")

        # Display Insights
        if insights:
            for insight in insights:
                st.markdown(f"• {insight}")
        else:
            st.markdown("No significant insights available based on the current metrics.")

        # Additional Insights can be added similarly based on other metrics

        # Interactive Summary Recommendations
        create_summary_recommendations('insights', metrics=metrics)