import plotly.graph_objects as go
import pandas as pd
# 2. Define node labels and indices (the order determines positions)
# Indices: 0-Start, 1-Excluded, 2-Eligible, 3-Won P1, 4-Lost P1,
# 5-Consistent P1/P2, 6-P1 Winner/P2 Loser, 7-P2 Only Winner, 8-P1 Loser/P2 Loser
node_labels = [
"Russell 1000 (Start)",
"Excluded (<$30B)",
"Eligible Large-Caps",
"Outperform P1",
"Underperform P1",
"Consistent Outperformance (95)", # Highlight this node
"P1 Outperform, P2 Underperform",
"Outperform P2 Only (35)", # This preserves your total of 130 (95 + 35)
"Underperform Both"
]
# (Simplified color definition for clarity, real chart uses gradients)
node_colors = ["#444", "#888", "#226B80", "#E0816C", "#666", "#019267", "#888", "#E0816C", "#444"]
# 3. Create the Sankey Diagram
fig = go.Figure(go.Sankey(
orientation = "h", # Keep horizontal, it flows better
node = dict(
pad = 20, # More space between nodes
thickness = 30,
line = dict(color = "#eee", width = 0.5),
label = node_labels,
color = node_colors,
# Positions: range [0,1] for x,y. You might need to refine these based on exact counts.
x = [0.05, 0.25, 0.35, 0.60, 0.60, 0.90, 0.90, 0.90, 0.90],
y = [0.5, 0.1, 0.5, 0.25, 0.75, 0.10, 0.35, 0.60, 0.85],
),
link = dict(
source = [0, 0, 2, 2, 3, 3, 4, 4], # Indices of node_labels list
target = [1, 2, 3, 4, 5, 6, 7, 8],
value = [excluded_count, eligible_count, p1_winners_count, p1_losers_count, consistent_count,
p1_winners_count - consistent_count, p2_only_winners_count, p1_losers_count - p2_only_winners_count],
color = ["#ddd", "#b1dbe1", "#ecbca2", "#eee", "#99f5cb", "#eee", "#ecbca2", "#ddd"], # Match source node colors
)
))
# 4. Format the layout
fig.update_layout(
title = dict(
text = "Finding Consistent Large-Cap Outperformers",
font_size = 20,
x=0.5
),
font = dict(family = "Arial", size = 14, color = "#333"),
# *** Resizing: Make it tall and spacious ***
margin=dict(t=150, b=50, l=50, r=50),
height = 500,
template = "plotly_white",
hovermode = 'x'
)
# 5. Add callouts to highlight the recovered 130 number
fig.add_annotation(
x=0.5, y=-0.10, text=f"Total Phase 2 Winners (130) = Consistent (95) + P2-only (35)",
showarrow=False, font=dict(color="#333", size=16),
)
fig.show()