PYTHON + LANGCHAIN 實戰專案

Unit 10: 台灣股市 AI 分析

K線圖、技術指標與 AI 投資策略

K線分析 技術指標 AI 策略

Step 1: 載入股市數據

# 匯入資料處理套件
import pandas as pd
# 匯入繪圖套件
import matplotlib.pyplot as plt
# 匯入股票 K 線繪圖套件
import mplfinance as mpf

# 載入台積電股票 CSV 數據
df = pd.read_csv('data/tw_stock_2330.csv')
# 將日期轉換為 datetime 格式
df['Date'] = pd.to_datetime(df['Date'])
# 將日期設為索引(mplfinance 需要)
df.set_index('Date', inplace=True)

# 計算移動平均線(MA = Moving Average)
df['MA5'] = df['Close'].rolling(window=5).mean()    # 5日均線
df['MA20'] = df['Close'].rolling(window=20).mean()  # 20日均線
df['MA60'] = df['Close'].rolling(window=60).mean()  # 60日均線

# 計算 RSI(相對強弱指標,判斷超買超賣)
delta = df['Close'].diff()  # 計算每日價格變化
gain = (delta.where(delta > 0, 0)).rolling(window=14).mean()  # 14日平均漲幅
loss = (-delta.where(delta < 0, 0)).rolling(window=14).mean() # 14日平均跌幅
df['RSI'] = 100 - (100 / (1 + gain / loss))  # RSI 公式

# 顯示資料概要
print(f"股票:台積電 (2330)")
print(f"時間範圍: {df.index.min()} ~ {df.index.max()}")
print(f"最新收盤價: {df['Close'].iloc[-1]}")

Step 2: K線圖繪製

# 匯入股票 K 線繪圖套件
import mplfinance as mpf

# 取得最近 60 個交易日資料繪製 K 線
kline_data = df.tail(60).copy()

# 設定額外繪製的線條(均線和 RSI)
add_plots = [
    mpf.make_addplot(kline_data['MA5'], color='blue', width=1),      # 5日均線(藍色)
    mpf.make_addplot(kline_data['MA20'], color='orange', width=1),   # 20日均線(橘色)
    mpf.make_addplot(kline_data['RSI'], panel=1, color='purple', ylabel='RSI')  # RSI 副圖
]

# 繪製 K 線圖
mpf.plot(kline_data,
         type='candle',       # 蠟燭圖類型
         style='yahoo',       # Yahoo Finance 風格
         title='台積電 (2330) K線圖',
         ylabel='股價',
         volume=True,         # 顯示成交量
         addplot=add_plots,   # 加入均線和 RSI
         figsize=(14, 10),
         savefig='output/K線圖.png')
K線圖結合均線與RSI指標,提供完整技術分析視角

Step 3: 技術指標視覺化

# 建立 3x1 垂直子圖佈局,共用 X 軸
fig, axes = plt.subplots(3, 1, figsize=(14, 12), sharex=True)

# 上圖:股價走勢與三條均線
axes[0].plot(df.index, df['Close'], label='收盤價', linewidth=1.5)
axes[0].plot(df.index, df['MA5'], label='MA5', alpha=0.7)    # 5日均線
axes[0].plot(df.index, df['MA20'], label='MA20', alpha=0.7)  # 20日均線
axes[0].plot(df.index, df['MA60'], label='MA60', alpha=0.7)  # 60日均線
axes[0].set_title('股價走勢與均線')
axes[0].legend()
axes[0].grid(True, alpha=0.3)

# 中圖:成交量長條圖(紅漲綠跌)
colors = ['red' if df['Close'].iloc[i] >= df['Open'].iloc[i] else 'green'
          for i in range(len(df))]  # 根據漲跌決定顏色
axes[1].bar(df.index, df['Volume'], color=colors, alpha=0.7)
axes[1].set_title('成交量')

# 下圖:RSI 相對強弱指標
axes[2].plot(df.index, df['RSI'], color='purple')
axes[2].axhline(y=70, color='r', linestyle='--', alpha=0.5)  # 超買線(70)
axes[2].axhline(y=30, color='g', linestyle='--', alpha=0.5)  # 超賣線(30)
axes[2].fill_between(df.index, 30, 70, alpha=0.1)  # 正常區間填色
axes[2].set_title('RSI 指標')
axes[2].set_ylim(0, 100)

# 儲存圖表
plt.tight_layout()
plt.savefig('output/技術分析.png', dpi=300)

Step 4: AI 技術面分析

# 匯入 LangChain OpenAI 模組
from langchain_openai import ChatOpenAI
# 匯入提示模板類別
from langchain_core.prompts import ChatPromptTemplate

# 初始化語言模型
llm = ChatOpenAI(model="gpt-5.6-luna")

# 取得最新一筆資料
latest = df.iloc[-1]
# 準備技術指標數據字典
stats = {
    "close": latest['Close'],      # 收盤價
    "ma5": latest['MA5'],          # 5日均線
    "ma20": latest['MA20'],        # 20日均線
    "ma60": latest['MA60'],        # 60日均線
    "rsi": latest['RSI'],          # RSI 值
    "volume": latest['Volume'],    # 成交量
    # 計算日漲跌幅 = (今收 - 昨收) / 昨收 × 100%
    "change": (latest['Close'] - df.iloc[-2]['Close']) / df.iloc[-2]['Close'] * 100
}

# 建立技術分析提示模板
analysis_prompt = ChatPromptTemplate.from_messages([
    ("system", "你是專業股票分析師,請用繁體中文提供技術面分析。注意:這僅供教學參考,不構成投資建議。"),
    ("human", """台積電 (2330) 最新數據:
- 收盤價:{close:.0f} 元
- 5日均線:{ma5:.0f} 元
- 20日均線:{ma20:.0f} 元
- 60日均線:{ma60:.0f} 元
- RSI:{rsi:.1f}
- 日漲跌:{change:+.2f}%

請分析:
1. 均線排列型態
2. RSI 超買超賣判斷
3. 短期技術面觀察
4. 關鍵支撐/壓力位""")
])

# 使用 LCEL 串接並執行
chain = analysis_prompt | llm
response = chain.invoke(stats)
# 輸出 AI 技術分析結果
print(response.content)

Step 5: AI 產業比較分析

# 匯入 JSON 輸出解析器
from langchain_core.output_parsers import JsonOutputParser

# 定義要比較的股票清單(股票代碼: 公司名稱)
stocks = {
    '2330': '台積電',
    '2317': '鴻海',
    '2454': '聯發科'
}

# 收集各股票的比較數據
comparison_data = []
for code, name in stocks.items():
    # 載入各股票 CSV 數據
    stock_df = pd.read_csv(f'data/tw_stock_{code}.csv')
    stock_df['Date'] = pd.to_datetime(stock_df['Date'])
    latest = stock_df.iloc[-1]  # 取得最新資料
    comparison_data.append({
        "code": code,
        "name": name,
        "price": latest['Close'],
        # 計算近一個月漲跌幅(約22個交易日)
        "change_30d": (latest['Close'] - stock_df.iloc[-22]['Close']) / stock_df.iloc[-22]['Close'] * 100
    })

# 建立產業比較提示模板(指定 JSON 輸出格式)
compare_prompt = ChatPromptTemplate.from_messages([
    ("system", """你是半導體產業分析師。比較股票並輸出JSON:
{{"ranking": ["股票代碼"], "analysis": "分析說明", "top_pick": "首選股票"}}"""),
    ("human", "比較以下股票近月表現:\\n{data}")
])

# 初始化 JSON 解析器
parser = JsonOutputParser()
# 串接完整鏈:提示模板 → 語言模型 → JSON 解析
compare_chain = compare_prompt | llm | parser

# 執行比較分析
result = compare_chain.invoke({"data": str(comparison_data)})
# 輸出排名和分析結果
print(f"排名: {result['ranking']}")
print(f"分析: {result['analysis']}")

Step 6: AI 投資策略建議

# 匯入 Pydantic 資料模型和欄位描述
from langchain_core.pydantic_v1 import BaseModel, Field
# 匯入型別提示
from typing import List

# 定義投資建議輸出結構
class InvestmentAdvice(BaseModel):
    action: str = Field(description="建議動作:買入/賣出/觀望")
    confidence: int = Field(description="信心度 0-100")
    reasons: List[str] = Field(description="理由列表")
    risk_level: str = Field(description="風險等級:低/中/高")
    target_price: float = Field(description="目標價位")

# 匯入 Pydantic 輸出解析器
from langchain.output_parsers import PydanticOutputParser

# 建立解析器(綁定 InvestmentAdvice 結構)
advice_parser = PydanticOutputParser(pydantic_object=InvestmentAdvice)

# 建立投資建議提示模板
advice_prompt = ChatPromptTemplate.from_messages([
    ("system", """你是投資顧問。根據技術指標提供建議(僅供教學參考)。
{format_instructions}"""),
    ("human", """股票:{stock}
收盤價:{price}
RSI:{rsi}
均線位置:股價{"高於" if {above_ma} else "低於"}20日均線""")
])

# 串接完整鏈:提示模板 → 語言模型 → Pydantic 解析
advice_chain = advice_prompt | llm | advice_parser

# 執行投資建議分析
result = advice_chain.invoke({
    "stock": "台積電 (2330)",
    "price": latest['Close'],
    "rsi": latest['RSI'],
    "above_ma": latest['Close'] > latest['MA20'],  # 判斷是否高於20日均線
    "format_instructions": advice_parser.get_format_instructions()  # 自動產生格式說明
})

# 輸出結構化投資建議
print(f"建議:{result.action}")
print(f"信心度:{result.confidence}%")
print(f"風險:{result.risk_level}")
print(f"理由:{', '.join(result.reasons)}")

Unit 10 專案總結

K線圖繪製

mplfinance 專業圖表

技術指標

MA、RSI 計算與視覺化

AI 技術分析

自動解讀技術面訊號

AI 策略建議

結構化投資建議輸出

課程完成!恭喜完成 Python + LangChain 資料視覺化全部 10 個單元

← 返回課程首頁