diff --git a/.streamlit/config.toml b/.streamlit/config.toml
new file mode 100644
index 0000000..df3ef0c
--- /dev/null
+++ b/.streamlit/config.toml
@@ -0,0 +1,6 @@
+[theme]
+primaryColor = "#1B4F8A"
+backgroundColor = "#F0F4F9"
+secondaryBackgroundColor = "#E4EBF4"
+textColor = "#1A1A1A"
+font = "serif"
diff --git a/Homepage.py b/Homepage.py
index 08b2250..b14427b 100644
--- a/Homepage.py
+++ b/Homepage.py
@@ -13,25 +13,57 @@
st.set_page_config(page_title="Weekly U.S. Petroleum Supply", layout="wide")
# =========================
-# Sidebar title
+# Sidebar title (above nav via CSS)
# =========================
-st.sidebar.markdown(
+st.markdown(
"""
-
- U.S. Petroleum & WTI Weekly Monitor
-
+
""",
unsafe_allow_html=True,
)
-st.sidebar.caption("Source: EIA")
-st.sidebar.divider()
# =========================
# Main page header
# =========================
st.title("Weekly U.S. Petroleum Supply")
-st.subheader("Team Members: Irina, Indra")
-st.caption("Source: U.S. Energy Information Administration (EIA)")
+st.caption("Team Members: Irina, Indra ยท Source: U.S. Energy Information Administration (EIA)")
# =========================
# Project Proposal
@@ -332,63 +364,71 @@ def compute_product_price_sensitivity(
st.divider()
# =========================
-# Two side-by-side charts
+# Stacked charts
# =========================
-left_col, right_col = st.columns(TWO_COLUMN_LAYOUT)
+st.subheader("Total Product Supplied")
-with left_col:
- st.subheader("Total Product Supplied")
+fig = px.line(
+ filtered_total,
+ x="week",
+ y="total_supply",
+ labels={"week": "Week", "total_supply": "Total Product Supplied"},
+)
+fig.update_layout(
+ hovermode="x unified",
+ xaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ yaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ plot_bgcolor="rgba(0,0,0,0)",
+ paper_bgcolor="rgba(0,0,0,0)",
+)
+fig.update_traces(hovertemplate="%{x|%b %d, %Y}
Total Supply: %{y:,.0f}")
+st.plotly_chart(fig, use_container_width=True)
- fig = px.line(
- filtered_total,
+with st.expander("Show total supply data table"):
+ total_display = filtered_total.sort_values("week", ascending=False).copy()
+ total_display["week"] = total_display["week"].dt.strftime("%Y-%m-%d")
+ st.dataframe(total_display, width="stretch")
+
+st.divider()
+
+st.subheader("Product-Level Weekly Supply")
+
+if not selected_products:
+ st.warning("Please select at least one product from the sidebar.")
+else:
+ product_plot_df = filtered_product[
+ filtered_product["product_name"].isin(selected_products)
+ ].copy()
+
+ fig2 = px.line(
+ product_plot_df,
x="week",
- y="total_supply",
- labels={"week": "Week", "total_supply": "Total Product Supplied"},
+ y="product_supplied",
+ color="product_name",
+ labels={
+ "week": "Week",
+ "product_supplied": "Product Supplied",
+ "product_name": "Product",
+ },
)
- fig.update_layout(hovermode="x unified")
- fig.update_traces(
- hovertemplate="%{x|%b %d, %Y}
Total Supply: %{y:,.0f}"
+ fig2.update_layout(
+ hovermode="x unified",
+ xaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ yaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ plot_bgcolor="rgba(0,0,0,0)",
+ paper_bgcolor="rgba(0,0,0,0)",
)
- st.plotly_chart(fig, use_container_width=True)
-
- with st.expander("Show total supply data table"):
- total_display = filtered_total.sort_values("week", ascending=False).copy()
- total_display["week"] = total_display["week"].dt.strftime("%Y-%m-%d")
- st.dataframe(total_display, width="stretch")
-
-with right_col:
- st.subheader("Product-Level Weekly Supply")
-
- if not selected_products:
- st.warning("Please select at least one product from the sidebar.")
- else:
- product_plot_df = filtered_product[
- filtered_product["product_name"].isin(selected_products)
- ].copy()
-
- fig2 = px.line(
- product_plot_df,
- x="week",
- y="product_supplied",
- color="product_name",
- labels={
- "week": "Week",
- "product_supplied": "Product Supplied",
- "product_name": "Product",
- },
- )
- fig2.update_layout(hovermode="x unified")
- fig2.update_traces(
- hovertemplate="%{fullData.name}
%{x|%b %d, %Y}: %{y:,.0f}"
- )
- st.plotly_chart(fig2, use_container_width=True)
-
- with st.expander("Show product-level data table"):
- product_display = product_plot_df.sort_values(
- ["product_name", "week"], ascending=[True, False]
- ).copy()
- product_display["week"] = product_display["week"].dt.strftime("%Y-%m-%d")
- st.dataframe(product_display, width="stretch")
+ fig2.update_traces(
+ hovertemplate="%{fullData.name}
%{x|%b %d, %Y}: %{y:,.0f}"
+ )
+ st.plotly_chart(fig2, use_container_width=True)
+
+ with st.expander("Show product-level data table"):
+ product_display = product_plot_df.sort_values(
+ ["product_name", "week"], ascending=[True, False]
+ ).copy()
+ product_display["week"] = product_display["week"].dt.strftime("%Y-%m-%d")
+ st.dataframe(product_display, width="stretch")
st.divider()
diff --git a/pages/2_WTI_Price.py b/pages/2_WTI_Price.py
index c45a0d6..de98665 100644
--- a/pages/2_WTI_Price.py
+++ b/pages/2_WTI_Price.py
@@ -14,18 +14,51 @@
st.set_page_config(page_title="WTI Price", layout="wide")
# =========================
-# Sidebar title
+# Sidebar title (above nav via CSS)
# =========================
-st.sidebar.markdown(
+st.markdown(
"""
-
- U.S. Petroleum & WTI Weekly Monitor
-
+
""",
unsafe_allow_html=True,
)
-st.sidebar.caption("Source: EIA")
-st.sidebar.divider()
# =========================
# Main page header
@@ -256,60 +289,66 @@ def find_top_highest_years(yearly_avg: pd.DataFrame, top_n: int) -> set[int]:
st.divider()
# =========================
-# Two charts side by side
+# Stacked charts
# =========================
-left_col, right_col = st.columns(TWO_COLUMN_LAYOUT)
-
-with left_col:
- st.subheader("WTI Price Over Time (Weekly)")
-
- fig = go.Figure()
- fig.add_trace(
- go.Scatter(
- x=filtered_wti["week"],
- y=filtered_wti["wti_price"],
- name="WTI Price",
- mode="lines",
- hovertemplate="WTI Price: $%{y:.2f}",
- )
- )
- fig.add_trace(
- go.Scatter(
- x=filtered_wti["week"],
- y=filtered_wti["wti_ma"],
- name=f"{ma_window}-Week Moving Average",
- mode="lines",
- hovertemplate=f"{ma_window}-Week Avg: $%{{y:.2f}}",
- )
- )
- fig.update_layout(
- xaxis_title="Week",
- yaxis_title="WTI Price ($/barrel)",
- hovermode="x unified",
- hoverlabel=dict(namelength=-1),
+st.subheader("WTI Price Over Time (Weekly)")
+
+fig = go.Figure()
+fig.add_trace(
+ go.Scatter(
+ x=filtered_wti["week"],
+ y=filtered_wti["wti_price"],
+ name="WTI Price",
+ mode="lines",
+ hovertemplate="WTI Price: $%{y:.2f}",
)
- st.plotly_chart(fig, use_container_width=True)
-
-with right_col:
- st.subheader("Weekly Change in WTI Price")
-
- fig2 = go.Figure()
- fig2.add_trace(
- go.Scatter(
- x=filtered_wti["week"],
- y=filtered_wti["weekly_change"],
- mode="lines",
- name="Weekly Change",
- hovertemplate="%{x|%b %d, %Y}
Change: $%{y:.2f}",
- )
+)
+fig.add_trace(
+ go.Scatter(
+ x=filtered_wti["week"],
+ y=filtered_wti["wti_ma"],
+ name=f"{ma_window}-Week Moving Average",
+ mode="lines",
+ hovertemplate=f"{ma_window}-Week Avg: $%{{y:.2f}}",
)
- fig2.add_hline(y=0, line_color="gray", line_width=1)
- fig2.update_layout(
- xaxis_title="Week",
- yaxis_title="Weekly Change ($/barrel)",
- hovermode="x unified",
+)
+fig.update_layout(
+ xaxis_title="Week",
+ yaxis_title="WTI Price ($/barrel)",
+ hovermode="x unified",
+ hoverlabel=dict(namelength=-1),
+ xaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ yaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ plot_bgcolor="rgba(0,0,0,0)",
+ paper_bgcolor="rgba(0,0,0,0)",
+)
+st.plotly_chart(fig, use_container_width=True)
+
+st.divider()
+
+st.subheader("Weekly Change in WTI Price")
+
+fig2 = go.Figure()
+fig2.add_trace(
+ go.Scatter(
+ x=filtered_wti["week"],
+ y=filtered_wti["weekly_change"],
+ mode="lines",
+ name="Weekly Change",
+ hovertemplate="%{x|%b %d, %Y}
Change: $%{y:.2f}",
)
- st.plotly_chart(fig2, use_container_width=True)
+)
+fig2.add_hline(y=0, line_color="#0D2B5E", line_width=1.5)
+fig2.update_layout(
+ xaxis_title="Week",
+ yaxis_title="Weekly Change ($/barrel)",
+ hovermode="x unified",
+ xaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ yaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ plot_bgcolor="rgba(0,0,0,0)",
+ paper_bgcolor="rgba(0,0,0,0)",
+)
+st.plotly_chart(fig2, use_container_width=True)
st.divider()
st.subheader("Real-Time Interpretation")
diff --git a/pages/3_Event_Context.py b/pages/3_Event_Context.py
index 775f87f..503ef29 100644
--- a/pages/3_Event_Context.py
+++ b/pages/3_Event_Context.py
@@ -14,16 +14,51 @@
# =========================
# Sidebar title
# =========================
-st.sidebar.markdown(
+# Sidebar title (above nav via CSS)
+# =========================
+st.markdown(
"""
-
- U.S. Petroleum & WTI Weekly Monitor
-
+
""",
unsafe_allow_html=True,
)
-st.sidebar.caption("Source: EIA + GDELT")
-st.sidebar.divider()
# =========================
# Main page header
@@ -263,55 +298,63 @@ def build_anomaly_table(merged_df: pd.DataFrame, top_n: int) -> pd.DataFrame:
st.divider()
# =========================
-# Two side-by-side charts
+# Stacked charts
# =========================
-left_col, right_col = st.columns(TWO_COLUMN_LAYOUT)
+st.subheader("Weekly Event Count")
-with left_col:
- st.subheader("Weekly Event Count")
+fig1 = px.line(
+ filtered,
+ x="week",
+ y="event_count",
+ labels={"week": "Week", "event_count": "Event Count"},
+)
+fig1.update_layout(
+ hovermode="x unified",
+ xaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ yaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ plot_bgcolor="rgba(0,0,0,0)",
+ paper_bgcolor="rgba(0,0,0,0)",
+)
+fig1.update_traces(hovertemplate="%{x|%b %d, %Y}
Events: %{y:,.0f}")
+st.plotly_chart(fig1, use_container_width=True)
- fig1 = px.line(
- filtered,
- x="week",
- y="event_count",
- labels={"week": "Week", "event_count": "Event Count"},
- )
- fig1.update_layout(hovermode="x unified")
- fig1.update_traces(hovertemplate="%{x|%b %d, %Y}
Events: %{y:,.0f}")
- st.plotly_chart(fig1, use_container_width=True)
+st.caption(
+ "This chart shows how many GDELT-recorded events occurred each week. "
+ "Use it to see whether broader event activity rises during weeks when "
+ "WTI or petroleum supply experiences unusual movement."
+)
- st.caption(
- "This chart shows how many GDELT-recorded events occurred each week. "
- "Use it to see whether broader event activity rises during weeks when "
- "WTI or petroleum supply experiences unusual movement."
- )
+st.divider()
-with right_col:
- st.subheader("Average Event Tone")
-
- fig2 = go.Figure()
- fig2.add_trace(
- go.Scatter(
- x=filtered["week"],
- y=filtered["avg_tone"],
- mode="lines",
- name="Average Tone",
- hovertemplate="%{x|%b %d, %Y}
Avg Tone: %{y:.2f}",
- )
- )
- fig2.add_hline(y=0, line_color="gray", line_width=1)
- fig2.update_layout(
- xaxis_title="Week",
- yaxis_title="Average Tone",
- hovermode="x unified",
- )
- st.plotly_chart(fig2, use_container_width=True)
+st.subheader("Average Event Tone")
- st.caption(
- "This chart tracks the average tone of events in each week. "
- "More negative values suggest a more adverse event environment, which may "
- "help contextualize stress periods in the energy data."
+fig2 = go.Figure()
+fig2.add_trace(
+ go.Scatter(
+ x=filtered["week"],
+ y=filtered["avg_tone"],
+ mode="lines",
+ name="Average Tone",
+ hovertemplate="%{x|%b %d, %Y}
Avg Tone: %{y:.2f}",
)
+)
+fig2.add_hline(y=0, line_color="#0D2B5E", line_width=1.5)
+fig2.update_layout(
+ xaxis_title="Week",
+ yaxis_title="Average Tone",
+ hovermode="x unified",
+ xaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ yaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ plot_bgcolor="rgba(0,0,0,0)",
+ paper_bgcolor="rgba(0,0,0,0)",
+)
+st.plotly_chart(fig2, use_container_width=True)
+
+st.caption(
+ "This chart tracks the average tone of events in each week. "
+ "More negative values suggest a more adverse event environment, which may "
+ "help contextualize stress periods in the energy data."
+)
st.divider()
st.subheader("Weekly Event Composition")
@@ -361,6 +404,10 @@ def build_anomaly_table(merged_df: pd.DataFrame, top_n: int) -> pd.DataFrame:
xaxis_title="Week",
yaxis_title="Event Count",
hovermode="x unified",
+ xaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ yaxis=dict(gridcolor="rgba(13,43,94,0.2)", linecolor="#0D2B5E"),
+ plot_bgcolor="rgba(0,0,0,0)",
+ paper_bgcolor="rgba(0,0,0,0)",
)
st.plotly_chart(fig3, use_container_width=True)