refactor: update app code for domain-scoped schema migration
Some checks failed
CI / lint-and-test (pull_request) Has been cancelled

- Update dbt model references to use new schema naming (stg_toronto, int_toronto, mart_toronto)
- Refactor figure factories to use consistent column naming from new schema
- Update callbacks to work with refactored data structures
- Add centralized design tokens module for consistent styling
- Streamline CLAUDE.md documentation

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-02-02 17:00:30 -05:00
parent cda2a078d9
commit dfa5f92d8a
21 changed files with 618 additions and 407 deletions

View File

@@ -6,6 +6,17 @@ import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from portfolio_app.design import (
CHART_PALETTE,
COLOR_NEGATIVE,
COLOR_POSITIVE,
GRID_COLOR,
PAPER_BG,
PLOT_BG,
TEXT_PRIMARY,
TEXT_SECONDARY,
)
def create_ranking_bar(
data: list[dict[str, Any]],
@@ -14,8 +25,8 @@ def create_ranking_bar(
title: str | None = None,
top_n: int = 10,
bottom_n: int = 10,
color_top: str = "#4CAF50",
color_bottom: str = "#F44336",
color_top: str = COLOR_POSITIVE,
color_bottom: str = COLOR_NEGATIVE,
value_format: str = ",.0f",
) -> go.Figure:
"""Create horizontal bar chart showing top and bottom rankings.
@@ -87,10 +98,10 @@ def create_ranking_bar(
barmode="group",
showlegend=True,
legend={"orientation": "h", "yanchor": "bottom", "y": 1.02},
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
xaxis={"gridcolor": "rgba(128,128,128,0.2)", "title": None},
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={"gridcolor": GRID_COLOR, "title": None},
yaxis={"autorange": "reversed", "title": None},
margin={"l": 10, "r": 10, "t": 40, "b": 10},
)
@@ -126,10 +137,10 @@ def create_stacked_bar(
df = pd.DataFrame(data)
# Default color scheme
# Default color scheme using accessible palette
if color_map is None:
categories = df[category_column].unique()
colors = px.colors.qualitative.Set2[: len(categories)]
colors = CHART_PALETTE[: len(categories)]
color_map = dict(zip(categories, colors, strict=False))
fig = px.bar(
@@ -147,11 +158,11 @@ def create_stacked_bar(
fig.update_layout(
title=title,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
xaxis={"gridcolor": "rgba(128,128,128,0.2)", "title": None},
yaxis={"gridcolor": "rgba(128,128,128,0.2)", "title": None},
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={"gridcolor": GRID_COLOR, "title": None},
yaxis={"gridcolor": GRID_COLOR, "title": None},
legend={"orientation": "h", "yanchor": "bottom", "y": 1.02},
margin={"l": 10, "r": 10, "t": 60, "b": 10},
)
@@ -164,7 +175,7 @@ def create_horizontal_bar(
name_column: str,
value_column: str,
title: str | None = None,
color: str = "#2196F3",
color: str = CHART_PALETTE[0],
value_format: str = ",.0f",
sort: bool = True,
) -> go.Figure:
@@ -204,10 +215,10 @@ def create_horizontal_bar(
fig.update_layout(
title=title,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
xaxis={"gridcolor": "rgba(128,128,128,0.2)", "title": None},
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={"gridcolor": GRID_COLOR, "title": None},
yaxis={"title": None},
margin={"l": 10, "r": 10, "t": 40, "b": 10},
)
@@ -225,13 +236,13 @@ def _create_empty_figure(title: str) -> go.Figure:
x=0.5,
y=0.5,
showarrow=False,
font={"size": 14, "color": "#888888"},
font={"size": 14, "color": TEXT_SECONDARY},
)
fig.update_layout(
title=title,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={"visible": False},
yaxis={"visible": False},
)

View File

@@ -5,6 +5,13 @@ from typing import Any
import plotly.express as px
import plotly.graph_objects as go
from portfolio_app.design import (
PAPER_BG,
PLOT_BG,
TEXT_PRIMARY,
TEXT_SECONDARY,
)
def create_choropleth_figure(
geojson: dict[str, Any] | None,
@@ -55,9 +62,9 @@ def create_choropleth_figure(
margin={"l": 0, "r": 0, "t": 40, "b": 0},
title=title or "Toronto Housing Map",
height=500,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
)
fig.add_annotation(
text="No geometry data available. Complete QGIS digitization to enable map.",
@@ -66,7 +73,7 @@ def create_choropleth_figure(
x=0.5,
y=0.5,
showarrow=False,
font={"size": 14, "color": "#888888"},
font={"size": 14, "color": TEXT_SECONDARY},
)
return fig
@@ -98,17 +105,17 @@ def create_choropleth_figure(
margin={"l": 0, "r": 0, "t": 40, "b": 0},
title=title,
height=500,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
coloraxis_colorbar={
"title": {
"text": color_column.replace("_", " ").title(),
"font": {"color": "#c9c9c9"},
"font": {"color": TEXT_PRIMARY},
},
"thickness": 15,
"len": 0.7,
"tickfont": {"color": "#c9c9c9"},
"tickfont": {"color": TEXT_PRIMARY},
},
)

View File

@@ -5,6 +5,16 @@ from typing import Any
import pandas as pd
import plotly.graph_objects as go
from portfolio_app.design import (
CHART_PALETTE,
GRID_COLOR,
PALETTE_GENDER,
PAPER_BG,
PLOT_BG,
TEXT_PRIMARY,
TEXT_SECONDARY,
)
def create_age_pyramid(
data: list[dict[str, Any]],
@@ -52,7 +62,7 @@ def create_age_pyramid(
x=male_values_neg,
orientation="h",
name="Male",
marker_color="#2196F3",
marker_color=PALETTE_GENDER["male"],
hovertemplate="%{y}<br>Male: %{customdata:,}<extra></extra>",
customdata=male_values,
)
@@ -65,7 +75,7 @@ def create_age_pyramid(
x=female_values,
orientation="h",
name="Female",
marker_color="#E91E63",
marker_color=PALETTE_GENDER["female"],
hovertemplate="%{y}<br>Female: %{x:,}<extra></extra>",
)
)
@@ -77,12 +87,12 @@ def create_age_pyramid(
title=title,
barmode="overlay",
bargap=0.1,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={
"title": "Population",
"gridcolor": "rgba(128,128,128,0.2)",
"gridcolor": GRID_COLOR,
"range": [-max_val * 1.1, max_val * 1.1],
"tickvals": [-max_val, -max_val / 2, 0, max_val / 2, max_val],
"ticktext": [
@@ -93,7 +103,7 @@ def create_age_pyramid(
f"{max_val:,.0f}",
],
},
yaxis={"title": None, "gridcolor": "rgba(128,128,128,0.2)"},
yaxis={"title": None, "gridcolor": GRID_COLOR},
legend={"orientation": "h", "yanchor": "bottom", "y": 1.02},
margin={"l": 10, "r": 10, "t": 60, "b": 10},
)
@@ -127,17 +137,9 @@ def create_donut_chart(
df = pd.DataFrame(data)
# Use accessible palette by default
if colors is None:
colors = [
"#2196F3",
"#4CAF50",
"#FF9800",
"#E91E63",
"#9C27B0",
"#00BCD4",
"#FFC107",
"#795548",
]
colors = CHART_PALETTE
fig = go.Figure(
go.Pie(
@@ -153,8 +155,8 @@ def create_donut_chart(
fig.update_layout(
title=title,
paper_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
font_color=TEXT_PRIMARY,
showlegend=False,
margin={"l": 10, "r": 10, "t": 60, "b": 10},
)
@@ -167,7 +169,7 @@ def create_income_distribution(
bracket_column: str,
count_column: str,
title: str | None = None,
color: str = "#4CAF50",
color: str = CHART_PALETTE[3], # Teal
) -> go.Figure:
"""Create histogram-style bar chart for income distribution.
@@ -199,17 +201,17 @@ def create_income_distribution(
fig.update_layout(
title=title,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={
"title": "Income Bracket",
"gridcolor": "rgba(128,128,128,0.2)",
"gridcolor": GRID_COLOR,
"tickangle": -45,
},
yaxis={
"title": "Households",
"gridcolor": "rgba(128,128,128,0.2)",
"gridcolor": GRID_COLOR,
},
margin={"l": 10, "r": 10, "t": 60, "b": 80},
)
@@ -227,13 +229,13 @@ def _create_empty_figure(title: str) -> go.Figure:
x=0.5,
y=0.5,
showarrow=False,
font={"size": 14, "color": "#888888"},
font={"size": 14, "color": TEXT_SECONDARY},
)
fig.update_layout(
title=title,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={"visible": False},
yaxis={"visible": False},
)

View File

@@ -4,6 +4,14 @@ from typing import Any
import plotly.graph_objects as go
from portfolio_app.design import (
CHART_PALETTE,
GRID_COLOR_DARK,
PAPER_BG,
TEXT_PRIMARY,
TEXT_SECONDARY,
)
def create_radar_figure(
data: list[dict[str, Any]],
@@ -32,16 +40,9 @@ def create_radar_figure(
if not data or not metrics:
return _create_empty_figure(title or "Radar Chart")
# Default colors
# Use accessible palette by default
if colors is None:
colors = [
"#2196F3",
"#4CAF50",
"#FF9800",
"#E91E63",
"#9C27B0",
"#00BCD4",
]
colors = CHART_PALETTE
fig = go.Figure()
@@ -78,19 +79,19 @@ def create_radar_figure(
polar={
"radialaxis": {
"visible": True,
"gridcolor": "rgba(128,128,128,0.3)",
"linecolor": "rgba(128,128,128,0.3)",
"tickfont": {"color": "#c9c9c9"},
"gridcolor": GRID_COLOR_DARK,
"linecolor": GRID_COLOR_DARK,
"tickfont": {"color": TEXT_PRIMARY},
},
"angularaxis": {
"gridcolor": "rgba(128,128,128,0.3)",
"linecolor": "rgba(128,128,128,0.3)",
"tickfont": {"color": "#c9c9c9"},
"gridcolor": GRID_COLOR_DARK,
"linecolor": GRID_COLOR_DARK,
"tickfont": {"color": TEXT_PRIMARY},
},
"bgcolor": "rgba(0,0,0,0)",
"bgcolor": PAPER_BG,
},
paper_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
font_color=TEXT_PRIMARY,
showlegend=len(data) > 1,
legend={"orientation": "h", "yanchor": "bottom", "y": -0.2},
margin={"l": 40, "r": 40, "t": 60, "b": 40},
@@ -133,7 +134,7 @@ def create_comparison_radar(
metrics=metrics,
name_column="__name__",
title=title,
colors=["#4CAF50", "#9E9E9E"],
colors=[CHART_PALETTE[3], TEXT_SECONDARY], # Teal for selected, gray for avg
)
@@ -156,11 +157,11 @@ def _create_empty_figure(title: str) -> go.Figure:
x=0.5,
y=0.5,
showarrow=False,
font={"size": 14, "color": "#888888"},
font={"size": 14, "color": TEXT_SECONDARY},
)
fig.update_layout(
title=title,
paper_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
font_color=TEXT_PRIMARY,
)
return fig

View File

@@ -6,6 +6,15 @@ import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
from portfolio_app.design import (
CHART_PALETTE,
GRID_COLOR,
PAPER_BG,
PLOT_BG,
TEXT_PRIMARY,
TEXT_SECONDARY,
)
def create_scatter_figure(
data: list[dict[str, Any]],
@@ -72,21 +81,21 @@ def create_scatter_figure(
if trendline:
fig.update_traces(
selector={"mode": "lines"},
line={"color": "#FF9800", "dash": "dash", "width": 2},
line={"color": CHART_PALETTE[1], "dash": "dash", "width": 2},
)
fig.update_layout(
title=title,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={
"gridcolor": "rgba(128,128,128,0.2)",
"gridcolor": GRID_COLOR,
"title": x_title or x_column.replace("_", " ").title(),
"zeroline": False,
},
yaxis={
"gridcolor": "rgba(128,128,128,0.2)",
"gridcolor": GRID_COLOR,
"title": y_title or y_column.replace("_", " ").title(),
"zeroline": False,
},
@@ -140,19 +149,20 @@ def create_bubble_chart(
hover_name=name_column,
size_max=size_max,
opacity=0.7,
color_discrete_sequence=CHART_PALETTE,
)
fig.update_layout(
title=title,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={
"gridcolor": "rgba(128,128,128,0.2)",
"gridcolor": GRID_COLOR,
"title": x_title or x_column.replace("_", " ").title(),
},
yaxis={
"gridcolor": "rgba(128,128,128,0.2)",
"gridcolor": GRID_COLOR,
"title": y_title or y_column.replace("_", " ").title(),
},
margin={"l": 10, "r": 10, "t": 40, "b": 10},
@@ -171,13 +181,13 @@ def _create_empty_figure(title: str) -> go.Figure:
x=0.5,
y=0.5,
showarrow=False,
font={"size": 14, "color": "#888888"},
font={"size": 14, "color": TEXT_SECONDARY},
)
fig.update_layout(
title=title,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={"visible": False},
yaxis={"visible": False},
)

View File

@@ -4,6 +4,14 @@ from typing import Any
import plotly.graph_objects as go
from portfolio_app.design import (
COLOR_NEGATIVE,
COLOR_POSITIVE,
PAPER_BG,
PLOT_BG,
TEXT_PRIMARY,
)
def create_metric_card_figure(
value: float | int | str,
@@ -59,8 +67,12 @@ def create_metric_card_figure(
"relative": False,
"valueformat": ".1f",
"suffix": delta_suffix,
"increasing": {"color": "green" if positive_is_good else "red"},
"decreasing": {"color": "red" if positive_is_good else "green"},
"increasing": {
"color": COLOR_POSITIVE if positive_is_good else COLOR_NEGATIVE
},
"decreasing": {
"color": COLOR_NEGATIVE if positive_is_good else COLOR_POSITIVE
},
}
fig.add_trace(go.Indicator(**indicator_config))
@@ -68,9 +80,9 @@ def create_metric_card_figure(
fig.update_layout(
height=120,
margin={"l": 20, "r": 20, "t": 40, "b": 20},
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font={"family": "Inter, sans-serif", "color": "#c9c9c9"},
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font={"family": "Inter, sans-serif", "color": TEXT_PRIMARY},
)
return fig

View File

@@ -5,6 +5,15 @@ from typing import Any
import plotly.express as px
import plotly.graph_objects as go
from portfolio_app.design import (
CHART_PALETTE,
GRID_COLOR,
PAPER_BG,
PLOT_BG,
TEXT_PRIMARY,
TEXT_SECONDARY,
)
def create_price_time_series(
data: list[dict[str, Any]],
@@ -38,14 +47,14 @@ def create_price_time_series(
x=0.5,
y=0.5,
showarrow=False,
font={"color": "#888888"},
font={"color": TEXT_SECONDARY},
)
fig.update_layout(
title=title,
height=350,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
)
return fig
@@ -59,6 +68,7 @@ def create_price_time_series(
y=price_column,
color=group_column,
title=title,
color_discrete_sequence=CHART_PALETTE,
)
else:
fig = px.line(
@@ -67,6 +77,7 @@ def create_price_time_series(
y=price_column,
title=title,
)
fig.update_traces(line_color=CHART_PALETTE[0])
fig.update_layout(
height=350,
@@ -76,11 +87,11 @@ def create_price_time_series(
yaxis_tickprefix="$",
yaxis_tickformat=",",
hovermode="x unified",
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
xaxis={"gridcolor": "#333333", "linecolor": "#444444"},
yaxis={"gridcolor": "#333333", "linecolor": "#444444"},
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={"gridcolor": GRID_COLOR, "linecolor": GRID_COLOR},
yaxis={"gridcolor": GRID_COLOR, "linecolor": GRID_COLOR},
)
return fig
@@ -118,14 +129,14 @@ def create_volume_time_series(
x=0.5,
y=0.5,
showarrow=False,
font={"color": "#888888"},
font={"color": TEXT_SECONDARY},
)
fig.update_layout(
title=title,
height=350,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
)
return fig
@@ -140,6 +151,7 @@ def create_volume_time_series(
y=volume_column,
color=group_column,
title=title,
color_discrete_sequence=CHART_PALETTE,
)
else:
fig = px.bar(
@@ -148,6 +160,7 @@ def create_volume_time_series(
y=volume_column,
title=title,
)
fig.update_traces(marker_color=CHART_PALETTE[0])
else:
if group_column and group_column in df.columns:
fig = px.line(
@@ -156,6 +169,7 @@ def create_volume_time_series(
y=volume_column,
color=group_column,
title=title,
color_discrete_sequence=CHART_PALETTE,
)
else:
fig = px.line(
@@ -164,6 +178,7 @@ def create_volume_time_series(
y=volume_column,
title=title,
)
fig.update_traces(line_color=CHART_PALETTE[0])
fig.update_layout(
height=350,
@@ -172,11 +187,11 @@ def create_volume_time_series(
yaxis_title=volume_column.replace("_", " ").title(),
yaxis_tickformat=",",
hovermode="x unified",
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
xaxis={"gridcolor": "#333333", "linecolor": "#444444"},
yaxis={"gridcolor": "#333333", "linecolor": "#444444"},
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={"gridcolor": GRID_COLOR, "linecolor": GRID_COLOR},
yaxis={"gridcolor": GRID_COLOR, "linecolor": GRID_COLOR},
)
return fig
@@ -211,14 +226,14 @@ def create_market_comparison_chart(
x=0.5,
y=0.5,
showarrow=False,
font={"color": "#888888"},
font={"color": TEXT_SECONDARY},
)
fig.update_layout(
title=title,
height=400,
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
)
return fig
@@ -230,8 +245,6 @@ def create_market_comparison_chart(
fig = make_subplots(specs=[[{"secondary_y": True}]])
colors = ["#1f77b4", "#ff7f0e", "#2ca02c", "#d62728"]
for i, metric in enumerate(metrics[:4]):
if metric not in df.columns:
continue
@@ -242,7 +255,7 @@ def create_market_comparison_chart(
x=df[date_column],
y=df[metric],
name=metric.replace("_", " ").title(),
line={"color": colors[i % len(colors)]},
line={"color": CHART_PALETTE[i % len(CHART_PALETTE)]},
),
secondary_y=secondary,
)
@@ -252,18 +265,18 @@ def create_market_comparison_chart(
height=400,
margin={"l": 40, "r": 40, "t": 50, "b": 40},
hovermode="x unified",
paper_bgcolor="rgba(0,0,0,0)",
plot_bgcolor="rgba(0,0,0,0)",
font_color="#c9c9c9",
xaxis={"gridcolor": "#333333", "linecolor": "#444444"},
yaxis={"gridcolor": "#333333", "linecolor": "#444444"},
paper_bgcolor=PAPER_BG,
plot_bgcolor=PLOT_BG,
font_color=TEXT_PRIMARY,
xaxis={"gridcolor": GRID_COLOR, "linecolor": GRID_COLOR},
yaxis={"gridcolor": GRID_COLOR, "linecolor": GRID_COLOR},
legend={
"orientation": "h",
"yanchor": "bottom",
"y": 1.02,
"xanchor": "right",
"x": 1,
"font": {"color": "#c9c9c9"},
"font": {"color": TEXT_PRIMARY},
},
)
@@ -290,13 +303,13 @@ def add_policy_markers(
if not policy_events:
return fig
# Color mapping for policy categories
# Color mapping for policy categories using design tokens
category_colors = {
"monetary": "#1f77b4", # Blue
"tax": "#2ca02c", # Green
"regulatory": "#ff7f0e", # Orange
"supply": "#9467bd", # Purple
"economic": "#d62728", # Red
"monetary": CHART_PALETTE[0], # Blue
"tax": CHART_PALETTE[3], # Teal/green
"regulatory": CHART_PALETTE[1], # Orange
"supply": CHART_PALETTE[6], # Pink
"economic": CHART_PALETTE[5], # Vermillion
}
# Symbol mapping for expected direction
@@ -313,7 +326,7 @@ def add_policy_markers(
title = event.get("title", "Policy Event")
level = event.get("level", "federal")
color = category_colors.get(category, "#666666")
color = category_colors.get(category, TEXT_SECONDARY)
symbol = direction_symbols.get(direction, "circle")
# Add vertical line for the event
@@ -335,7 +348,7 @@ def add_policy_markers(
"symbol": symbol,
"size": 12,
"color": color,
"line": {"width": 1, "color": "white"},
"line": {"width": 1, "color": TEXT_PRIMARY},
},
name=title,
hovertemplate=(