iT邦幫忙

2026 iThome 鐵人賽

DAY 5
0
Build on Google AI

基本面與技術面組合投資模型建置系列 第 7

用實作來讓理論可以用適用的狀況實現

  • 分享至 

  • xImage
  •  

第八天 09/22
本日需要用到Gemini 1.5模型來建立一個基本面代理
一、 基本面代理與 Gemini 1.5 JSON 模式實作
為了讓前述的「計算器引擎」能夠動態接收高階財務假設,我們需要建立一個基本面代理(Fundamental Agent)。該代理利用 Gemini 1.5 模型的強大語意理解能力,並透過 responseMimeType: "application/json" 與 responseSchema 強制輸出結構化資料,自動生成適用於 DCF 模型的「基準(Base)」、「樂觀(Bull)」與「保守(Bear)」三種情境假設。

  1. 定義 Pydantic / Schema 資料結構
    在 Python 環境中,建議使用 pydantic 定義型別,並將其傳入 Gemini API 進行型別約束:

Python
from pydantic import BaseModel, Field
from google import genai
from google.genai import types

class ScenarioAssumptions(BaseModel):
wacc: float = Field(description="加權平均資金成本 (WACC),例:0.085")
terminal_growth_rate: float = Field(description="永續成長率,例:0.025")
revenue_growth_rates: list[float] = Field(description="未來5年的營收成長率列表")
operating_margin: float = Field(description="預期營業利益率,例:0.20")

class DCFScenarioResponse(BaseModel):
ticker: str
base_case: ScenarioAssumptions
bull_case: ScenarioAssumptions
bear_case: ScenarioAssumptions
reasoning: str = Field(description="簡短說明情境設定之基本面論述")

呼叫 Gemini 1.5 API 取得強型別 JSON

client = genai.Client()
response = client.models.generate_content(
model="gemini-1.5-pro", # 或 gemini-1.5-flash
contents="請分析台積電 (2330) 未來 5 年的基本面,並給出 DCF 三種情境的假設數據。",
config=types.GenerateContentConfig(
response_mime_type="application/json",
response_schema=DCFScenarioResponse,
temperature=0.2, # 低隨機性以維持數據穩定
),
)

  1. 與模組化計算器引擎對接
    將 LLM 回傳解析後的 ScenarioAssumptions 直接注入前述的計算器管道:

TypeScript
// 引擎轉換管道概念實作
interface DCFInput {
wacc: number;
g: number;
fcfList: number[];
}

function runScenarioEvaluation(assumptions: ScenarioAssumptions, currentFCF: number, engine: CalculatorEngine): number {
// 1. 動態建構未來現金流公式表達式
let totalPV = 0;
assumptions.revenue_growth_rates.forEach((rate, index) => {
const year = index + 1;
const fcfExpr = ${currentFCF} * ((1 + ${rate}) ^ ${year}) / ((1 + ${assumptions.wacc}) ^ ${year});
totalPV += engine.evaluate(fcfExpr); // 呼叫先前實作的計算引擎
});

// 2. 計算終值 (Terminal Value) 併入
const lastFCF = currentFCF * assumptions.revenue_growth_rates.reduce((acc, r) => acc * (1 + r), 1);
const tvExpr = (${lastFCF} * (1 + ${assumptions.terminal_growth_rate})) / (${assumptions.wacc} - ${assumptions.terminal_growth_rate});
const tvPVExpr = (${tvExpr}) / ((1 + ${assumptions.wacc}) ^ 5);

totalPV += engine.evaluate(tvPVExpr);
return totalPV;
}

二、 實作過程中的核心困難與關鍵細節
將非確定性的 LLM 輸出對接到嚴謹的 DCF 計算引擎時,工程團隊必須特別留意以下幾點:

  1. 困難點:經濟學邏輯衝突與無效假設(Domain Invalidation)
    Gemini 1.5 的 JSON 模式能確保語法正確(Syntax Valid)並符合 Schema,但無法在生成階段保證經濟學邏輯的合理性。
    • 永續成長率大於 WACC:若 LLM 在樂觀情境給出 $g = 0.09$、$WACC = 0.08$,這會導致分母 $(WACC - g) \le 0$,使戈登成長模型算出無窮大或負值的荒謬估值。
    • 解決方案:在接收到 JSON 後、送入引擎計算前,必須加上中間驗證層(Application Guardrails)。例如強制檢驗 $WACC - g \ge 0.015$,若不滿足則觸發預設的安全修飾策略或拋出領域例外。
  2. 細節一:JSON Schema 的嚴格邊界約束
    在設定 responseSchema 時,不應僅定義欄位型別為 float,應運用 JSON Schema 的語意約束(如 minimum, maximum):
    • 設定 wacc 的範圍為 0.01 至 0.5,防止模型回傳整數如 8.5 代替 0.085 的百分比混淆。
    • 設定 revenue_growth_rates 的 minItems: 5 與 maxItems: 5,避免現金流期數不對稱導致與後續陣列運算碰撞產生越界錯誤(Out of Bounds)。
  3. 細節二:跨系統欄位版本控制與防禦性解析
    LLM 輸出的結構應被視為外部 API 合約。當模型版本更換(如從 Gemini 1.5 升級)時,Prompt 語義可能有些微變動:
    • 欄位缺漏處理:在下游解析器建立 Fallback 機制,當 bull_case 或 bear_case 部分欄位為空時,自動落入 base_case 加上一定比例增減之預設邏輯,確保計算引擎永不崩潰。
    三、 結論
    結合 Gemini 1.5 的結構化 JSON 輸出模式與模組化計算器,能打造出具備「AI 分析思考」與「精密數學算力」的自動化估值系統。然而,工程落地的重中之重在於:絕不能直接信任 LLM 輸出的數值。必須透過強型別 Schema 隔離第一層語法風險,再由業務邏輯驗證層守住領域知識的邊界,方能確保最終算出的 DCF 估值具備商業級的精確度與可信度。利用今天的實作,其實讓我對WACC跟g在三個情境模擬了解哪些的細節需要特別注意,因為只有透過實作,才能了解理論上有那些實務上不可能達到狀況,以使我所做的投資模型真的可以實用。

上一篇
在設計此程式中的驗證里程碑遇到那些挑戰及該注意的細節
下一篇
設定事件與產業代理-->事件發生時對價格影響與敏感度分析
系列文
基本面與技術面組合投資模型建置8
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言