|
|
|
|
|
"""
|
|
|
|
|
|
投資建議 Prompt V2 - Context Engineering + Prompt Engineering
|
|
|
|
|
|
|
|
|
|
|
|
核心改進:
|
|
|
|
|
|
1. Context Engineering: 加入用戶背景、市場環境、評分標準
|
|
|
|
|
|
2. Prompt Engineering: 強制一致性邏輯、嚴格輸出格式
|
|
|
|
|
|
3. 前端整合: 支援 Markdown 渲染
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from typing import Dict, Any
|
|
|
|
|
|
from datetime import datetime
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===== Context Engineering =====
|
|
|
|
|
|
|
|
|
|
|
|
def get_market_context(tw: bool = True) -> Dict[str, Any]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
獲取市場環境背景(從資料庫計算實際數據)
|
|
|
|
|
|
|
|
|
|
|
|
整合:
|
|
|
|
|
|
- 資料庫:從 stock_price_tw (0050.TW) 和 stock_price (SPY) 計算
|
|
|
|
|
|
- 快取:1小時 TTL 避免重複計算
|
|
|
|
|
|
- Fallback:資料庫查詢失敗時使用靜態資料
|
|
|
|
|
|
"""
|
|
|
|
|
|
try:
|
|
|
|
|
|
# 嘗試使用資料庫計算的實際市場數據
|
|
|
|
|
|
from market_benchmark import get_market_benchmark
|
|
|
|
|
|
benchmark = get_market_benchmark()
|
|
|
|
|
|
context = benchmark.get_market_context(tw)
|
|
|
|
|
|
|
|
|
|
|
|
# 如果是 fallback,記錄警告
|
|
|
|
|
|
if context.get('is_fallback'):
|
|
|
|
|
|
import logging
|
|
|
|
|
|
logging.warning(f"Using fallback market data for {'TW' if tw else 'US'}")
|
|
|
|
|
|
|
|
|
|
|
|
return context
|
|
|
|
|
|
|
|
|
|
|
|
except ImportError:
|
|
|
|
|
|
# market_benchmark 模組不存在,使用靜態資料
|
|
|
|
|
|
import logging
|
|
|
|
|
|
logging.warning("market_benchmark module not found, using static data")
|
|
|
|
|
|
return _get_static_market_context(tw)
|
|
|
|
|
|
except Exception as e:
|
|
|
|
|
|
# 其他錯誤,使用靜態資料
|
|
|
|
|
|
import logging
|
|
|
|
|
|
logging.error(f"Error loading market context: {e}, using static data")
|
|
|
|
|
|
return _get_static_market_context(tw)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def _get_static_market_context(tw: bool) -> Dict[str, Any]:
|
|
|
|
|
|
"""靜態市場資料(Fallback)"""
|
|
|
|
|
|
if tw:
|
|
|
|
|
|
return {
|
|
|
|
|
|
"market_name": "台灣加權指數(0050.TW)",
|
|
|
|
|
|
"ytd_return": 0.18,
|
|
|
|
|
|
"avg_5y_return": 0.09,
|
|
|
|
|
|
"volatility": 0.15,
|
|
|
|
|
|
"sentiment": "neutral",
|
|
|
|
|
|
"is_fallback": True
|
|
|
|
|
|
}
|
|
|
|
|
|
else:
|
|
|
|
|
|
return {
|
|
|
|
|
|
"market_name": "S&P 500(SPY)",
|
|
|
|
|
|
"ytd_return": 0.22,
|
|
|
|
|
|
"avg_5y_return": 0.12,
|
|
|
|
|
|
"volatility": 0.14,
|
|
|
|
|
|
"sentiment": "bull",
|
|
|
|
|
|
"is_fallback": True
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_investor_profile(risk_tolerance: str = "moderate") -> Dict[str, Any]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
投資人背景設定 (未來可從用戶資料庫讀取)
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
risk_tolerance: conservative/moderate/aggressive
|
|
|
|
|
|
"""
|
|
|
|
|
|
profiles = {
|
|
|
|
|
|
"conservative": {
|
|
|
|
|
|
"label": "保守型",
|
|
|
|
|
|
"max_acceptable_mdd": -0.15, # 最大可接受回落
|
|
|
|
|
|
"target_sharpe": 1.5, # 目標夏普比率
|
|
|
|
|
|
"description": "重視資本保全,追求穩定收益"
|
|
|
|
|
|
},
|
|
|
|
|
|
"moderate": {
|
|
|
|
|
|
"label": "穩健型",
|
|
|
|
|
|
"max_acceptable_mdd": -0.25,
|
|
|
|
|
|
"target_sharpe": 1.0,
|
|
|
|
|
|
"description": "平衡風險與報酬"
|
|
|
|
|
|
},
|
|
|
|
|
|
"aggressive": {
|
|
|
|
|
|
"label": "積極型",
|
|
|
|
|
|
"max_acceptable_mdd": -0.40,
|
|
|
|
|
|
"target_sharpe": 0.8,
|
|
|
|
|
|
"description": "追求高報酬,願意承擔較高風險"
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
return profiles.get(risk_tolerance, profiles["moderate"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_evaluation_criteria() -> Dict[str, Any]:
|
|
|
|
|
|
"""
|
|
|
|
|
|
明確的評分標準 (解決評價不一致問題)
|
|
|
|
|
|
"""
|
|
|
|
|
|
return {
|
|
|
|
|
|
"sharpe_ratio": {
|
|
|
|
|
|
"excellent": 2.0, # >= 2.0
|
|
|
|
|
|
"good": 1.5, # >= 1.5
|
|
|
|
|
|
"acceptable": 1.0, # >= 1.0
|
|
|
|
|
|
"poor": 0.5, # >= 0.5
|
|
|
|
|
|
"very_poor": 0.0 # < 0.5
|
|
|
|
|
|
},
|
|
|
|
|
|
"annual_return": {
|
|
|
|
|
|
"tw": {"excellent": 0.15, "good": 0.10, "acceptable": 0.08, "poor": 0.05},
|
|
|
|
|
|
"us": {"excellent": 0.18, "good": 0.12, "acceptable": 0.10, "poor": 0.06}
|
|
|
|
|
|
},
|
|
|
|
|
|
"mdd": {
|
|
|
|
|
|
"low_risk": -0.15, # < -15% 算低風險
|
|
|
|
|
|
"medium_risk": -0.25, # -15% ~ -25%
|
|
|
|
|
|
"high_risk": -0.40, # -25% ~ -40%
|
|
|
|
|
|
"extreme_risk": -0.40 # > -40%
|
|
|
|
|
|
},
|
|
|
|
|
|
"beta": {
|
|
|
|
|
|
"defensive": 0.8, # < 0.8
|
|
|
|
|
|
"balanced": 1.2, # 0.8 ~ 1.2
|
|
|
|
|
|
"aggressive": 1.2 # > 1.2
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ===== Prompt Engineering =====
|
|
|
|
|
|
|
|
|
|
|
|
def get_context_aware_prompt(strategy_data: Dict[str, Any],
|
|
|
|
|
|
risk_tolerance: str = "moderate",
|
|
|
|
|
|
use_cot: bool = True) -> str:
|
|
|
|
|
|
"""
|
|
|
|
|
|
Context-Aware Prompt with Strict Evaluation Logic
|
|
|
|
|
|
|
|
|
|
|
|
Args:
|
|
|
|
|
|
strategy_data: 策略數據
|
|
|
|
|
|
risk_tolerance: 風險承受度 (conservative/moderate/aggressive)
|
|
|
|
|
|
use_cot: 是否使用 Chain-of-Thought
|
|
|
|
|
|
"""
|
|
|
|
|
|
# 提取數據
|
|
|
|
|
|
annual_ret = strategy_data.get('annual_ret', 0)
|
|
|
|
|
|
vol = strategy_data.get('vol', 0)
|
|
|
|
|
|
sharpe = strategy_data.get('annual_sr', 0)
|
|
|
|
|
|
mdd = strategy_data.get('mdd', 0)
|
|
|
|
|
|
alpha = strategy_data.get('alpha', 0)
|
|
|
|
|
|
beta = strategy_data.get('beta', 0)
|
|
|
|
|
|
var10 = strategy_data.get('var10', 0)
|
|
|
|
|
|
r2 = strategy_data.get('r2', 0)
|
|
|
|
|
|
assets = strategy_data.get('assets', [])
|
|
|
|
|
|
name = strategy_data.get('name', 'N/A')
|
|
|
|
|
|
role = strategy_data.get('role', 'N/A')
|
|
|
|
|
|
tw = strategy_data.get('tw', True)
|
|
|
|
|
|
|
|
|
|
|
|
# Context Engineering
|
|
|
|
|
|
market_ctx = get_market_context(tw)
|
|
|
|
|
|
investor_profile = get_investor_profile(risk_tolerance)
|
|
|
|
|
|
criteria = get_evaluation_criteria()
|
|
|
|
|
|
|
|
|
|
|
|
# 構建評分邏輯
|
|
|
|
|
|
evaluation_logic = f"""
|
|
|
|
|
|
## 評分標準與邏輯 (CRITICAL: 必須嚴格遵守)
|
|
|
|
|
|
|
|
|
|
|
|
### 1. 夏普比率評級
|
|
|
|
|
|
```python
|
|
|
|
|
|
if sharpe >= {criteria['sharpe_ratio']['excellent']}:
|
|
|
|
|
|
rating = "優秀"
|
|
|
|
|
|
description = "風險調整後報酬表現卓越"
|
|
|
|
|
|
elif sharpe >= {criteria['sharpe_ratio']['good']}:
|
|
|
|
|
|
rating = "良好"
|
|
|
|
|
|
description = "風險調整後報酬表現良好"
|
|
|
|
|
|
elif sharpe >= {criteria['sharpe_ratio']['acceptable']}:
|
|
|
|
|
|
rating = "可接受"
|
|
|
|
|
|
description = "風險調整後報酬尚可"
|
|
|
|
|
|
elif sharpe >= {criteria['sharpe_ratio']['poor']}:
|
|
|
|
|
|
rating = "待改善"
|
|
|
|
|
|
description = "風險調整後報酬偏低"
|
|
|
|
|
|
else:
|
|
|
|
|
|
rating = "不佳"
|
|
|
|
|
|
description = "風險調整後報酬表現不佳"
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
**本策略夏普比率: {sharpe:.2f}** → 請依上述邏輯給予評級,並保持一致性。
|
|
|
|
|
|
|
|
|
|
|
|
### 2. 報酬率評級 (相對於市場基準)
|
|
|
|
|
|
- 市場基準: {market_ctx['market_name']} 近5年平均 {market_ctx['avg_5y_return']:.1%}
|
|
|
|
|
|
- 本策略: {annual_ret:.2%}
|
|
|
|
|
|
- 相對表現: {((annual_ret / market_ctx['avg_5y_return']) - 1) * 100:+.1f}%
|
|
|
|
|
|
|
|
|
|
|
|
### 3. 風險評級
|
|
|
|
|
|
- 最大回落: {mdd:.2%}
|
|
|
|
|
|
- 投資人可接受範圍: {investor_profile['max_acceptable_mdd']:.1%}
|
|
|
|
|
|
- 超出程度: {((abs(mdd) / abs(investor_profile['max_acceptable_mdd'])) - 1) * 100:+.1f}%
|
|
|
|
|
|
|
|
|
|
|
|
### 4. 市場相關性
|
|
|
|
|
|
- Beta: {beta:.2f}
|
|
|
|
|
|
- 類型: {"防禦型 (< 0.8)" if beta < criteria['beta']['defensive'] else "均衡型 (0.8-1.2)" if beta < criteria['beta']['balanced'] else "進攻型 (> 1.2)"}
|
|
|
|
|
|
- 預期波動: 市場變動 1%,策略預期變動 {beta:.2f}%
|
|
|
|
|
|
|
|
|
|
|
|
### 5. 超額收益能力
|
|
|
|
|
|
- Alpha: {alpha:.4f}
|
|
|
|
|
|
- 解釋: {"創造超額收益 ✓" if alpha > 0.01 else "與市場同步 ≈" if alpha >= -0.01 else "落後市場 ✗"}
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
# 一致性邏輯檢查
|
|
|
|
|
|
consistency_check = f"""
|
|
|
|
|
|
## 一致性邏輯檢查 (MUST FOLLOW)
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ **禁止自相矛盾**:
|
|
|
|
|
|
1. 如果夏普比率評級為「優秀」,整體評價不能說「表現一般」
|
|
|
|
|
|
2. 如果報酬率遠超市場,風險評價不能忽略這個亮點
|
|
|
|
|
|
3. 如果 MDD 超出可接受範圍,必須在風險警示中明確指出
|
|
|
|
|
|
|
|
|
|
|
|
✅ **評價優先順序**:
|
|
|
|
|
|
1. 首先看風險調整後報酬 (夏普比率) → 這是最重要的指標
|
|
|
|
|
|
2. 其次看絕對報酬 vs 市場基準
|
|
|
|
|
|
3. 最後看風險承受度匹配性
|
|
|
|
|
|
|
|
|
|
|
|
📊 **本策略快速判讀**:
|
|
|
|
|
|
- 夏普 {sharpe:.2f}: {"優秀 ✓" if sharpe >= 2.0 else "良好 ✓" if sharpe >= 1.5 else "可接受 ○" if sharpe >= 1.0 else "待改善 ✗"}
|
|
|
|
|
|
- 報酬 {annual_ret:.2%} vs 市場 {market_ctx['avg_5y_return']:.1%}: {"超越 ✓" if annual_ret > market_ctx['avg_5y_return'] * 1.2 else "接近 ○" if annual_ret > market_ctx['avg_5y_return'] * 0.8 else "落後 ✗"}
|
|
|
|
|
|
- 風險 {mdd:.2%}: {"可接受 ✓" if abs(mdd) <= abs(investor_profile['max_acceptable_mdd']) else "偏高 ⚠️"}
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
# CoT 推理步驟
|
|
|
|
|
|
cot_steps = """
|
|
|
|
|
|
## 推理步驟 (Chain-of-Thought)
|
|
|
|
|
|
|
|
|
|
|
|
請按以下順序思考並輸出:
|
|
|
|
|
|
|
|
|
|
|
|
**步驟 1: 指標解讀**
|
|
|
|
|
|
- 先單獨解讀每個指標的絕對值
|
|
|
|
|
|
- 再與市場基準比較
|
|
|
|
|
|
- 最後與投資人預期比較
|
|
|
|
|
|
|
|
|
|
|
|
**步驟 2: 綜合評分**
|
|
|
|
|
|
- 根據評分標準,給出各維度評級
|
|
|
|
|
|
- 注意保持一致性(不要有矛盾)
|
|
|
|
|
|
- 找出最突出的優勢和劣勢
|
|
|
|
|
|
|
|
|
|
|
|
**步驟 3: 情境分析**
|
|
|
|
|
|
- 假設投入 100 萬資金
|
|
|
|
|
|
- 最好情況能賺多少?(基於年化報酬)
|
|
|
|
|
|
- 最壞情況會虧多少?(基於 MDD)
|
|
|
|
|
|
- 承受 1 單位風險能換多少報酬?(基於夏普)
|
|
|
|
|
|
|
|
|
|
|
|
**步驟 4: 投資建議**
|
|
|
|
|
|
- 這個策略適合哪種投資人?
|
|
|
|
|
|
- 在什麼市場環境下表現最好?
|
|
|
|
|
|
- 需要做哪些調整才能更好?
|
|
|
|
|
|
""" if use_cot else ""
|
|
|
|
|
|
|
|
|
|
|
|
# 嚴格禁止事項
|
|
|
|
|
|
strict_prohibitions = f"""
|
|
|
|
|
|
## ⛔ 嚴格禁止事項 (CRITICAL - MUST FOLLOW)
|
|
|
|
|
|
|
|
|
|
|
|
1. **禁止自己假設或生成市場數據**
|
|
|
|
|
|
- ❌ 禁止說「假設台灣加權指數同期間年化報酬率為 12%...」
|
|
|
|
|
|
- ❌ 禁止說「為了更精確的比較,我們需要...」
|
|
|
|
|
|
- ✅ **必須使用已提供的市場基準數據**: {market_ctx['market_name']} 近5年平均 {market_ctx['avg_5y_return']:.1%}
|
|
|
|
|
|
|
|
|
|
|
|
2. **禁止模糊或矛盾的評價**
|
|
|
|
|
|
- ❌ 禁止說「優秀的投資策略...風險調整後報酬表現一般」
|
|
|
|
|
|
- ❌ 禁止說「良好但待改善」
|
|
|
|
|
|
- ✅ 必須根據夏普比率給出**明確且一致**的評級
|
|
|
|
|
|
|
|
|
|
|
|
3. **禁止使用模板化語言**
|
|
|
|
|
|
- ❌ 禁止說「策略基本資訊回顧」「歷史表現趨勢分析」等空泛標題
|
|
|
|
|
|
- ✅ 必須根據**實際數據**給出具體分析
|
|
|
|
|
|
|
|
|
|
|
|
4. **市場基準說明**
|
|
|
|
|
|
- 台灣市場: 使用 **0050.TW (元大台灣50)** 作為市場代理指標
|
|
|
|
|
|
- 理由: 追蹤台灣市值前50大公司,涵蓋約70%市值,流動性高
|
|
|
|
|
|
- 美國市場: 使用 **SPY (SPDR S&P 500 ETF)** 作為市場代理指標
|
|
|
|
|
|
- **直接使用提供的數據,不要質疑或假設其他數據**
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
# 輸出格式要求(專業深度版)
|
|
|
|
|
|
output_format = """
|
|
|
|
|
|
## 輸出格式要求 (STRICT)
|
|
|
|
|
|
|
|
|
|
|
|
**目標對象**:專業投資人、進階使用者
|
|
|
|
|
|
**字數控制**:1500-2000 字
|
|
|
|
|
|
**特色**:顯示完整推理過程、技術性分析、數學計算
|
|
|
|
|
|
|
|
|
|
|
|
請用以下 Markdown 格式輸出:
|
|
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
|
## 📊 策略總評
|
|
|
|
|
|
|
|
|
|
|
|
[一句話總結:綜合評級 + 核心特性] (不超過 30 字)
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🎯 核心指標分析
|
|
|
|
|
|
|
|
|
|
|
|
### 風險調整後報酬
|
|
|
|
|
|
**夏普比率 {sharpe:.2f}** → [優秀/良好/可接受/待改善]
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
推理過程:
|
|
|
|
|
|
- 業界標準: ≥2.0 優秀, ≥1.5 良好, ≥1.0 可接受
|
|
|
|
|
|
- 本策略: {sharpe:.2f}
|
|
|
|
|
|
- 意義: 每承受 1% 風險,獲得 {sharpe:.2f}% 超額報酬
|
|
|
|
|
|
→ 結論: [具體評價]
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 報酬表現
|
|
|
|
|
|
**年化報酬 {annual_ret:.2%}** vs **市場基準 {market_ctx['avg_5y_return']:.1%}**
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
推理過程:
|
|
|
|
|
|
- 絕對報酬: {annual_ret:.2%}
|
|
|
|
|
|
- 相對市場: {((annual_ret / market_ctx['avg_5y_return']) - 1) * 100:+.1f}%
|
|
|
|
|
|
- 情境假設: 投入 100 萬,一年後預期變為 {100 * (1 + annual_ret):.1f} 萬
|
|
|
|
|
|
→ 結論: [超越/接近/落後]市場表現
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 風險評估
|
|
|
|
|
|
**最大回落 {mdd:.2%}** | **波動率 {vol:.2%}**
|
|
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
|
推理過程:
|
|
|
|
|
|
- 歷史最大虧損: {mdd:.2%}
|
|
|
|
|
|
- 投資人可接受範圍: {investor_profile['max_acceptable_mdd']:.1%}
|
|
|
|
|
|
- 情境假設: 投入 100 萬,最壞情況虧損 {abs(100 * mdd):.1f} 萬
|
|
|
|
|
|
→ 結論: 風險水平 [低/中/高],[適合/不適合] {investor_profile['label']}投資人
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 💡 投資建議
|
|
|
|
|
|
|
|
|
|
|
|
### ✅ 策略亮點
|
|
|
|
|
|
1. [最突出的優勢,用數據支持]
|
|
|
|
|
|
2. [第二個優勢]
|
|
|
|
|
|
|
|
|
|
|
|
### ⚠️ 風險提示
|
|
|
|
|
|
1. [最主要的風險,量化說明]
|
|
|
|
|
|
2. [次要風險]
|
|
|
|
|
|
|
|
|
|
|
|
### 🎯 適合對象
|
|
|
|
|
|
- **投資人類型**: [保守/穩健/積極]
|
|
|
|
|
|
- **投資期限**: [短期/中期/長期]
|
|
|
|
|
|
- **市場環境**: [牛市/震盪/熊市]
|
|
|
|
|
|
|
|
|
|
|
|
### 🔧 優化建議
|
|
|
|
|
|
[1-2 個具體的改進方向]
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📈 未來展望
|
|
|
|
|
|
|
|
|
|
|
|
[基於當前市場環境 {market_ctx['sentiment']},給出 3-6 個月展望]
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
*本分析基於歷史數據回測,過往績效不代表未來表現。建議搭配即時市場分析與專業投資顧問。*
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ **重要**:
|
|
|
|
|
|
1. 禁止使用模糊詞彙(「優秀但一般」「良好卻待改善」)
|
|
|
|
|
|
2. 每個評價必須有數據支持
|
|
|
|
|
|
3. 推理過程要顯示計算邏輯
|
|
|
|
|
|
4. 結論必須與推理過程一致
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
# 組合完整 Prompt
|
|
|
|
|
|
full_prompt = f"""
|
|
|
|
|
|
你是一位資深投資顧問(CFA, 20+ 年經驗)。請基於以下背景與數據,提供專業投資分析。
|
|
|
|
|
|
|
|
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
## 投資人背景
|
|
|
|
|
|
- 風險承受度:**{investor_profile['label']}** ({investor_profile['description']})
|
|
|
|
|
|
- 目標夏普比率:≥ {investor_profile['target_sharpe']:.1f}
|
|
|
|
|
|
- 可接受最大回落:{investor_profile['max_acceptable_mdd']:.1%}
|
|
|
|
|
|
|
|
|
|
|
|
## 市場環境
|
|
|
|
|
|
- 市場:{market_ctx['market_name']}
|
|
|
|
|
|
- 今年表現:{market_ctx['ytd_return']:.1%}
|
|
|
|
|
|
- 近5年平均:{market_ctx['avg_5y_return']:.1%}
|
|
|
|
|
|
- 市場情緒:{market_ctx['sentiment']}
|
|
|
|
|
|
|
|
|
|
|
|
## 策略資訊
|
|
|
|
|
|
- 名稱:{name}
|
|
|
|
|
|
- 目標:{role}
|
|
|
|
|
|
- 持股:{', '.join(assets[:5])}{"..." if len(assets) > 5 else ""} (共 {len(assets)} 檔)
|
|
|
|
|
|
|
|
|
|
|
|
## 績效數據
|
|
|
|
|
|
| 指標 | 數值 |
|
|
|
|
|
|
|------|------|
|
|
|
|
|
|
| 年化報酬率 | {annual_ret:.1%} |
|
|
|
|
|
|
| 年化波動率 | {vol:.1%} |
|
|
|
|
|
|
| 夏普比率 | {sharpe:.1f} |
|
|
|
|
|
|
| 最大回落 (MDD) | {mdd:.2%} |
|
|
|
|
|
|
| Alpha | {alpha:.1f} |
|
|
|
|
|
|
| Beta | {beta:.2f} |
|
|
|
|
|
|
| VaR (95%) | {var10:.2%} |
|
|
|
|
|
|
| R² | {r2:.2%} |
|
|
|
|
|
|
|
|
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
|
|
|
|
|
|
{strict_prohibitions}
|
|
|
|
|
|
|
|
|
|
|
|
{evaluation_logic}
|
|
|
|
|
|
|
|
|
|
|
|
{consistency_check}
|
|
|
|
|
|
|
|
|
|
|
|
{cot_steps}
|
|
|
|
|
|
|
|
|
|
|
|
{output_format}
|
|
|
|
|
|
|
|
|
|
|
|
現在請開始分析,記住:**數據驅動,邏輯一致,評價明確,禁止假設市場數據**。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
return full_prompt
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_simplified_context_prompt(strategy_data: Dict[str, Any]) -> str:
|
|
|
|
|
|
"""
|
|
|
|
|
|
教育性詳細版 Context-Aware Prompt(為普羅大眾設計,預設模式)
|
|
|
|
|
|
|
|
|
|
|
|
目標對象:投資新手、一般散戶
|
|
|
|
|
|
|
|
|
|
|
|
特色:
|
|
|
|
|
|
- 白話文解釋每個指標的意義
|
|
|
|
|
|
- 舉例說明(投入100萬的情境)
|
|
|
|
|
|
- 說明為什麼這個數字重要
|
|
|
|
|
|
- 提供具體優化建議
|
|
|
|
|
|
- 字數控制在 1000-1500 字
|
|
|
|
|
|
|
|
|
|
|
|
適用於:use_cot=False(預設模式,不顯示推理步驟,但內容詳盡)
|
|
|
|
|
|
"""
|
|
|
|
|
|
annual_ret = strategy_data.get('annual_ret', 0)
|
|
|
|
|
|
sharpe = strategy_data.get('annual_sr', 0)
|
|
|
|
|
|
vol = strategy_data.get('vol', 0)
|
|
|
|
|
|
mdd = strategy_data.get('mdd', 0)
|
|
|
|
|
|
beta = strategy_data.get('beta', 0)
|
|
|
|
|
|
alpha = strategy_data.get('alpha', 0)
|
|
|
|
|
|
var10 = strategy_data.get('var10', 0)
|
|
|
|
|
|
r2 = strategy_data.get('r2', 0)
|
|
|
|
|
|
tw = strategy_data.get('tw', True)
|
|
|
|
|
|
assets = strategy_data.get('assets', [])
|
|
|
|
|
|
name = strategy_data.get('name', 'N/A')
|
|
|
|
|
|
|
|
|
|
|
|
market_ctx = get_market_context(tw)
|
|
|
|
|
|
criteria = get_evaluation_criteria()
|
|
|
|
|
|
|
|
|
|
|
|
# 評分邏輯
|
|
|
|
|
|
sharpe_rating = "優秀" if sharpe >= 2.0 else "良好" if sharpe >= 1.5 else "可接受" if sharpe >= 1.0 else "待改善"
|
|
|
|
|
|
return_vs_market = ((annual_ret / market_ctx['avg_5y_return']) - 1) * 100
|
|
|
|
|
|
|
|
|
|
|
|
return f"""
|
|
|
|
|
|
你是一位資深投資教育講師,專門為**投資新手和普羅大眾**解釋投資策略。
|
|
|
|
|
|
|
|
|
|
|
|
你的任務是:
|
|
|
|
|
|
1. **用白話文**解釋每個績效指標的意義
|
|
|
|
|
|
2. **說明為什麼**這個指標重要
|
|
|
|
|
|
3. **給予具體的優化建議**
|
|
|
|
|
|
4. **避免使用過多專業術語**,如果必須使用,請解釋清楚
|
|
|
|
|
|
|
|
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
## 策略基本資訊
|
|
|
|
|
|
- **策略名稱**: {name}
|
|
|
|
|
|
- **投資市場**: {'🇹🇼 台灣股市' if tw else '🇺🇸 美國股市'}
|
|
|
|
|
|
- **持股標的**: {', '.join(assets[:10])}{"..." if len(assets) > 10 else ""} (共 {len(assets)} 檔)
|
|
|
|
|
|
- **對比基準**: {market_ctx['market_name']} (近5年平均 {market_ctx['avg_5y_return']:.1%})
|
|
|
|
|
|
|
|
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
|
|
|
|
|
|
## 📊 核心績效對比表(你的策略 vs 市場)
|
|
|
|
|
|
|
|
|
|
|
|
| 指標 | 你的策略 | 市場基準 | 差異 | 評價 |
|
|
|
|
|
|
|------|---------|---------|------|------|
|
|
|
|
|
|
| 📈 年化報酬率 | {annual_ret:.2%} | {market_ctx['avg_5y_return']:.1%} | {return_vs_market:+.1f}% | {'🚀 大勝' if return_vs_market > 50 else '✅ 超越' if return_vs_market > 0 else '❌ 落後'} |
|
|
|
|
|
|
| ⭐ 夏普比率 | {sharpe:.2f} | ~1.0 | {(sharpe - 1.0):+.2f} | {sharpe_rating} |
|
|
|
|
|
|
| 📊 波動率 | {vol:.2%} | {market_ctx.get('volatility', 0.20):.1%} | {(vol - market_ctx.get('volatility', 0.20)) * 100:+.1f}% | {'⚠️ 較高' if vol > market_ctx.get('volatility', 0.20) * 1.2 else '✅ 適中'} |
|
|
|
|
|
|
| ⚠️ 最大回落 | {mdd:.2%} | ~-30% | {'更深' if abs(mdd) > 0.30 else '相近'} | {'❌ 風險高' if abs(mdd) > 0.30 else '✅ 可控'} |
|
|
|
|
|
|
|
|
|
|
|
|
## 🎯 主動管理能力
|
|
|
|
|
|
|
|
|
|
|
|
| 指標 | 數值 | 說明 |
|
|
|
|
|
|
|------|------|------|
|
|
|
|
|
|
| 🎯 Alpha (超額報酬) | {alpha:.4f} | {'✅ 打敗市場' if alpha > 0.01 else '≈ 跟隨市場' if alpha >= -0.01 else '❌ 落後市場'} |
|
|
|
|
|
|
| ⚖️ Beta (市場相關性) | {beta:.2f} | {'🔥 進攻型 (Beta > 1.2)' if beta > 1.2 else '⚖️ 均衡型 (Beta 0.8-1.2)' if beta > 0.8 else '🛡️ 防禦型 (Beta < 0.8)'} |
|
|
|
|
|
|
| 📐 R² (可解釋度) | {r2:.2%} | 策略中 {r2:.1%} 的波動來自市場影響 |
|
|
|
|
|
|
| 📉 VaR (風險值) | {var10:.2%} | 95%信心水準下的最大單日損失 |
|
|
|
|
|
|
|
|
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
|
|
|
|
|
|
## ⛔ 重要指示
|
|
|
|
|
|
|
|
|
|
|
|
1. **禁止假設數據** - 市場基準 {market_ctx['avg_5y_return']:.1%} 已提供,直接使用
|
|
|
|
|
|
2. **評級必須一致** - 夏普 {sharpe:.2f} = 「{sharpe_rating}」
|
|
|
|
|
|
3. **用白話文** - 避免過多專業術語
|
|
|
|
|
|
4. **解釋每個指標** - 說明它的意義和為什麼重要
|
|
|
|
|
|
|
|
|
|
|
|
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
|
|
|
|
|
|
|
|
|
|
## 📝 輸出格式(教育性詳細版)
|
|
|
|
|
|
|
|
|
|
|
|
請用 1200-1600 字,包含以下內容:
|
|
|
|
|
|
|
|
|
|
|
|
```markdown
|
|
|
|
|
|
## 📊 一句話總評
|
|
|
|
|
|
|
|
|
|
|
|
[根據夏普比率和報酬率,給一個清晰的總評,30字內]
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📋 你選了哪些股票?
|
|
|
|
|
|
|
|
|
|
|
|
{', '.join(assets[:15])}{"..." if len(assets) > 15 else ""}(共 {len(assets)} 檔)
|
|
|
|
|
|
|
|
|
|
|
|
**組合特性:**
|
|
|
|
|
|
- **產業分布**: [分析持股集中在哪些產業,例如:科技股佔50%、金融股佔30%]
|
|
|
|
|
|
- **風險分散度**: [評估是否分散,例如:持股{len(assets)}檔,{'分散良好' if len(assets) >= 8 else '偏集中' if len(assets) >= 5 else '非常集中'}]
|
|
|
|
|
|
- **代表性個股**: [列出前3-5檔重要持股,簡述其特色]
|
|
|
|
|
|
|
|
|
|
|
|
**💡 持股建議:**
|
|
|
|
|
|
[根據持股數量和類型,給予是否需要調整的建議]
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📊 績效表現分析(vs 市場基準)
|
|
|
|
|
|
|
|
|
|
|
|
### 1️⃣ 賺錢能力:年化報酬率 {annual_ret:.2%}
|
|
|
|
|
|
|
|
|
|
|
|
**白話文解釋:**
|
|
|
|
|
|
假設你投入 100 萬,一年後預期變成 **{100 * (1 + annual_ret):.1f} 萬**({'賺' if annual_ret > 0 else '虧'} {abs(100 * annual_ret):.1f} 萬)。
|
|
|
|
|
|
|
|
|
|
|
|
**vs 市場表現:**
|
|
|
|
|
|
- 📈 你的策略:{annual_ret:.2%}
|
|
|
|
|
|
- 📊 市場平均:{market_ctx['avg_5y_return']:.1%}({market_ctx['market_name']})
|
|
|
|
|
|
- 🎯 相對表現:{return_vs_market:+.1f}%
|
|
|
|
|
|
|
|
|
|
|
|
**評價:** {'🚀 遠超市場表現!' if return_vs_market > 50 else '✅ 打敗市場' if return_vs_market > 20 else '✓ 略勝市場' if return_vs_market > 0 else '❌ 落後市場'}
|
|
|
|
|
|
|
|
|
|
|
|
**為什麼重要?**
|
|
|
|
|
|
[解釋報酬率是投資最直觀的指標,但不能只看報酬率,還要考慮風險]
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 2️⃣ 投資CP值:夏普比率 {sharpe:.2f} → {sharpe_rating}
|
|
|
|
|
|
|
|
|
|
|
|
**白話文解釋:**
|
|
|
|
|
|
「CP值」就是夏普比率!每承受 1 元風險,你能賺 {sharpe:.2f} 元報酬。
|
|
|
|
|
|
|
|
|
|
|
|
**評級:**
|
|
|
|
|
|
- ⭐⭐⭐ 優秀 (≥ 2.0) - CP值超高!
|
|
|
|
|
|
- ⭐⭐ 良好 (≥ 1.5) - CP值不錯
|
|
|
|
|
|
- ⭐ 可接受 (≥ 1.0) - CP值及格 ← {'你在這裡' if 1.0 <= sharpe < 1.5 else ''}
|
|
|
|
|
|
- 待改善 (< 1.0) - CP值偏低
|
|
|
|
|
|
|
|
|
|
|
|
**為什麼重要?**
|
|
|
|
|
|
[解釋夏普比率是同時考慮報酬和風險的指標,比單看報酬率更全面]
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 3️⃣ 最大虧損風險:最大回落 {mdd:.2%}
|
|
|
|
|
|
|
|
|
|
|
|
**白話文解釋:**
|
|
|
|
|
|
投入 100 萬,最慘的時候會虧到剩 **{100 * (1 + mdd):.1f} 萬**(虧損 {abs(100 * mdd):.1f} 萬)。
|
|
|
|
|
|
|
|
|
|
|
|
**vs 市場風險:**
|
|
|
|
|
|
- 你的策略:{mdd:.2%}
|
|
|
|
|
|
- 一般市場:約 -30%
|
|
|
|
|
|
- 評價:{'❌ 風險較高' if abs(mdd) > 0.30 else '✅ 風險可控'}
|
|
|
|
|
|
|
|
|
|
|
|
**心理測試:**
|
|
|
|
|
|
[問投資人是否能接受這個程度的虧損]
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
### 4️⃣ 主動選股價值:Alpha {alpha:.4f} & Beta {beta:.2f}
|
|
|
|
|
|
|
|
|
|
|
|
**Alpha 超額報酬:** {'✅ +{alpha:.2%} 打敗市場' if alpha > 0.01 else '≈ 跟隨市場' if alpha >= -0.01 else '❌ 落後市場'}
|
|
|
|
|
|
**Beta 市場連動:** {'🔥 進攻型' if beta > 1.2 else '⚖️ 均衡型' if beta > 0.8 else '🛡️ 防禦型'}
|
|
|
|
|
|
|
|
|
|
|
|
**白話文解釋:**
|
|
|
|
|
|
- Alpha:扣除市場影響後,你的選股能力創造的額外報酬
|
|
|
|
|
|
- Beta:當市場漲 1%,你的策略預期漲 {beta:.2f}%
|
|
|
|
|
|
|
|
|
|
|
|
**為什麼重要?**
|
|
|
|
|
|
[解釋主動選股的價值,以及不同市場環境下的策略表現]
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 🎯 給投資人的建議
|
|
|
|
|
|
|
|
|
|
|
|
### ✅ 這個策略的優勢
|
|
|
|
|
|
[列出2-3個具體優點,用數據支持]
|
|
|
|
|
|
|
|
|
|
|
|
### ⚠️ 需要注意的風險
|
|
|
|
|
|
[列出2-3個具體風險,量化說明]
|
|
|
|
|
|
|
|
|
|
|
|
### 🔧 如何優化這個策略?
|
|
|
|
|
|
[給3個具體的優化建議]
|
|
|
|
|
|
1. [建議1:例如分散持股、調整權重等]
|
|
|
|
|
|
2. [建議2:例如設定停損點]
|
|
|
|
|
|
3. [建議3:例如定期再平衡]
|
|
|
|
|
|
|
|
|
|
|
|
### 💼 適合什麼樣的投資人?
|
|
|
|
|
|
- **風險承受度**: [保守/穩健/積極]
|
|
|
|
|
|
- **投資期限**: [建議持有多久]
|
|
|
|
|
|
- **市場環境**: [適合牛市/震盪/熊市]
|
|
|
|
|
|
- **資金用途**: [閒錢/退休金/教育基金]
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
## 📈 總結
|
|
|
|
|
|
|
|
|
|
|
|
[用2-3句話總結這個策略的核心特點,並給出明確的投資建議]
|
|
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
|
|
*💡 小提醒:過去績效不代表未來表現,投資一定有風險,建議搭配專業顧問意見。*
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
⚠️ **輸出要求**:
|
|
|
|
|
|
1. **字數**: 1000-1500 字(教育性內容,不能太少)
|
|
|
|
|
|
2. **語氣**: 親切、易懂,像在跟朋友聊天
|
|
|
|
|
|
3. **避免**: 「策略基本資訊回顧」等空泛標題
|
|
|
|
|
|
4. **必須**: 解釋每個指標的意義和重要性
|
|
|
|
|
|
5. **必須**: 給出具體的優化建議
|
|
|
|
|
|
"""
|