# MacroScope — 總經儀表板 · 學習 · 個股 · 復盤 · 日曆

一個給初學者用的美國總體經濟 + 投資學習工具箱。資料主要來自美國聖路易聯儲 **FRED**（免費、公開）、Yahoo Finance、SEC EDGAR 等官方與公開來源。全中文介面、每張卡片與檢查都有白話解釋，並用透明公式算出「總經健康分數」。

強調「照問題學、不要硬背名詞」：從總經水位、財報健檢、六層投資地圖、交易復盤等實際任務出發，隨時可跳轉回對應的投資原則與名詞。內建市場日曆（含自訂追蹤財報）與可帶頁面上下文的 AI 助手（支援 Grok 與 OpenCode Go）。

> **為什麼需要後端？** FRED 官方 API 不允許瀏覽器直接呼叫（沒有 CORS），且金鑰不能放在前端。本專案用一支很小的 Node 伺服器當代理：金鑰只留在伺服器，瀏覽器只跟自己的 `/api/*` 溝通。

---

## 目錄

- [快速開始](#快速開始)
- [主要功能](#主要功能)
- [專案在整體 repo 中的位置](#專案在整體-repo-中的位置)
- [資料夾結構](#資料夾結構)
- [系統架構](#系統架構)
- [API 端點](#api-端點)
- [資料流與快取](#資料流與快取)
- [建立知識庫](#建立知識庫)
- [環境變數](#環境變數)
- [技術棧](#技術棧)
- [指標與資料來源](#指標與資料來源)
- [常見問題](#常見問題)
- [免責聲明](#免責聲明)

---

## 快速開始

### 1. 申請 FRED 金鑰（約 1 分鐘）

到 <https://fred.stlouisfed.org/docs/api/api_key.html> 註冊，取得 32 碼金鑰（免費、即時核發）。

### 2. 設定金鑰

啟動後到頂部 **AI 設定** 頁填入：

| 變數 | 用途 |
|------|------|
| `FRED_API_KEY` | 總經 + 部分日曆 |
| `GROK_API_KEY` / `OPENCODE_GO_API_KEY` | AI 助手（可擇一或都填） |
| `AI_ACTIVE_PROVIDER` | 預設 provider（`grok` 或 `opencode-go`） |

設定會寫入本機 `.env`，**不會出現在瀏覽器**。

或手動複製範例檔：

```bash
cp .env.example .env
# 編輯 .env 填入金鑰
```

### 3. 安裝並啟動

```bash
npm install
npm run build:knowledge   # 學習教材前置（需 emmy 知識庫，見下方）
npm start
# 開發模式（自動重啟）：npm run dev
```

瀏覽器開啟 `http://localhost:3000`。看到 `MacroScope 已啟動` 即成功。

> 還沒設 FRED 金鑰也能啟動，總經頁會顯示設定教學。

---

## 主要功能

頂部分頁使用 **hash 路由**（無前端框架）：

| 路由 | 視圖 | 說明 |
|------|------|------|
| `#/` | 總經儀表板 | 31 項 FRED 指標、健康分數、殖利率曲線 |
| `#/calendar` | 市場日曆 | FOMC/CPI/非農等 + 自訂追蹤財報 |
| `#/learn` | 學習教材 | Obsidian 知識庫快照、wikilink、知識圖譜 |
| `#/stock` | 個股工具 | 財報、走勢、健檢、投資地圖、回測 |
| `#/journal` | 交易復盤 | 交易紀錄、損益、勝率、分組統計 |
| `#/settings` | AI 設定 | 金鑰、provider、模型清單 |

右下角常駐 **AI 助手**，會依目前頁面自動帶入上下文。

### 總經儀表板

- 31 項真實 FRED 指標，分 6 組（利率 & 殖利率、通膨、勞動、成長、貨幣 & 信用、市場情緒 & 大宗）。
- 每張卡片：最新值、變動%、sparkline、三段白話解釋、資料來源與更新頻率。
- **總經健康分數**（0–100）與景氣燈號，附完整 breakdown。
- 殖利率曲線 + 歷史事件標記（`EVENTS` / `EPISODES`）。
- 點卡片開走勢大圖 Modal，支援多區間與分數累積走勢。

### 市場日曆

- 未來約 60 天重要事件（央行、通膨、就業、四巫日、休市等）。
- **追蹤財報**：自訂股票代號 watchlist，earnings 顯示在對應日期。
- 多源抓取（官方 iCal、FRED、BLS、BEA、Nasdaq），伺服器每日快取。

### 學習教材

- 由 `emmy/emmy` Obsidian 知識庫建置快照（原則、案例、名詞、公司、單集、知識圖譜）。
- wikilink `[[目標]]` 站內跳轉、Markdown + Mermaid、個人筆記（localStorage）。
- 與總經、個股、復盤雙向連結。

### 個股工具

- **指標面板**：報價、三表、比率、Company Intel。
- **價格走勢**：多區間／日週月線圖（Yahoo 主力，Nasdaq 備援）。
- **財報健檢**：五步驟紅黃綠燈 + 連結知識庫。
- **投資地圖**：六層漏斗互動流程。
- **回測**：買進持有 / 定期定額 / 均線 / 逢大跌等策略。

### 交易復盤

- CRUD 交易紀錄，自動損益、勝率、Payoff、分組分析。
- 資料存於 SQLite `trades` 表。

### AI 助手

- Provider：Grok、OpenCode Go；可從 `/api/ai/models` 抓取可用模型。
- `/api/ai/context` 組裝目前頁面精簡摘要 → `/api/ai/chat` 轉發 LLM。
- 繁體中文、先結論再依據，一律附學習免責聲明。

---

## 專案在整體 repo 中的位置

本目錄是 `finance` monorepo 下的 **Web 應用**；學習內容來自同層的 Obsidian 知識庫：

```
finance/                    # 父目錄（git repo 根目錄）
├── emmy/
│   └── emmy/               # Obsidian 投資知識庫（Markdown + wikilink）
│       ├── 投資原則/
│       ├── 名詞/
│       └── ...
└── web/                    # ← 本專案（MacroScope）
    ├── server.js
    ├── index.html
    ├── app.js
    ├── lib/
    ├── data/               # build:knowledge 產物
    └── data.db             # 執行期 SQLite（.gitignore）
```

建置腳本預期路徑：`../../emmy/emmy`（相對 `web/scripts/`）。

---

## 資料夾結構

```
web/
├── index.html              # 總經視圖 HTML 骨架 + 內聯渲染（卡片、Modal、圖表）
├── app.js                  # SPA 路由、五視圖 init、AI widget、Markdown/wikilink
├── app.css                 # 全站樣式（淺色、玻璃擬態 header）
├── server.js               # Express：靜態檔 + 全部 /api + 快取 + AI proxy + .env 管理
│
├── lib/                    # 領域邏輯（多數檔案開頭有職責說明）
│   ├── indicators.js       # 31 指標字典 + 6 分組 + 卡片 tip
│   ├── fred.js             # FRED 抓取、YoY/MoM、sparkline、殖利率曲線
│   ├── score.js            # 健康分數、regime、breakdown、signals
│   ├── context.js          # 依歷史序列產生白話脈絡
│   ├── events.js           # 歷史事件 EVENTS、危機案例 EPISODES
│   ├── db.js               # SQLite：cache / series / score_history / trades
│   ├── marketdata.js       # Yahoo chart + Nasdaq 備援
│   ├── fundamentals.js     # Yahoo quoteSummary + SEC EDGAR 正規化三表
│   ├── fincheck.js         # 財報基本功五步驟規則引擎
│   ├── backtest.js         # 四種策略回測與績效統計
│   ├── investmap.js        # 六層投資地圖設定與問題
│   ├── calendar.js         # 日曆事件彙整（多源）
│   ├── calendar-fred.js      # FRED 相關日曆源
│   ├── calendar-market.js  # 市場結構（四巫、休市等）
│   ├── calendar-i18n.js    # 事件中文化
│   ├── calendar-cache.js   # 日曆每日快取 + watchlist
│   ├── companyintel.js     # 管理層、內部人、新聞等
│   ├── knowledge.js        # 載入 knowledge.json / notes.json
│   ├── graph.js            # wikilink → vis-network 圖譜
│   ├── learn-html.js       # 學習路徑首頁渲染
│   └── glossary.js         # 名詞提示
│
├── data/                   # 建置產物（可 commit JSON，執行期讀取）
│   ├── knowledge.json      # 課綱索引 + linkMap + 輕量條目
│   └── notes.json          # 全筆記全文（kind:id → body）
│
├── scripts/
│   └── build-knowledge.mjs # 從 emmy/emmy 快照 → data/*.json
│
├── package.json
├── .env.example
├── .gitignore              # 忽略 node_modules、.env、data.db
└── README.md
```

**執行期產生、不進版控：**

| 檔案 | 說明 |
|------|------|
| `data.db` | SQLite：快取、序列、分數歷史、交易、通用 JSON cache |
| `.env` | API 金鑰與設定（可由設定頁寫入） |
| `node_modules/` | npm 依賴 |

---

## 系統架構

### 分層概覽

```mermaid
flowchart TB
  subgraph Browser["瀏覽器（Vanilla JS SPA）"]
    HTML[index.html]
    APP[app.js + app.css]
    HASH["Hash 路由 #/macro … #/settings"]
    AIW[AI 浮動面板]
  end

  subgraph Server["Node.js + Express（server.js）"]
    API["/api/* 路由"]
    CACHE[記憶體 + SQLite 快取]
    ENV[.env 讀寫]
  end

  subgraph Lib["lib/ 領域模組"]
    FRED[fred + indicators + score]
    MKT[marketdata + fundamentals]
    CAL[calendar-*]
    LEARN[knowledge + graph]
    TRD[db trades + fincheck + backtest]
  end

  subgraph External["外部資料源"]
    FREDAPI[FRED API]
    YAHOO[Yahoo Finance]
    SEC[SEC EDGAR]
    LLM[Grok / OpenCode Go]
    OFFICIAL[央行 / BLS / BEA / Nasdaq iCal]
  end

  subgraph Data["本機資料"]
    JSON[data/knowledge.json + notes.json]
    SQLITE[(data.db)]
  end

  Browser -->|fetch /api| Server
  Server --> Lib
  Lib --> FREDAPI
  Lib --> YAHOO
  Lib --> SEC
  Lib --> OFFICIAL
  Server --> LLM
  Lib --> JSON
  Lib --> SQLITE
  EMMY[(emmy/emmy)] -.->|build:knowledge| JSON
```

### 前端模組職責

| 檔案 | 職責 |
|------|------|
| `index.html` | 總經頁 DOM、卡片/Modal/圖表渲染、頂部 nav |
| `app.js` | `VIEW_IDS` 路由、`initCalendar/Learn/Stock/Journal/Settings`、wikilink/Markdown、AI context |
| `app.css` | 各視圖版面與元件樣式 |

### 後端模組職責

| 檔案 | 職責 |
|------|------|
| `server.js` | 路由表、TTL 常數、`buildPayload` / `refreshAndCache`、財報/股價快取邏輯、AI summarizer、`SETTINGS_FIELDS` |

---

## API 端點

所有 API 前綴為 `/api`，回傳 JSON（錯誤時附 `error` 訊息）。

### 總經

| 方法 | 路徑 | 說明 |
|------|------|------|
| GET | `/api/macro` | 整包總經 payload；`?fresh=1` 強制重抓 |
| GET | `/api/series/:key` | 單一指標歷史（走勢大圖） |
| GET | `/api/score-history` | 每日健康分數累積 |
| GET | `/api/events` | 歷史事件與危機案例 |

### 學習

| 方法 | 路徑 | 說明 |
|------|------|------|
| GET | `/api/knowledge` | 知識庫索引與 metadata |
| GET | `/api/note/:kind/:id` | 單篇筆記全文 |
| GET | `/api/graph` | vis-network 節點與邊 |

### 個股與日曆

| 方法 | 路徑 | 說明 |
|------|------|------|
| GET | `/api/fundamentals/:symbol` | 三表、比率、財測等 |
| GET | `/api/price/:symbol` | 歷史 OHLC（`range`, `interval`） |
| GET | `/api/quote/:symbol` | 即時報價 |
| GET | `/api/profile/:symbol` | 公司簡介 |
| GET | `/api/company-intel/:symbol` | 管理層、內部人、新聞 |
| GET | `/api/backtest/:symbol` | 策略回測結果 |
| GET | `/api/investmap` | 六層地圖設定 |
| GET | `/api/calendar` | 日曆事件 payload |
| GET/PUT | `/api/calendar/watchlist` | 追蹤財報代號清單 |

### 復盤

| 方法 | 路徑 | 說明 |
|------|------|------|
| GET | `/api/trades` | 交易列表 |
| GET | `/api/trades/stats` | 統計摘要 |
| POST | `/api/trades` | 新增 |
| PUT | `/api/trades/:id` | 更新 |
| DELETE | `/api/trades/:id` | 刪除 |

### AI 與設定

| 方法 | 路徑 | 說明 |
|------|------|------|
| POST | `/api/ai/models` | 依 provider 列出可用模型 |
| POST | `/api/ai/context` | 組裝目前頁面上下文 |
| POST | `/api/ai/chat` | 帶 context 的對話 |
| GET | `/api/settings/env` | 讀取設定（金鑰遮罩） |
| POST | `/api/settings/env` | 寫入 `.env` |
| GET | `/api/health` | `{ ok, knowledge }` 健康檢查 |

靜態檔：根目錄 `index.html`、`app.js`、`app.css` 由 Express 直接提供。

---

## 資料流與快取

| 功能 | 路徑 | 外部來源 | 持久化 |
|------|------|----------|--------|
| 總經 | `/api/macro` | FRED + Yahoo（黃金） | 記憶體 + `cache`/`series`/`score_history` |
| 日曆 | `/api/calendar` | 多源 iCal / API | `cache` 表（24h） |
| 學習 | `/api/knowledge` | `data/*.json` | 建置時快照 |
| 財報 | `/api/fundamentals/:s` | Yahoo → SEC | 通用 cache + SEC 探針 |
| 股價 | `/api/price/:s` | Yahoo → Nasdaq | 日線 6h / 週月 1d TTL |
| 復盤 | `/api/trades` | — | `trades` 表 |
| AI | `/api/ai/chat` | Grok / OpenCode | 無持久（僅請求日誌於 console） |

**SQLite 表（`lib/db.js`）：**

- `cache` — macro 整包、fundamentals、hist、quote、calendar 等 JSON
- `series` — 各 FRED 指標完整歷史點
- `score_history` — 每日健康分數
- `trades` — 使用者交易復盤

**財報快取邏輯（`server.js`）：**

1. 軟 TTL（預設 12h）內：完全不連網，直接用 DB。
2. 超過軟 TTL：輕量 SEC `getLatestFilingInfo` 探針；無新申報則續用快取。
3. 硬上限（預設 3 天）或探針失敗且過期：重抓 Yahoo/EDGAR。

失敗時盡量回傳 stale 資料並標記 `degraded`，避免畫面卡住。

---

## 建立知識庫

學習教材、財報健檢連結、投資地圖原則、知識圖譜皆依賴 `emmy/emmy` 快照：

```bash
npm run build:knowledge
```

產出：

- `data/knowledge.json` — 索引、分類、linkMap
- `data/notes.json` — 全文（key = `kind:id`）

`emmy/` 更新後重跑即可。未建置時學習頁會提示，且 `/api/health` 的 `knowledge: false`。

---

## 環境變數

見 `.env.example`：

| 變數 | 預設 | 說明 |
|------|------|------|
| `FRED_API_KEY` | — | 必填（總經） |
| `PORT` | `3000` | 伺服器埠 |
| `CACHE_TTL_SECONDS` | `3600` | 總經整包快取 |
| `FUND_SOFT_HOURS` | `12` | 財報軟 TTL |
| `FUND_HARD_DAYS` | `3` | 財報硬上限 |
| `HIST_SOFT_HOURS` | `6` | 日線股價快取 |
| `QUOTE_TTL_SECONDS` | `60` | 報價快取 |
| `GROK_*` / `OPENCODE_GO_*` | — | AI provider |
| `AI_ACTIVE_PROVIDER` | `grok` | 預設 provider |

---

## 技術棧

| 層級 | 技術 |
|------|------|
| 執行環境 | Node.js ≥ 18（ESM） |
| 後端 | Express 4、`dotenv`、內建 `node:sqlite` |
| 前端 | 純 HTML/CSS/Vanilla JS，無 bundler |
| CDN | mermaid@11、vis-network@9 |
| 依賴數 | 僅 2 個 npm 套件（express、dotenv） |

外部 API 金鑰與抓取**全部經 server 代理**，不出現在瀏覽器。

---

## 指標與資料來源

絕大多數指標對應 FRED 序列；黃金改用 Yahoo 期貨（FRED 無良好日線）。

### 免費替代指標（卡片標「替代」）

| 理想指標 | 替代序列 | 說明 |
|----------|----------|------|
| ISM 製造業 PMI | `GACDFSA066MSFRBPHI` | 費城聯儲製造業景氣 |
| 世界大型企業聯合會 CCI | `UMCSENT` | 密西根消費者信心 |
| 領先指標 LEI | `RECPROUSM156N` | NY Fed 衰退機率模型 |

另含工業生產年增（`INDPRO`）作實體經濟補充。

### 總經健康分數

從 **50 分（中性）** 出發，依殖利率曲線、衰退機率、通膨、就業、信用利差等規則加減，限制 0–100。中性參考指標（美元、油價等）不計分。

| 分數 | 燈號 |
|------|------|
| ≥ 65 | 景氣穩健 |
| 50–64 | 溫和成長 |
| 35–49 | 景氣放緩 |
| < 35 | 衰退風險高 |

教學用簡化模型，**不構成投資建議**。

---

## 常見問題

- **總經顯示要設定金鑰？** → AI 設定頁填 `FRED_API_KEY` 或編輯 `.env` 後重整。
- **學習頁空白？** → 確認 `finance/emmy/emmy` 存在，執行 `npm run build:knowledge`。
- **個股或卡片抓取失敗？** → 按「↻ 更新」；多數有 stale 回退。
- **AI 沒帶頁面資料？** → 設定 provider + model，在對應視圖（個股／學習筆記）再開 AI 面板。
- **要改指標或分數規則？** → 編輯 `lib/indicators.js`、`lib/score.js`，重啟 server。

---

## 免責聲明

本專案所有內容、工具、AI 回覆、回測與統計**僅供個人學習與研究**，不構成投資、財務、稅務或任何專業建議。投資有風險，請以 FRED、SEC、Yahoo 等官方來源為準。過去績效不代表未來表現。