feat: Sprint 6 polish - methodology, demo data, deployment prep
- Add policy event markers to time series charts - Create methodology page (/toronto/methodology) with data sources - Add demo data module for testing without full pipeline - Update README with project documentation - Add health check endpoint (/health) - Add database initialization script - Export new figure factory functions Closes #21 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,12 +1,31 @@
|
||||
"""Plotly figure factories for data visualization."""
|
||||
|
||||
from .choropleth import create_choropleth_figure
|
||||
from .summary_cards import create_metric_card_figure
|
||||
from .time_series import create_price_time_series, create_volume_time_series
|
||||
from .choropleth import (
|
||||
create_choropleth_figure,
|
||||
create_district_map,
|
||||
create_zone_map,
|
||||
)
|
||||
from .summary_cards import create_metric_card_figure, create_summary_metrics
|
||||
from .time_series import (
|
||||
add_policy_markers,
|
||||
create_market_comparison_chart,
|
||||
create_price_time_series,
|
||||
create_time_series_with_events,
|
||||
create_volume_time_series,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
# Choropleth
|
||||
"create_choropleth_figure",
|
||||
"create_district_map",
|
||||
"create_zone_map",
|
||||
# Time series
|
||||
"create_price_time_series",
|
||||
"create_volume_time_series",
|
||||
"create_market_comparison_chart",
|
||||
"create_time_series_with_events",
|
||||
"add_policy_markers",
|
||||
# Summary
|
||||
"create_metric_card_figure",
|
||||
"create_summary_metrics",
|
||||
]
|
||||
|
||||
@@ -231,3 +231,119 @@ def create_market_comparison_chart(
|
||||
)
|
||||
|
||||
return fig
|
||||
|
||||
|
||||
def add_policy_markers(
|
||||
fig: go.Figure,
|
||||
policy_events: list[dict[str, Any]],
|
||||
date_column: str = "event_date",
|
||||
y_position: float | None = None,
|
||||
) -> go.Figure:
|
||||
"""Add policy event markers to an existing time series figure.
|
||||
|
||||
Args:
|
||||
fig: Existing Plotly figure to add markers to.
|
||||
policy_events: List of policy event dicts with date and metadata.
|
||||
date_column: Column name for event dates.
|
||||
y_position: Y position for markers. If None, uses top of chart.
|
||||
|
||||
Returns:
|
||||
Updated Plotly Figure object with policy markers.
|
||||
"""
|
||||
if not policy_events:
|
||||
return fig
|
||||
|
||||
# Color mapping for policy categories
|
||||
category_colors = {
|
||||
"monetary": "#1f77b4", # Blue
|
||||
"tax": "#2ca02c", # Green
|
||||
"regulatory": "#ff7f0e", # Orange
|
||||
"supply": "#9467bd", # Purple
|
||||
"economic": "#d62728", # Red
|
||||
}
|
||||
|
||||
# Symbol mapping for expected direction
|
||||
direction_symbols = {
|
||||
"bullish": "triangle-up",
|
||||
"bearish": "triangle-down",
|
||||
"neutral": "circle",
|
||||
}
|
||||
|
||||
for event in policy_events:
|
||||
event_date = event.get(date_column)
|
||||
category = event.get("category", "economic")
|
||||
direction = event.get("expected_direction", "neutral")
|
||||
title = event.get("title", "Policy Event")
|
||||
level = event.get("level", "federal")
|
||||
|
||||
color = category_colors.get(category, "#666666")
|
||||
symbol = direction_symbols.get(direction, "circle")
|
||||
|
||||
# Add vertical line for the event
|
||||
fig.add_vline(
|
||||
x=event_date,
|
||||
line_dash="dot",
|
||||
line_color=color,
|
||||
opacity=0.5,
|
||||
annotation_text="",
|
||||
)
|
||||
|
||||
# Add marker with hover info
|
||||
fig.add_trace(
|
||||
go.Scatter(
|
||||
x=[event_date],
|
||||
y=[y_position] if y_position else [None], # type: ignore[list-item]
|
||||
mode="markers",
|
||||
marker={
|
||||
"symbol": symbol,
|
||||
"size": 12,
|
||||
"color": color,
|
||||
"line": {"width": 1, "color": "white"},
|
||||
},
|
||||
name=title,
|
||||
hovertemplate=(
|
||||
f"<b>{title}</b><br>"
|
||||
f"Date: %{{x}}<br>"
|
||||
f"Level: {level.title()}<br>"
|
||||
f"Category: {category.title()}<br>"
|
||||
f"<extra></extra>"
|
||||
),
|
||||
showlegend=False,
|
||||
)
|
||||
)
|
||||
|
||||
return fig
|
||||
|
||||
|
||||
def create_time_series_with_events(
|
||||
data: list[dict[str, Any]],
|
||||
policy_events: list[dict[str, Any]],
|
||||
date_column: str = "full_date",
|
||||
value_column: str = "avg_price",
|
||||
title: str = "Price Trend with Policy Events",
|
||||
) -> go.Figure:
|
||||
"""Create a time series chart with policy event markers.
|
||||
|
||||
Args:
|
||||
data: Time series data.
|
||||
policy_events: Policy events to overlay.
|
||||
date_column: Column name for dates.
|
||||
value_column: Column name for values.
|
||||
title: Chart title.
|
||||
|
||||
Returns:
|
||||
Plotly Figure with time series and policy markers.
|
||||
"""
|
||||
# Create base time series
|
||||
fig = create_price_time_series(
|
||||
data=data,
|
||||
date_column=date_column,
|
||||
price_column=value_column,
|
||||
title=title,
|
||||
)
|
||||
|
||||
# Add policy markers at the top of the chart
|
||||
if policy_events:
|
||||
fig = add_policy_markers(fig, policy_events)
|
||||
|
||||
return fig
|
||||
|
||||
Reference in New Issue
Block a user