From 35afc2aecf2ed397645f9c65b1f268a5be7d9d12 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 02:59:16 +0000 Subject: [PATCH 1/2] feat: add contextual tooltips to financial parameters Adds helpful native tooltips (`help` parameter) to various statistical and financial inputs (e.g., `factor_window`, `bt_cost`, `adv_pct`) in the Streamlit dashboard. These tooltips provide concrete examples (like "10 bps = 0.10%") to improve usability and UX accessibility when configuring the backtest parameters. Also added a critical learning entry to the Palette UX journal. Co-authored-by: aarjava <218419324+aarjava@users.noreply.github.com> --- .Jules/palette.md | 4 +++ src/dashboard.py | 80 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 .Jules/palette.md diff --git a/.Jules/palette.md b/.Jules/palette.md new file mode 100644 index 0000000..b7dff5f --- /dev/null +++ b/.Jules/palette.md @@ -0,0 +1,4 @@ + +## 2024-05-24 - Concrete Tooltips for Financial Parameters +**Learning:** Users struggle to interpret abstract statistical inputs (like quantiles, days, or basis points). Providing concrete, easily understandable examples within tooltips significantly improves confidence and usability. +**Action:** Always include concrete examples in tooltips for financial or statistical parameters (e.g., '10 bps = 0.10%', '63 days = ~3 months'). diff --git a/src/dashboard.py b/src/dashboard.py index 4156c1d..74512ce 100644 --- a/src/dashboard.py +++ b/src/dashboard.py @@ -168,9 +168,30 @@ def get_cache_key(*args) -> str: help="Lookback months for Momentum signal." ) else: - factor_window = st.slider("Factor Beta Window (days)", 20, 252, 63, 7) - vol_window = st.slider("Regime Vol Window (days)", 10, 60, 21, 5) - adv_pct = st.slider("ADV Participation %", 0.01, 0.30, float(DEFAULT_ADV_PCT), 0.01) + factor_window = st.slider( + "Factor Beta Window (days)", + 20, + 252, + 63, + 7, + help="Rolling window for calculating factor betas. 63 days = ~3 months.", + ) + vol_window = st.slider( + "Regime Vol Window (days)", + 10, + 60, + 21, + 5, + help="Rolling window for realized volatility. 21 days = ~1 trading month.", + ) + adv_pct = st.slider( + "ADV Participation %", + 0.01, + 0.30, + float(DEFAULT_ADV_PCT), + 0.01, + help="Maximum percentage of Average Daily Volume to trade. 0.10 = 10% of daily volume.", + ) st.markdown("---") st.subheader("4. Research Rigor") @@ -185,19 +206,60 @@ def get_cache_key(*args) -> str: st.info("Using full-sample quantiles (exploratory mode)") vol_q_high = st.slider( - "High Volatility Quantile", 0.5, 0.95, DEFAULT_VOL_QUANTILE_HIGH, 0.05 + "High Volatility Quantile", + 0.5, + 0.95, + DEFAULT_VOL_QUANTILE_HIGH, + 0.05, + help="Threshold for 'High' volatility regime. 0.80 = Top 20% of historical volatility.", ) if mode == "Single-Asset": st.subheader("5. Backtest Settings") - bt_cost = st.number_input("Transaction Cost (bps)", value=DEFAULT_COST_BPS, step=1) / 10000 + bt_cost = ( + st.number_input( + "Transaction Cost (bps)", + value=DEFAULT_COST_BPS, + step=1, + help="Cost per trade in basis points. 10 bps = 0.10%.", + ) + / 10000 + ) allow_short = st.checkbox("Allow Short Selling?", value=False) else: st.subheader("5. Alert Thresholds") - dd_alert = st.slider("Max Drawdown Alert", -0.6, -0.05, -0.2, 0.05) - vol_alert = st.slider("Volatility Alert (ann.)", 0.1, 1.0, 0.35, 0.05) - beta_alert = st.slider("Beta Alert", 0.5, 2.0, 1.3, 0.1) - dttl_alert = st.slider("Days-to-Liquidate Alert", 1.0, 20.0, 5.0, 1.0) + dd_alert = st.slider( + "Max Drawdown Alert", + -0.6, + -0.05, + -0.2, + 0.05, + help="Alert when drawdown exceeds this negative threshold. -0.20 = 20% loss.", + ) + vol_alert = st.slider( + "Volatility Alert (ann.)", + 0.1, + 1.0, + 0.35, + 0.05, + help="Alert when annualized volatility exceeds this level. 0.35 = 35% volatility.", + ) + beta_alert = st.slider( + "Beta Alert", + 0.5, + 2.0, + 1.3, + 0.1, + help="Alert when portfolio beta to benchmark exceeds this value.", + ) + dttl_alert = st.slider( + "Days-to-Liquidate Alert", + 1.0, + 20.0, + 5.0, + 1.0, + help="Alert when estimated days to liquidate the portfolio exceeds this value.", + ) # --- Portfolio Mode --- From 348f248e40834989772681499fb43ca6ff47fafa Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 30 Mar 2026 03:05:31 +0000 Subject: [PATCH 2/2] fix: ensure specific tooltips modifications pass global black formatting check Added the remaining missing manual `black` auto-formatting to the modified `st.slider` blocks and surrounding context in `src/dashboard.py` so that they completely satisfy CI `black --check` scoped formatting constraints. Co-authored-by: aarjava <218419324+aarjava@users.noreply.github.com> --- src/dashboard.py | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/src/dashboard.py b/src/dashboard.py index 74512ce..d4815da 100644 --- a/src/dashboard.py +++ b/src/dashboard.py @@ -160,12 +160,20 @@ def get_cache_key(*args) -> str: st.subheader("3. Signal Parameters") if mode == "Single-Asset": sma_window = st.slider( - "Trend SMA Window", 10, 200, DEFAULT_SMA_WINDOW, 10, - help="Lookback days for Simple Moving Average trend signal." + "Trend SMA Window", + 10, + 200, + DEFAULT_SMA_WINDOW, + 10, + help="Lookback days for Simple Moving Average trend signal.", ) mom_window = st.slider( - "Momentum Lookback (Months)", 1, 24, DEFAULT_MOMENTUM_WINDOW, 1, - help="Lookback months for Momentum signal." + "Momentum Lookback (Months)", + 1, + 24, + DEFAULT_MOMENTUM_WINDOW, + 1, + help="Lookback months for Momentum signal.", ) else: factor_window = st.slider( @@ -198,7 +206,7 @@ def get_cache_key(*args) -> str: use_oos = st.toggle( "Out-of-Sample Mode", value=False, - help="Uses expanding-window quantiles for regime classification to avoid look-ahead bias. Enable for rigorous backtesting." + help="Uses expanding-window quantiles for regime classification to avoid look-ahead bias. Enable for rigorous backtesting.", ) if use_oos: st.success("✓ Look-ahead bias removed") @@ -978,8 +986,12 @@ def get_cache_key(*args) -> str: """) wf_col1, wf_col2 = st.columns(2) - wf_train = wf_col1.number_input("Training Window (months)", value=24, min_value=6, max_value=60) - wf_test = wf_col2.number_input("Test Window (months)", value=6, min_value=1, max_value=12) + wf_train = wf_col1.number_input( + "Training Window (months)", value=24, min_value=6, max_value=60 + ) + wf_test = wf_col2.number_input( + "Test Window (months)", value=6, min_value=1, max_value=12 + ) if st.button("Run Walk-Forward Analysis"): with st.spinner("Running walk-forward validation..."):