claude-code/claude-finance/skills/chart-drawing/SKILL.md

186 lines
5.0 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
name: chart-drawing
description: 技術分析圖表繪製知識庫。用 Python matplotlib 繪製各種技術型態圖,每種型態分開畫,輸出 PNG 圖片。
---
# 技術分析圖表繪製
## 環境需求
```bash
pip install yfinance matplotlib mplfinance pandas numpy
```
## 數據取得
```python
import yfinance as yf
# 美股
df = yf.download("NVDA", period="1y", interval="1d")
# 台股(代號加 .TW
df = yf.download("2330.TW", period="1y", interval="1d")
```
## 核心原則
1. **每種型態分開畫** — 不要把所有東西混在一張圖上
2. **圖片要清晰** — 至少 1200x800 像素,字體夠大
3. **標註關鍵價位** — 支撐、壓力、進場點用不同顏色標示
4. **存成 PNG** — 存到 `docs/fin/charts/` 目錄下
## 圖表類型與範本
### 1. K 線圖 + 均線(基礎圖)
```python
import mplfinance as mpf
import yfinance as yf
df = yf.download("NVDA", period="6mo", interval="1d")
mpf.plot(df, type='candle', style='charles',
mav=(20, 50, 200),
volume=True,
title='NVDA K線圖 + 均線',
figsize=(14, 8),
savefig='docs/fin/charts/NVDA-kline.png')
```
### 2. 支撐壓力圖
```python
import matplotlib.pyplot as plt
import yfinance as yf
df = yf.download("NVDA", period="6mo", interval="1d")
close = df['Close'].values.flatten()
dates = df.index
fig, ax = plt.subplots(figsize=(14, 8))
ax.plot(dates, close, 'b-', linewidth=1.5, label='收盤價')
# 標註支撐壓力(需手動或演算法計算)
support = 120 # 範例值
resistance = 150
ax.axhline(y=support, color='green', linestyle='--', label=f'支撐 ${support}')
ax.axhline(y=resistance, color='red', linestyle='--', label=f'壓力 ${resistance}')
ax.set_title('NVDA 支撐壓力圖', fontsize=16)
ax.legend(fontsize=12)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('docs/fin/charts/NVDA-support-resistance.png', dpi=150)
plt.show()
```
### 3. RSI 圖
```python
import matplotlib.pyplot as plt
import yfinance as yf
import pandas as pd
df = yf.download("NVDA", period="6mo", interval="1d")
close = df['Close'].squeeze()
delta = close.diff()
gain = delta.where(delta > 0, 0).rolling(14).mean()
loss = (-delta.where(delta < 0, 0)).rolling(14).mean()
rs = gain / loss
rsi = 100 - (100 / (1 + rs))
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10), height_ratios=[3, 1])
ax1.plot(df.index, close, 'b-', linewidth=1.5)
ax1.set_title('NVDA 股價', fontsize=14)
ax1.grid(True, alpha=0.3)
ax2.plot(df.index, rsi, 'purple', linewidth=1.5)
ax2.axhline(y=70, color='red', linestyle='--', alpha=0.7, label='超買 70')
ax2.axhline(y=30, color='green', linestyle='--', alpha=0.7, label='超賣 30')
ax2.fill_between(df.index, 70, 100, alpha=0.1, color='red')
ax2.fill_between(df.index, 0, 30, alpha=0.1, color='green')
ax2.set_title('RSI(14)', fontsize=14)
ax2.set_ylim(0, 100)
ax2.legend()
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('docs/fin/charts/NVDA-rsi.png', dpi=150)
plt.show()
```
### 4. MACD 圖
```python
import matplotlib.pyplot as plt
import yfinance as yf
df = yf.download("NVDA", period="6mo", interval="1d")
close = df['Close'].squeeze()
ema12 = close.ewm(span=12).mean()
ema26 = close.ewm(span=26).mean()
macd_line = ema12 - ema26
signal = macd_line.ewm(span=9).mean()
histogram = macd_line - signal
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(14, 10), height_ratios=[3, 1])
ax1.plot(df.index, close, 'b-', linewidth=1.5)
ax1.set_title('NVDA 股價', fontsize=14)
ax1.grid(True, alpha=0.3)
ax2.plot(df.index, macd_line, 'b-', label='MACD', linewidth=1.5)
ax2.plot(df.index, signal, 'r-', label='Signal', linewidth=1.5)
colors = ['green' if v >= 0 else 'red' for v in histogram]
ax2.bar(df.index, histogram, color=colors, alpha=0.5, label='Histogram')
ax2.set_title('MACD', fontsize=14)
ax2.legend()
ax2.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('docs/fin/charts/NVDA-macd.png', dpi=150)
plt.show()
```
### 5. 布林通道圖
```python
import matplotlib.pyplot as plt
import yfinance as yf
df = yf.download("NVDA", period="6mo", interval="1d")
close = df['Close'].squeeze()
sma20 = close.rolling(20).mean()
std20 = close.rolling(20).std()
upper = sma20 + 2 * std20
lower = sma20 - 2 * std20
fig, ax = plt.subplots(figsize=(14, 8))
ax.plot(df.index, close, 'b-', linewidth=1.5, label='收盤價')
ax.plot(df.index, sma20, 'orange', linewidth=1, label='SMA(20)')
ax.plot(df.index, upper, 'red', linewidth=0.8, linestyle='--', label='上軌')
ax.plot(df.index, lower, 'green', linewidth=0.8, linestyle='--', label='下軌')
ax.fill_between(df.index, upper, lower, alpha=0.1, color='gray')
ax.set_title('NVDA 布林通道', fontsize=16)
ax.legend(fontsize=12)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('docs/fin/charts/NVDA-bollinger.png', dpi=150)
plt.show()
```
## 型態辨識圖(手動標註)
當 technical-analyst 識別出型態時,用以下模板繪製:
### 頭肩頂/底、雙頂/底、三角收斂等
```python
# 通用型態標註模板
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import yfinance as yf
```