diff --git a/scripts/build_historical_memories.py b/scripts/build_historical_memories.py index d1eb40e0..e91b6e49 100644 --- a/scripts/build_historical_memories.py +++ b/scripts/build_historical_memories.py @@ -27,13 +27,11 @@ 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 d91dd050..2849367c 100644 --- a/scripts/build_strategy_specific_memories.py +++ b/scripts/build_strategy_specific_memories.py @@ -89,8 +89,7 @@ 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('_', ' ')} ╚══════════════════════════════════════════════════════════════╝ @@ -99,8 +98,7 @@ 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() @@ -159,8 +157,7 @@ Tickers: {', '.join(strategy['tickers'])} def main(): - logger.info( - """ + logger.info(""" ╔══════════════════════════════════════════════════════════════╗ ║ TradingAgents - Strategy-Specific Memory Builder ║ ╚══════════════════════════════════════════════════════════════╝ @@ -171,8 +168,7 @@ 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): @@ -220,13 +216,11 @@ 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 d727d143..7bb99b60 100755 --- a/scripts/update_positions.py +++ b/scripts/update_positions.py @@ -129,12 +129,10 @@ 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 8a5666fc..db4f671a 100644 --- a/tradingagents/ui/pages/todays_picks.py +++ b/tradingagents/ui/pages/todays_picks.py @@ -79,15 +79,53 @@ def _format_move_pct(window: pd.DataFrame) -> str: return f"{move:+.2f}%" -def _build_dynamic_chart(history: pd.DataFrame, timeframe: str) -> tuple[go.Figure, str, str]: +def _get_daily_movement(ticker: str) -> str: + """Get today's intraday price movement percentage.""" + try: + from tradingagents.dataflows.y_finance import download_history + + today_data = download_history( + ticker, + period="1d", + interval="1d", + auto_adjust=True, + progress=False, + ) + if today_data is None or today_data.empty: + return "N/A" + + if isinstance(today_data.columns, pd.MultiIndex): + tickers = today_data.columns.get_level_values(1).unique() + if ticker not in tickers: + ticker = tickers[0] + today_data = today_data.xs(ticker, level=1, axis=1) + + close_col = "Close" if "Close" in today_data.columns else "Adj Close" + if close_col not in today_data.columns: + return "N/A" + + today_close = float(today_data[close_col].iloc[-1]) + today_open = float(today_data.get("Open", today_data[close_col]).iloc[-1]) + if today_open != 0: + daily_move = ((today_close - today_open) / today_open) * 100 + return f"{daily_move:+.2f}%" + except Exception: + pass + return "N/A" + + +def _build_dynamic_chart( + history: pd.DataFrame, timeframe: str, ticker: str = "" +) -> tuple[go.Figure, str, str, str]: window = _slice_history_window(history, timeframe) if window.empty: - return go.Figure(), "N/A", COLORS["text_muted"] + return go.Figure(), "N/A", COLORS["text_muted"], "N/A" 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) + daily_move_text = _get_daily_movement(ticker) if ticker else "N/A" template = dict(get_plotly_template()) @@ -144,7 +182,7 @@ def _build_dynamic_chart(history: pd.DataFrame, timeframe: str) -> tuple[go.Figu nticks=5, range=[y_min - pad, y_max + pad], ) - return fig, move_text, line_color + return fig, move_text, line_color, daily_move_text def _render_single_dynamic_chart(ticker: str, timeframe: str) -> None: @@ -158,17 +196,31 @@ def _render_single_dynamic_chart(ticker: str, timeframe: str) -> None: st.caption(f"Not enough data to render {timeframe} window.") return - fig, move_text, move_color = _build_dynamic_chart(base_history, timeframe) + fig, move_text, move_color, daily_move_text = _build_dynamic_chart(base_history, timeframe, ticker) + + # Determine daily movement color + try: + daily_move_val = float(daily_move_text.strip().rstrip('%')) + daily_color = COLORS["green"] if daily_move_val >= 0 else COLORS["red"] + except (ValueError, AttributeError): + daily_color = COLORS["text_muted"] + st.markdown( f"""