From aef83cd6e0c6fe6cc4d9cb10b72a6591a0e4383e Mon Sep 17 00:00:00 2001 From: Youssef Aitousarrah Date: Mon, 16 Feb 2026 22:41:54 -0800 Subject: [PATCH 1/2] Update the price chart --- tradingagents/ui/pages/todays_picks.py | 150 ++++++++++++++----------- 1 file changed, 87 insertions(+), 63 deletions(-) diff --git a/tradingagents/ui/pages/todays_picks.py b/tradingagents/ui/pages/todays_picks.py index 2ce89772..9f018b27 100644 --- a/tradingagents/ui/pages/todays_picks.py +++ b/tradingagents/ui/pages/todays_picks.py @@ -79,92 +79,105 @@ def _format_move_pct(window: pd.DataFrame) -> str: return f"{move:+.2f}%" -def _build_mini_chart(window: pd.DataFrame, timeframe: str) -> go.Figure: - template = get_plotly_template() +def _build_dynamic_chart(history: pd.DataFrame, timeframe: str) -> tuple[go.Figure, str, str]: + window = _slice_history_window(history, timeframe) + if window.empty: + return go.Figure(), "N/A", COLORS["text_muted"] + first_close = float(window["close"].iloc[0]) last_close = float(window["close"].iloc[-1]) line_color = COLORS["green"] if last_close >= first_close else COLORS["red"] + move_text = _format_move_pct(window) + + template = dict(get_plotly_template()) fig = go.Figure() + fig.add_trace( + go.Scatter( + x=history["date"], + y=history["close"], + mode="lines", + line=dict(color="rgba(148,163,184,0.22)", width=1.1), + hovertemplate="%{x|%b %d, %Y}
$%{y:.2f}", + name="History", + ) + ) fig.add_trace( go.Scatter( x=window["date"], y=window["close"], mode="lines", - line=dict(color=line_color, width=1.8), + line=dict(color=line_color, width=2.8), fill="tozeroy", - fillcolor="rgba(34,197,94,0.08)" if line_color == COLORS["green"] else "rgba(239,68,68,0.08)", + fillcolor=( + "rgba(34,197,94,0.18)" + if line_color == COLORS["green"] + else "rgba(239,68,68,0.18)" + ), hovertemplate=f"{timeframe}
%{{x|%b %d, %Y}}
$%{{y:.2f}}", - name=timeframe, + name=f"{timeframe} Focus", ) ) - fig.update_layout( - **template, - height=140, - showlegend=False, - margin=dict(l=0, r=0, t=0, b=0), + + # Override template keys before expansion to avoid duplicate keyword args. + template["height"] = 210 + template["showlegend"] = False + template["margin"] = dict(l=0, r=0, t=10, b=0) + fig.update_layout(**template) + + # Tighten Y-axis to selected timeframe range for better signal visibility. + y_min = float(window["close"].min()) + y_max = float(window["close"].max()) + if y_min == y_max: + pad = max(0.5, y_min * 0.01) + else: + pad = max((y_max - y_min) * 0.08, y_max * 0.01) + + fig.update_xaxes( + showticklabels=False, + showgrid=False, + range=[window["date"].min(), history["date"].max()], + rangeslider=dict(visible=False), ) - fig.update_xaxes(showticklabels=False, showgrid=False) - fig.update_yaxes(showgrid=True, gridcolor="rgba(42,53,72,0.28)", tickprefix="$", nticks=4) - return fig + fig.update_yaxes( + showgrid=True, + gridcolor="rgba(42,53,72,0.28)", + tickprefix="$", + nticks=5, + range=[y_min - pad, y_max + pad], + ) + return fig, move_text, line_color -def _render_multi_timeframe_charts(ticker: str, selected_timeframes: list[str]) -> None: - if not selected_timeframes: - return - +def _render_single_dynamic_chart(ticker: str, timeframe: str) -> None: base_history = _load_price_history(ticker, "1y") if base_history.empty: + st.caption("No price history available for this ticker.") return - ordered_timeframes = [tf for tf in TIMEFRAME_LOOKBACK_DAYS.keys() if tf in selected_timeframes] - if not ordered_timeframes: + window = _slice_history_window(base_history, timeframe) + if window.empty: + st.caption(f"Not enough data to render {timeframe} window.") return + fig, move_text, move_color = _build_dynamic_chart(base_history, timeframe) st.markdown( f""" -
- + - Multi-Timeframe Price Map + Dynamic Price View • {timeframe} + {move_text}
""", unsafe_allow_html=True, ) - - for i in range(0, len(ordered_timeframes), 2): - cols = st.columns(2) - for j, col in enumerate(cols): - idx = i + j - if idx >= len(ordered_timeframes): - continue - timeframe = ordered_timeframes[idx] - window = _slice_history_window(base_history, timeframe) - if window.empty: - continue - first_close = float(window["close"].iloc[0]) - last_close = float(window["close"].iloc[-1]) - move_text = _format_move_pct(window) - move_color = COLORS["green"] if last_close >= first_close else COLORS["red"] - fig = _build_mini_chart(window, timeframe) - - with col: - st.markdown( - f""" -
- {timeframe} - {move_text} -
- """, - unsafe_allow_html=True, - ) - st.plotly_chart(fig, width="stretch") + st.plotly_chart(fig, width="stretch", config={"displayModeBar": False}) def render(): @@ -199,14 +212,6 @@ def render(): min_score = st.slider("Min Score", 0, 100, 0) with ctrl_cols[3]: show_charts = st.checkbox("Price Charts", value=False) - if show_charts: - selected_timeframes = st.multiselect( - "Timeframes", - list(TIMEFRAME_LOOKBACK_DAYS.keys()), - default=["1M", "3M", "6M", "1Y"], - ) - else: - selected_timeframes = [] # Apply filters filtered = [ @@ -259,7 +264,26 @@ def render(): ) if show_charts: - _render_multi_timeframe_charts(ticker, selected_timeframes) + st.markdown( + f""" +
+ Chart Timeframe +
+ """, + unsafe_allow_html=True, + ) + chart_timeframe = st.radio( + f"Timeframe for {ticker}", + list(TIMEFRAME_LOOKBACK_DAYS.keys()), + index=2, + horizontal=True, + label_visibility="collapsed", + key=f"chart_tf_{ticker}_{idx}", + ) + _render_single_dynamic_chart(ticker, chart_timeframe) # Action buttons btn_cols = st.columns(2) From 457d650e42a0392fb40a651df600ecb49c532949 Mon Sep 17 00:00:00 2001 From: Youssef Aitousarrah Date: Tue, 17 Feb 2026 10:27:13 -0800 Subject: [PATCH 2/2] Update --- scripts/build_historical_memories.py | 6 ++++-- scripts/build_strategy_specific_memories.py | 18 ++++++++++++------ scripts/update_positions.py | 6 ++++-- tradingagents/ui/pages/todays_picks.py | 4 +--- 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/scripts/build_historical_memories.py b/scripts/build_historical_memories.py index e91b6e49..d1eb40e0 100644 --- a/scripts/build_historical_memories.py +++ b/scripts/build_historical_memories.py @@ -27,11 +27,13 @@ logger = get_logger(__name__) def main(): - logger.info(""" + logger.info( + """ ╔══════════════════════════════════════════════════════════════╗ ║ TradingAgents - Historical Memory Builder ║ ╚══════════════════════════════════════════════════════════════╝ - """) + """ + ) # Configuration tickers = [ diff --git a/scripts/build_strategy_specific_memories.py b/scripts/build_strategy_specific_memories.py index 2849367c..d91dd050 100644 --- a/scripts/build_strategy_specific_memories.py +++ b/scripts/build_strategy_specific_memories.py @@ -89,7 +89,8 @@ def build_strategy_memories(strategy_name: str, config: dict): strategy = STRATEGIES[strategy_name] - logger.info(f""" + logger.info( + f""" ╔══════════════════════════════════════════════════════════════╗ ║ Building Memories: {strategy_name.upper().replace('_', ' ')} ╚══════════════════════════════════════════════════════════════╝ @@ -98,7 +99,8 @@ Strategy: {strategy['description']} Lookforward: {strategy['lookforward_days']} days Sampling: Every {strategy['interval_days']} days Tickers: {', '.join(strategy['tickers'])} - """) + """ + ) # Date range - last 2 years end_date = datetime.now() @@ -157,7 +159,8 @@ Tickers: {', '.join(strategy['tickers'])} def main(): - logger.info(""" + logger.info( + """ ╔══════════════════════════════════════════════════════════════╗ ║ TradingAgents - Strategy-Specific Memory Builder ║ ╚══════════════════════════════════════════════════════════════╝ @@ -168,7 +171,8 @@ This script builds optimized memories for different trading styles: 2. Swing Trading - 7-day returns, weekly samples 3. Position Trading - 30-day returns, monthly samples 4. Long-term - 90-day returns, quarterly samples - """) + """ + ) logger.info("Available strategies:") for i, (name, config) in enumerate(STRATEGIES.items(), 1): @@ -216,11 +220,13 @@ This script builds optimized memories for different trading styles: logger.info("\n" + "=" * 70) logger.info("\n💡 TIP: To use a specific strategy's memories, update your config:") - logger.info(""" + logger.info( + """ config = DEFAULT_CONFIG.copy() config["memory_dir"] = "data/memories/swing_trading" # or your strategy config["load_historical_memories"] = True - """) + """ + ) if __name__ == "__main__": diff --git a/scripts/update_positions.py b/scripts/update_positions.py index 7bb99b60..d727d143 100755 --- a/scripts/update_positions.py +++ b/scripts/update_positions.py @@ -129,10 +129,12 @@ def main(): 6. Save updated positions 7. Print progress messages """ - logger.info(""" + logger.info( + """ ╔══════════════════════════════════════════════════════════════╗ ║ TradingAgents - Position Updater ║ -╚══════════════════════════════════════════════════════════════╝""".strip()) +╚══════════════════════════════════════════════════════════════╝""".strip() + ) # Initialize position tracker tracker = PositionTracker(data_dir="data") diff --git a/tradingagents/ui/pages/todays_picks.py b/tradingagents/ui/pages/todays_picks.py index 9f018b27..8a5666fc 100644 --- a/tradingagents/ui/pages/todays_picks.py +++ b/tradingagents/ui/pages/todays_picks.py @@ -110,9 +110,7 @@ def _build_dynamic_chart(history: pd.DataFrame, timeframe: str) -> tuple[go.Figu line=dict(color=line_color, width=2.8), fill="tozeroy", fillcolor=( - "rgba(34,197,94,0.18)" - if line_color == COLORS["green"] - else "rgba(239,68,68,0.18)" + "rgba(34,197,94,0.18)" if line_color == COLORS["green"] else "rgba(239,68,68,0.18)" ), hovertemplate=f"{timeframe}
%{{x|%b %d, %Y}}
$%{{y:.2f}}", name=f"{timeframe} Focus",