--- apis/yfinance/api.py.orig	2026-09-22 12:21:37
+++ apis/yfinance/api.py	2026-09-22 12:21:37
@@ -30,3 +30,25 @@
             ))
 
         return news_list
+
+    # --- added by tutorial author (2026-09-22): key-free path ---
+    # The repo ships Router(APISource.YFINANCE) but YFinanceAPI implements only
+    # get_news, so every price call falls through. These two fill the gap.
+    def get_daily_candles_df(self, ticker: str, trading_date: datetime):
+        """Daily OHLCV up to and including trading_date (no look-ahead)."""
+        import pandas as pd
+        df = yf.Ticker(ticker).history(period="2y", interval="1d", auto_adjust=False)
+        df = df.rename(columns={
+            "Open": "open", "High": "high", "Low": "low",
+            "Close": "close", "Volume": "volume",
+        })[["open", "high", "low", "close", "volume"]]
+        df.index = pd.to_datetime(df.index).tz_localize(None).normalize()
+        df = df[df.index <= pd.Timestamp(trading_date).normalize()]
+        df.index.name = "Date"
+        return df.sort_index()
+
+    def get_last_close_price(self, ticker: str, trading_date: datetime) -> Optional[float]:
+        df = self.get_daily_candles_df(ticker, trading_date)
+        if df.empty:
+            return None
+        return float(df["close"].iloc[-1])
--- llm/prompt.py.orig	2026-09-22 12:23:34
+++ llm/prompt.py	2026-09-22 12:23:34
@@ -15,7 +15,7 @@
 """ + ANALYST_OUTPUT_FORMAT
 
 TECHNICAL_PROMPT = """
-You are a technical analyst evaluating ticker using multiple technical analysis strategies.
+You are a technical analyst evaluating {ticker} using multiple technical analysis strategies.
 
 The following signals have been generated from our analysis:
 
@@ -44,7 +44,7 @@
 """ + ANALYST_OUTPUT_FORMAT
 
 COMPANY_NEWS_PROMPT = """
-You are a company news analyst evaluating ticker based on recent news. Title, publisher, and publish time are provided.
+You are a company news analyst evaluating {ticker} based on recent news. Title, publisher, and publish time are provided.
 
 Here are recent news:
 {news}
@@ -73,7 +73,7 @@
 
 
 PORTFOLIO_PROMPT = """
-You are a portfolio manager making final trading decisions based on decision memory, and the provided optimal position ratio.
+You are a portfolio manager making the final trading decision for {ticker}, based on decision memory, and the provided optimal position ratio.
 
 Here is the decision memory:
 {decision_memory}
@@ -111,7 +111,7 @@
 
 RISK_CONTROL_PROMPT = """
 You are a professional risk control analyst.
-Please evaluate the risk of the ticker and set the optimal position ratio based on analyst signals and portfolio state.
+Please evaluate the risk of {ticker} and set the optimal position ratio based on analyst signals and portfolio state.
 
 Here are the analyst signals:
 {ticker_signals}
--- agents/analysts/company_news.py.orig	2026-09-22 12:23:34
+++ agents/analysts/company_news.py	2026-09-22 12:23:34
@@ -34,7 +34,7 @@
 
     # Analyze news sentiment via LLM
     news_dict = [m.model_dump_json() for m in company_news]
-    prompt = COMPANY_NEWS_PROMPT.format(news=news_dict)
+    prompt = COMPANY_NEWS_PROMPT.format(ticker=ticker, news=news_dict)
 
     # Get LLM signal
     signal = agent_call(
--- agents/portfolio_manager.py.orig	2026-09-22 12:23:34
+++ agents/portfolio_manager.py	2026-09-22 12:23:34
@@ -42,6 +42,7 @@
 
     # risk control
     risk_prompt = RISK_CONTROL_PROMPT.format(
+        ticker=ticker,
         ticker_signals=analyst_signals,
         portfolio=portfolio.model_dump_json(),
         max_position_ratio=max_position_ratio,
@@ -73,6 +74,7 @@
 
     # make trading decision
     prompt = PORTFOLIO_PROMPT.format(
+        ticker=ticker,
         decision_memory=decision_memory,
         current_price=current_price,
         current_shares=current_shares,
