LLM Alpha Mining: วิธีดึงสัญญาณการซื้อขายจาก Earnings Calls และเอกสารทางการเงิน
มีมุกตลกบน Wall Street ว่า: "ข้อมูลที่มีค่าที่สุดในการประชุมกำไรไม่ใช่สิ่งที่ CEO พูด แต่เป็น วิธีที่เขาพูด" เมื่อ Tim Cook กล่าวว่า "เรามองในแง่ดีอย่างระมัดระวัง" แทนที่จะเป็น "เรารู้สึกพอใจอย่างมาก" เหมือนปีที่แล้ว — นั่นไม่ใช่เกมทางภาษา แต่เป็นสัญญาณที่มีมูลค่าหลายร้อยล้านดอลลาร์
ตลอดหลายทศวรรษที่ผ่านมา กองทุน Quant พยายามสร้างระบบเพื่อดึงสัญญาณเหล่านี้ เริ่มจากการนับความถี่ของคำ "เชิงบวก" และ "เชิงลบ" โดยใช้พจนานุกรม จากนั้นก็ปล่อย BERT เข้าทำงาน และตอนนี้เรามี GPT-4o, Claude และ LLM แบบ open-source ที่สามารถวิเคราะห์ความละเอียดอ่อนของภาษาองค์กรได้อย่างแม่นยำจนแม้แต่นักวิจัยยังต้องตกใจ
มาดูกันว่าจะสร้าง pipeline ที่สมบูรณ์สำหรับการดึงสัญญาณการซื้อขายจาก earnings calls ได้อย่างไร — ตั้งแต่การได้รับ transcript จนถึงการทดสอบย้อนหลังของ cumulative abnormal returns
เหตุใด Earnings Calls จึงเป็นแหล่งทองคำสำหรับ Alpha
Post-Earnings Announcement Drift: ความผิดปกติที่ไม่ยอมหายไป
ในปี 1968 Ball และ Brown ค้นพบสิ่งแปลกประหลาด: หลังจากผลประจำไตรมาสถูกเผยแพร่ หุ้นยังคงเคลื่อนไหวในทิศทางของ "surprise" ต่ออีก 60-90 วัน พวกเขาเรียกมันว่า Post-Earnings Announcement Drift (PEAD) ผ่านมากว่าครึ่งศตวรรษ มีการเขียนบทความนับร้อยชิ้น อธิบายความผิดปกตินี้จากมุมต่างๆ กว่าสิบมุม — และมันยังคงทำงานอยู่
PEAD เป็นหนึ่งในความผิดปกติของตลาดที่ยืนหยัดได้นานที่สุดในประวัติศาสตร์การเงิน กลยุทธ์พอร์ตโฟลิโอ "ซื้อ positive surprise ขาย negative surprise" ในอดีตให้ผลตอบแทนส่วนเกินต่อปี 10-25% ทำไมตลาดถึงยังไม่ arbitrage สิ่งนี้ออกไป? มีเหตุผลหลายประการ:
- ความสนใจของนักลงทุนที่จำกัด — เมื่อ 200 บริษัทรายงานในสัปดาห์เดียวกัน เป็นไปไม่ได้ทางกายภาพที่จะอ่าน transcript ทั้งหมด
- ความซับซ้อนทางความคิด — การประชุม earnings กินเวลา 45-60 นาที และสัญญาณสำคัญอาจซ่อนอยู่ในประโยคเดียวที่นาทีที่ 38 ของส่วน Q&A
- ความคลุมเครือของภาษา — CFO บอกว่า "เราพยายามรับมือกับแรงต้าน" และถ้าไม่มีบริบทก็ไม่ชัดเจนว่านี่คือการเตือนเบาๆ หรือเพียงแค่การป้องกันตัวตามปกติ
นี่คือจุดที่ LLM เข้ามามีบทบาท เป็นครั้งแรกที่เรามีเครื่องมือที่สามารถประมวลผล transcript 500 ชิ้นในคืนเดียว พร้อมกับจับความละเอียดอ่อนที่แม้แต่นักวิเคราะห์ที่มีประสบการณ์อาจพลาดไป
PEAD.txt: ข้อความสำคัญกว่าตัวเลข
นักวิจัยจาก Federal Reserve Bank of Philadelphia (Meursault, Liang, Routledge, Scanlon) ตีพิมพ์บทความ PEAD.txt ซึ่งพลิกสมมติฐานเกี่ยวกับคุณค่าของข้อมูลเชิงข้อความ พวกเขาสร้างตัวอนาคต earnings surprise ที่อิงจากข้อความ — SUE.txt — ซึ่ง ไม่ใช้ค่า earnings ตัวเลขเลย
ผลลัพธ์? SUE.txt สร้าง drift ที่ ใหญ่กว่าสองเท่า เทียบกับ PEAD แบบคลาสสิก นอกจากนี้: ในช่วงปีหลังๆ ในขณะที่ PEAD แบบคลาสสิกที่อิงตัวเลขแทบจะหายไป (ตลาดเรียนรู้แล้ว) drift จากข้อความยังคงมีนัยสำคัญ ตลาดเรียนรู้ที่จะประมวลผลตัวเลขได้เร็ว แต่ยังดิ้นรนกับการตีความข้อความ
นี่คือข้อโต้แย้งพื้นฐานที่สนับสนุนแนวทาง NLP สำหรับ earnings calls
จาก Sentiment สู่ Semantics: วิวัฒนาการของแนวทาง

รุ่นแรก: Bag-of-Words และพจนานุกรม (2000-2015)
ทุกอย่างเริ่มต้นด้วยพจนานุกรม Loughran-McDonald (2011) — รายการคำที่ติดป้ายว่า "เชิงบวก" "เชิงลบ" "ไม่แน่นอน" และ "เกี่ยวกับคดีความ" แนวคิดนั้นหรูหราในความเรียบง่าย: นับเปอร์เซ็นต์ของคำเชิงลบในเอกสาร 10-K แล้วซื้อขายตามนั้น
ปัญหาคืออะไร? คำว่า "outstanding" ในบริบทการเงินมักหมายความว่า "หนี้ค้างชำระ" มากกว่า "ผลลัพธ์ยอดเยี่ยม" คำว่า "risk" ใน Risk Management ไม่ใช่สัญญาณเชิงลบ — มันเป็นการอธิบายกระบวนการ พจนานุกรม sentiment NLP มาตรฐานทำงานได้แย่มากบนข้อความทางการเงิน
Loughran และ McDonald สร้างพจนานุกรมเฉพาะทาง ซึ่งช่วยปรับปรุงสถานการณ์ แต่ปัญหาพื้นฐานยังคงอยู่: bag-of-words ไม่เข้าใจบริบท "We did not fail to meet expectations" — มีคำ "เชิงลบ" สองคำที่นี่ แต่ความหมายเป็นเชิงบวก
รุ่นที่สอง: FinBERT และ Transformers (2019-2023)
ในปี 2019 Dogu Araci ตีพิมพ์ FinBERT — BERT ที่ fine-tune บนข้อความทางการเงินจาก Reuters TRC2 ผลลัพธ์น่าประทับใจ: ปรับปรุง 14 เปอร์เซ็นต์พอยต์บน Financial PhraseBank dataset เมื่อเทียบกับ state-of-the-art FinBERT เข้าใจบริบท: "outstanding" ข้างๆ "debt" — เชิงลบ, ข้างๆ "performance" — เชิงบวก
แต่ FinBERT มีข้อจำกัด: หน้าต่างบริบท 512 token earnings call ยาว 8,000-12,000 คำ การแบ่งเป็นส่วนๆ และหาค่าเฉลี่ย sentiment หมายความว่าสูญเสีย semantics ระหว่างย่อหน้า CEO อาจเริ่มด้วยความมองโลกในแง่ดี แล้วพูดถึงปัญหา supply chain แบบผ่านๆ ในช่วง Q&A FinBERT วิเคราะห์แต่ละส่วนอิสระและพลาดความแตกต่างนี้
รุ่นที่สาม: LLM ที่มี Long Context (2023-ปัจจุบัน)
GPT-4, Claude, Gemini ที่มีหน้าต่างบริบท 128K-1M token เปลี่ยนกฎของเกม ตอนนี้คุณสามารถโหลด transcript ทั้งหมด ในครั้งเดียวและถามคำถามที่ต้องการเข้าใจเอกสารทั้งหมด
การศึกษาสำคัญ — Lopez-Lira & Tang (2023) "Can ChatGPT Forecast Stock Price Movements?" จาก 50,000+ พาดหัว GPT-4 แสดง hit rate ~90% ในการทำนายทิศทางปฏิกิริยาตลาดเริ่มต้นและทำนาย drift ที่ตามมาได้อย่างมีนัยสำคัญ โดยเฉพาะสำหรับ small-cap และข่าวเชิงลบ โมเดลรุ่นก่อนหน้า (GPT-1, GPT-2, BERT) ไม่แสดงความสามารถนี้ — พลังการทำนายเกิดขึ้นเป็น emergent property ของโมเดลขนาดใหญ่
BloombergGPT (2023) — โมเดลพารามิเตอร์ 50 พันล้านที่ฝึกบน financial corpus ของ Bloomberg — แสดงการปรับปรุงใน financial NER การจำแนกข่าว และการวิเคราะห์ sentiment FinGPT — ทางเลือก open-source — บรรลุความแม่นยำ 89% บนงาน financial sentiment โดยใช้แนวทาง data-centric และ RAG
MarketSenseAI ซึ่งใช้ GPT-4 ร่วมกับ Chain-of-Thought และ In-Context Learning สำหรับการวิเคราะห์ S&P 100 แสดง excess alpha 10-30% และ cumulative returns สูงถึง 72% ในการทดสอบ 15 เดือน ใช่ ตัวเลขเหล่านี้ควรรับด้วยความระมัดระวัง (backtest ≠ การซื้อขายจริง) แต่แนวโน้มชัดเจน
Data Pipeline: จะหาข้อมูลได้จากไหน
SEC EDGAR: แหล่งอย่างเป็นทางการ
สำหรับหุ้น US แหล่งหลักคือ SEC EDGAR earnings calls ไม่ได้ถูกยื่นโดยตรงโดยทั่วไป แต่เอกสารที่เกี่ยวข้องมีให้:
- 8-K filings (Item 2.02 — Results of Operations) — press releases พร้อมผลลัพธ์ มักมี exhibit 99 พร้อม transcript
- 10-Q / 10-K — รายงานรายไตรมาสและรายปีพร้อม Management Discussion & Analysis (MD&A) — เป็นแหล่งข้อความที่มีค่า
- DEF 14A — proxy statements พร้อมข้อมูลค่าตอบแทนผู้บริหาร
from edgar import Company
company = Company("AAPL")
filings = company.get_filings(form="8-K")
for filing in filings.latest(10):
if "2.02" in str(filing.items):
doc = filing.document()
text = doc.text() # ข้อความเต็มพร้อม exhibits
print(f"{filing.filing_date}: {len(text)} chars")
Seeking Alpha และ Commercial APIs
Earnings call transcripts เป็นผลิตภัณฑ์แยกต่างหาก Seeking Alpha เคยเป็นแหล่งฟรีหลัก แต่ตอนนี้จำกัดการเข้าถึง ตัวเลือกเชิงพาณิชย์:
- Seeking Alpha Premium API — full transcripts พร้อม speaker labels
- AlphaVantage Earnings API — free tier พร้อมข้อจำกัด
- Financial Modeling Prep — transcripts + fundamentals
- Earnings Call Edge / Motley Fool Transcripts — แหล่งทางเลือก
Crypto: Governance Calls และ DAO Proposals
นี่คือจุดที่น่าสนใจ โปรโตคอล DeFi รายใหญ่จัดประชุมในแบบเดียวกับ earnings calls:
- Uniswap — governance calls, community calls, การบันทึกบน YouTube
- Aave — community calls รายเดือน + governance forum proposals
- MakerDAO — governance calls + การอภิปรายในฟอรัมที่ครอบคลุม
- Compound — governance proposals พร้อมการอภิปรายโดยละเอียด
Transcript ของ crypto call มักไม่มีโครงสร้าง วิธีแก้ — Whisper ของ OpenAI สำหรับการถอดความการบันทึก YouTube:
import openai
from yt_dlp import YoutubeDL
def transcribe_governance_call(youtube_url: str) -> str:
"""ดาวน์โหลดเสียงจาก YouTube และถอดความผ่าน Whisper."""
ydl_opts = {
'format': 'bestaudio/best',
'postprocessors': [{
'key': 'FFmpegExtractAudio',
'preferredcodec': 'mp3',
'preferredquality': '64', # Bitrate ต่ำเพียงพอสำหรับเสียงพูด
}],
'outtmpl': '/tmp/governance_call.%(ext)s',
}
with YoutubeDL(ydl_opts) as ydl:
ydl.download([youtube_url])
client = openai.OpenAI()
with open("/tmp/governance_call.mp3", "rb") as audio_file:
transcript = client.audio.transcriptions.create(
model="whisper-1",
file=audio_file,
response_format="verbose_json",
timestamp_granularities=["segment"]
)
return transcript.text
ค่าใช้จ่ายในการถอดความผ่าน Whisper API: 0.36 สำหรับตัวเลือก self-hosted — Whisper Large-v3 Turbo ถอดความไฟล์ 60 นาทีใน ~17 วินาที (216x real-time) บน GPU สมัยใหม่
กลยุทธ์ LLM Prompting: จาก Naive สู่ Production-Grade

กลยุทธ์ที่ 1: Direct Sentiment (อ่อนแอ)
แนวทางที่ naive ที่สุด — ถามโมเดลตรงๆ:
"earnings call นี้เชิงบวกหรือเชิงลบต่อราคาหุ้น?"
วิธีนี้ใช้ได้ไหม? ใช่ น่าแปลก Lopez-Lira & Tang แสดงให้เห็นว่าแม้แต่ prompt ดั้งเดิมแบบนี้ก็สร้างการทำนายที่มีนัยสำคัญทางสถิติ แต่มีปัญหา:
- Output แบบ Binary — คุณสูญเสียระดับ "หายนะ" และ "ผิดหวังเล็กน้อย" ได้รับป้ายเดียวกัน
- ไม่มีคำอธิบาย — ไม่ชัดเจนว่าโมเดลอิงอะไรในการตัดสิน
- ความไม่เสถียร — การรันซ้ำอาจให้คำตอบที่แตกต่าง
กลยุทธ์ที่ 2: Structured Extraction ด้วย Chain-of-Thought (แข็งแกร่ง)
แนวคิด: แทนที่จะเป็นตัวเลขเดียว ดึงชุดสัญญาณเชิงโครงสร้าง บังคับให้โมเดลอธิบายแต่ละขั้นตอน
from pydantic import BaseModel, Field
from openai import OpenAI
from enum import Enum
from typing import Optional
class SentimentLevel(str, Enum):
VERY_BEARISH = "very_bearish"
BEARISH = "bearish"
NEUTRAL = "neutral"
BULLISH = "bullish"
VERY_BULLISH = "very_bullish"
class GuidanceSurprise(BaseModel):
"""การเบี่ยงเบนของ forward guidance จากความคาดหวัง consensus"""
revenue_guidance_vs_consensus: Optional[float] = Field(
None, description="% การเบี่ยงเบนของ revenue guidance จาก consensus"
)
margin_guidance_direction: Optional[str] = Field(
None, description="expanding / stable / contracting"
)
key_quote: str = Field(
description="คำพูดตรงๆ พร้อม guidance"
)
reasoning: str = Field(
description="CoT: ทำไม guidance นี้ถึงสำคัญ"
)
class ConfidenceMetrics(BaseModel):
"""ตัวชี้วัดความมั่นใจของผู้บริหาร"""
hedge_word_count: int = Field(
description="จำนวน hedge words: 'approximately', 'potentially', 'subject to'"
)
forward_looking_ratio: float = Field(
description="สัดส่วนของ forward-looking statements ต่อคำพูดทั้งหมด"
)
q_and_a_evasion_count: int = Field(
description="จำนวนคำถามที่ CEO/CFO ตอบแบบหลบเลี่ยง"
)
ceo_vs_cfo_sentiment_delta: float = Field(
description="ความแตกต่าง sentiment ระหว่าง CEO และ CFO (-1 ถึง 1) ความแตกต่างเป็น red flag"
)
class CompetitiveIntelligence(BaseModel):
"""การกล่าวถึงคู่แข่งและตำแหน่งทางการตลาด"""
competitors_mentioned: list[str] = Field(
description="รายชื่อคู่แข่งที่ถูกกล่าวถึง"
)
market_share_claims: list[str] = Field(
description="การอ้างสิทธิ์ส่วนแบ่งตลาด"
)
new_product_signals: list[str] = Field(
description="สัญญาณเกี่ยวกับผลิตภัณฑ์/บริการใหม่"
)
class ManagementSignals(BaseModel):
"""สัญญาณของผู้บริหาร"""
turnover_risk: SentimentLevel = Field(
description="ความเสี่ยงของการเปลี่ยนผู้บริหารสำคัญ"
)
tone_shift_from_previous: Optional[str] = Field(
None, description="โทนเปลี่ยนแปลงอย่างไรเมื่อเทียบกับไตรมาสที่แล้ว"
)
insider_language_flags: list[str] = Field(
description="วลีบ่งชี้: 'exploring strategic alternatives', 'right-sizing' ฯลฯ"
)
class EarningsCallAnalysis(BaseModel):
"""การวิเคราะห์ earnings call แบบสมบูรณ์"""
ticker: str
quarter: str
overall_sentiment: SentimentLevel
sentiment_score: float = Field(description="จาก -1.0 ถึง 1.0")
guidance_surprise: GuidanceSurprise
confidence_metrics: ConfidenceMetrics
competitive_intel: CompetitiveIntelligence
management_signals: ManagementSignals
key_risks: list[str]
key_catalysts: list[str]
one_line_summary: str
def analyze_earnings_call(transcript: str, ticker: str, quarter: str) -> EarningsCallAnalysis:
"""
ดึงสัญญาณเชิงโครงสร้างจาก earnings call
ค่าใช้จ่าย: ~$0.15-0.30 ต่อ call (GPT-4o, ~10K tokens input)
"""
client = OpenAI()
system_prompt = """You are a senior equity research analyst with 20 years of experience.
Analyze the following earnings call transcript and extract structured trading signals.
IMPORTANT INSTRUCTIONS:
1. Use Chain-of-Thought reasoning for each field — explain WHY before giving the value
2. Focus on DEVIATIONS from expectations, not absolute statements
3. Pay special attention to Q&A section — management is less scripted there
4. Compare management's language to typical corporate hedging baseline
5. Flag any "strategic alternatives", "right-sizing", or other euphemisms
6. Score sentiment relative to market expectations, not in absolute terms
HEDGE WORDS TO COUNT: approximately, potentially, subject to, may, might,
could, uncertain, challenging, headwinds, navigate, prudent, cautious,
evolving, dynamic, unprecedented, transitional"""
completion = client.beta.chat.completions.parse(
model="gpt-4o",
messages=[
{"role": "system", "content": system_prompt},
{"role": "user", "content": f"Ticker: {ticker}\nQuarter: {quarter}\n\n{transcript}"}
],
response_format=EarningsCallAnalysis,
temperature=0.1, # Temperature ต่ำเพื่อความสามารถในการทำซ้ำ
)
return completion.choices[0].message.parsed
สังเกตจุดสำคัญหลายประการ:
Pydantic schema — OpenAI Structured Outputs รับประกัน schema compliance 100% ไม่มีอีกแล้ว "sorry, I cannot parse the JSON" แต่ละฟิลด์มีคำอธิบายที่ทำหน้าที่เป็น mini-prompt สำหรับแง่มุมเฉพาะของการวิเคราะห์
Chain-of-Thought ภายใน schema — ฟิลด์ reasoning และ key_quote บังคับให้โมเดล "แสดงการทำงาน" ของมัน วิธีนี้ไม่เพียงแต่ปรับปรุงคุณภาพ (โมเดลถูกบังคับให้หาคำพูดเฉพาะก่อนตัดสิน) แต่ยังสร้าง audit trail สำหรับผู้กำกับดูแล
Temperature 0.1 — เราไม่ต้องการความคิดสร้างสรรค์ เราต้องการความสามารถในการทำซ้ำ ที่ temperature 0 โมเดลบางครั้ง "ติด" ในรูปแบบ 0.1 คือการประนีประนอมที่เหมาะสม
กลยุทธ์ที่ 3: Few-Shot พร้อมตัวอย่างประวัติศาสตร์
ทรงพลังยิ่งขึ้น — ให้ตัวอย่างของ earnings calls ในอดีตพร้อมปฏิกิริยาตลาดจริงแก่โมเดล:
few_shot_examples = """
EXAMPLE 1:
Transcript excerpt: "We are cautiously optimistic about the second half...
While we continue to navigate macro headwinds, our pipeline remains robust."
Actual market reaction: -3.2% (next day)
Analysis: Despite surface-level positivity, "cautiously optimistic" is a
DOWNGRADE from previous quarter's "very confident". Five hedge words in
two sentences. Market read through the hedging.
EXAMPLE 2:
Transcript excerpt: "Frankly, demand has exceeded our ability to supply.
We're expediting CapEx to address this."
Actual market reaction: +7.8% (next day)
Analysis: "Frankly" signals genuine surprise even from management.
Accelerated CapEx on demand = strong confidence. No hedging language.
"""
ตัวอย่าง Few-shot ช่วยให้โมเดลปรับเทียบ: มันเรียนรู้ว่า "cautiously optimistic" ในภาษา Wall Street ไม่ใช่เชิงบวก — มันคือเชิงลบอ่อนๆ โดยไม่มีตัวอย่าง LLM อาจตีความคำตามตัวอักษร
สัญญาณสี่ประเภท
1. Guidance Surprise
สัญญาณตรงที่สุด บริษัทให้การคาดการณ์ (guidance) สำหรับไตรมาส/ปีถัดไป และตลาดตอบสนองต่อการเบี่ยงเบนจาก consensus LLM สามารถดึง guidance แม้เมื่อผู้บริหารสื่อสารอย่างคลุมเครือ:
- "We expect revenues in the range of..." — guidance ตรงๆ แยกวิเคราะห์ได้ง่าย
- "We feel comfortable with current Street estimates" — การยืนยัน consensus แบบนัย
- "There are puts and takes relative to consensus" — สัญญาณความเสี่ยงแบบนัย
LLM เข้าใจทั้งสามรูปแบบ regex เข้าใจเฉพาะแบบแรก
2. Confidence Metrics: ความหนาแน่นของ Hedge Words
นี่คือสัญญาณที่ฉันชอบที่สุดเพราะมันต้านสัญชาตญาณ แก่นแท้: ผู้จัดการคือคนที่ผ่านการฝึกกฎหมายและมีฝ่ายกฎหมายที่หวาดระแวง เมื่อสิ่งต่างๆ ดีขึ้น พวกเขาจะเฉพาะเจาะจง เมื่อปัญหาก่อตัว — พวกเขาเริ่ม hedge
ตัวชี้วัดที่ต้องติดตาม:
| ตัวชี้วัด | คำอธิบาย | สัญญาณ Bearish |
|---|---|---|
| ความหนาแน่น hedge word | สัดส่วน hedge words ต่อ 1,000 คำ | > 15 ต่อ 1,000 คำ |
| Certainty ratio | สัดส่วน "will/expect" vs "may/could" | < 1.5 |
| Q&A evasion rate | % ของคำถามที่ไม่ได้รับคำตอบตรงๆ | > 30% |
| CEO/CFO delta | ความแตกต่างโทนระหว่าง CEO และ CFO | > 0.3 บนสเกล [-1, 1] |
จุดสุดท้ายน่าสนใจเป็นพิเศษ CEO เป็นนักเล่าเรื่อง — งานของเขาคือวาดภาพที่สวยงาม CFO คือผู้รับผิดชอบต่อผู้ตรวจสอบ เมื่อ CEO บอกว่า "transformative growth ahead" และ CFO ขัดขึ้นมาทันที "while maintaining disciplined cost management" — ความแตกต่างนี้บ่งชี้ถึงความตึงเครียดภายใน
3. Competitive Intelligence
LLM สามารถดึงการกล่าวถึงคู่แข่งจาก transcript แม้เมื่อผู้บริหารหลีกเลี่ยงชื่อโดยตรง "the largest player in the market" — นั่นไม่ใช่ปริศนาสำหรับ GPT-4 ถ้ามันรู้อุตสาหกรรม
สัญญาณการซื้อขาย: ถ้าบริษัท A กล่าวถึงคู่แข่ง B ในบริบทเชิงลบในระหว่าง earnings call ("we're taking share from...") นั่นคือสัญญาณไม่เพียงแต่สำหรับ A (long) แต่ยังสำหรับ B (short) เป็น pairs trade
4. Management Turnover Signals
วลีบ่งชี้สำหรับการเปลี่ยนผู้บริหารหรือ strategic pivots:
- "Exploring strategic alternatives" — น่าจะขายบริษัท
- "Right-sizing our operations" — ปลดพนักงานจำนวนมาก
- "The board has initiated a comprehensive review" — CEO จะออกในไม่ช้า
- "We're bringing in fresh perspectives" — ทีมปัจจุบันล้มเหลว
แต่ละวลีเหล่านี้มีความสัมพันธ์ที่มีนัยสำคัญทางสถิติกับพลวัตราคาที่ตามมา LLM สามารถตรวจจับได้ด้วย false positives เป็นศูนย์ — เพราะมันเข้าใจบริบท ไม่เหมือน regex ที่อาจจับ "strategic alternatives" ในคำอธิบายสายผลิตภัณฑ์
Backtesting: Event Study Methodology

เรากำลังสร้างสัญญาณ — ดีมาก แต่มันทำงานได้ไหม? วิธีการยืนยันมาตรฐานคือ Event Study พร้อมการคำนวณ Cumulative Abnormal Returns (CAR)
Methodology
- กำหนด event — วันที่ earnings call
- Estimation window — [-250, -30] วันซื้อขายก่อน event เพื่อประเมินผลตอบแทน "ปกติ"
- Event window — [-1, +60] วันรอบ event
- คำนวณผลตอบแทนปกติ ผ่าน market model:
- Abnormal return — ความแตกต่างระหว่างผลตอบแทนจริงและ "ปกติ"
- CAR — ผลรวมสะสมของ abnormal returns ตลอด event window
import numpy as np
import pandas as pd
from scipy import stats
from dataclasses import dataclass
@dataclass
class EventStudyResult:
car: np.ndarray # Cumulative abnormal returns รายวัน
t_stats: np.ndarray # t-statistics สำหรับแต่ละวัน
avg_car_3d: float # CAR[-1, +1]
avg_car_30d: float # CAR[-1, +30]
avg_car_60d: float # CAR[-1, +60]
p_value_3d: float
p_value_30d: float
n_events: int
def run_event_study(
returns: pd.DataFrame, # ผลตอบแทนหุ้นรายวัน (columns = tickers)
market_returns: pd.Series, # ผลตอบแทน market index รายวัน
events: pd.DataFrame, # DataFrame พร้อม columns: [ticker, date, signal_score]
estimation_window: int = 220,
gap: int = 30,
event_window: tuple = (-1, 60),
) -> EventStudyResult:
"""
Event study เพื่อประเมินพลังการทำนายของสัญญาณ LLM
เรียงลำดับ events ตาม signal_score สร้างพอร์ตโฟลิโอ long/short
คำนวณ CAR และทดสอบนัยสำคัญทางสถิติ
"""
all_cars = []
for _, event in events.iterrows():
ticker = event['ticker']
event_date = event['date']
if ticker not in returns.columns:
continue
try:
event_idx = returns.index.get_loc(event_date, method='ffill')
except KeyError:
continue
est_start = event_idx - estimation_window - gap
est_end = event_idx - gap
if est_start < 0:
continue
y = returns.iloc[est_start:est_end][ticker].values
x = market_returns.iloc[est_start:est_end].values
mask = ~(np.isnan(y) | np.isnan(x))
if mask.sum() < 60: # ขั้นต่ำ 60 observations
continue
y_clean, x_clean = y[mask], x[mask]
slope, intercept, _, _, _ = stats.linregress(x_clean, y_clean)
residual_std = np.std(y_clean - (intercept + slope * x_clean))
ev_start = event_idx + event_window[0]
ev_end = event_idx + event_window[1] + 1
if ev_end > len(returns):
continue
actual = returns.iloc[ev_start:ev_end][ticker].values
market = market_returns.iloc[ev_start:ev_end].values
expected = intercept + slope * market
ar = actual - expected
car = np.cumsum(ar)
all_cars.append(car)
if not all_cars:
raise ValueError("No valid events found")
min_len = min(len(c) for c in all_cars)
all_cars = np.array([c[:min_len] for c in all_cars])
mean_car = np.mean(all_cars, axis=0)
std_car = np.std(all_cars, axis=0) / np.sqrt(len(all_cars))
t_stats = mean_car / (std_car + 1e-10)
offset = -event_window[0] # เลื่อนไปที่วัน event
car_3d = mean_car[min(offset + 1, min_len - 1)] if min_len > offset + 1 else mean_car[-1]
car_30d = mean_car[min(offset + 30, min_len - 1)] if min_len > offset + 30 else mean_car[-1]
car_60d = mean_car[min(offset + 60, min_len - 1)] if min_len > offset + 60 else mean_car[-1]
n = len(all_cars)
p_3d = 2 * (1 - stats.t.cdf(abs(car_3d / (np.std([c[min(offset+1, min_len-1)] for c in all_cars]) / np.sqrt(n) + 1e-10)), df=n-1))
p_30d = 2 * (1 - stats.t.cdf(abs(car_30d / (np.std([c[min(offset+30, min_len-1)] for c in all_cars]) / np.sqrt(n) + 1e-10)), df=n-1))
return EventStudyResult(
car=mean_car,
t_stats=t_stats,
avg_car_3d=car_3d,
avg_car_30d=car_30d,
avg_car_60d=car_60d,
p_value_3d=p_3d,
p_value_30d=p_30d,
n_events=n,
)
def backtest_llm_signals(
llm_signals: pd.DataFrame, # [ticker, date, sentiment_score]
returns: pd.DataFrame,
market_returns: pd.Series,
):
"""Backtest: long สัญญาณ quintile บน, short สัญญาณ quintile ล่าง"""
llm_signals['quintile'] = pd.qcut(
llm_signals['sentiment_score'], 5, labels=[1, 2, 3, 4, 5]
)
long_events = llm_signals[llm_signals['quintile'] == 5].copy()
short_events = llm_signals[llm_signals['quintile'] == 1].copy()
long_result = run_event_study(returns, market_returns, long_events)
short_result = run_event_study(returns, market_returns, short_events)
print(f"พอร์ตโฟลิโอ LONG (LLM sentiment quintile บน):")
print(f" CAR[0,+3]: {long_result.avg_car_3d:+.2%} (p={long_result.p_value_3d:.4f})")
print(f" CAR[0,+30]: {long_result.avg_car_30d:+.2%} (p={long_result.p_value_30d:.4f})")
print(f" N events: {long_result.n_events}")
print(f"\nพอร์ตโฟลิโอ SHORT (LLM sentiment quintile ล่าง):")
print(f" CAR[0,+3]: {short_result.avg_car_3d:+.2%} (p={short_result.p_value_3d:.4f})")
print(f" CAR[0,+30]: {short_result.avg_car_30d:+.2%} (p={short_result.p_value_30d:.4f})")
print(f" N events: {short_result.n_events}")
ls_3d = long_result.avg_car_3d - short_result.avg_car_3d
ls_30d = long_result.avg_car_30d - short_result.avg_car_30d
print(f"\nLONG-SHORT spread:")
print(f" CAR[0,+3]: {ls_3d:+.2%}")
print(f" CAR[0,+30]: {ls_30d:+.2%}")
สิ่งที่เราคาดหวังจะเห็น
อิงจากการวิจัยที่มีอยู่ CAR ที่สมจริงสำหรับสัญญาณ LLM:
| Window | พอร์ตโฟลิโอ Long | พอร์ตโฟลิโอ Short | L/S spread |
|---|---|---|---|
| [0, +1] | +0.8% — +1.5% | -0.5% — -1.2% | 1.3% — 2.7% |
| [0, +30] | +1.5% — +3.0% | -1.0% — -2.5% | 2.5% — 5.5% |
| [0, +60] | +2.0% — +4.0% | -1.5% — -3.5% | 3.5% — 7.5% |
ตัวบ่งชี้หลักคือนัยสำคัญทางสถิติ ด้วย p < 0.01 และ N > 200 events คุณสามารถพูดถึงสัญญาณที่แข็งแกร่ง ด้วย p > 0.05 — อาจเป็นเสียงรบกวน
การนำไปใช้ใน Production: จาก Jupyter สู่ Prod
สถาปัตยกรรม Real-time Pipeline
YouTube/Audio Stream
│
▼
┌─────────────────┐ ┌──────────────────┐
│ Whisper │───▶│ Transcript │
│ Transcription │ │ Buffer │
│ (streaming) │ │ (Redis Stream) │
└─────────────────┘ └──────────────────┘
│
┌─────────┴─────────┐
▼ ▼
┌──────────────┐ ┌──────────────┐
│ Real-time │ │ Full-call │
│ Chunk Anal. │ │ Analysis │
│ (every 5min) │ │ (after call │
│ │ │ ends) │
└──────────────┘ └──────────────┘
│ │
▼ ▼
┌──────────────────────────────┐
│ Signal Aggregator │
│ (confidence-weighted merge) │
└──────────────────────────────┘
│
▼
┌──────────────────────────────┐
│ Trading Engine │
│ (position sizing, risk mgmt)│
└──────────────────────────────┘
การวิเคราะห์ค่าใช้จ่าย: Earnings Call หนึ่งครั้งมีราคาเท่าไร
มาแจกแจงเศรษฐศาสตร์ของการประมวลผล earnings call หนึ่งครั้งใน production:
| ส่วนประกอบ | ค่าใช้จ่าย | Latency |
|---|---|---|
| Whisper API transcription (60 นาที) | $0.36 | ~17 วินาที (Turbo) |
| GPT-4o structured extraction | $0.15-0.30 | ~8-15 วินาที |
| GPT-4o real-time chunk analysis (x12) | $1.80-3.60 | ~5 วินาทีต่อชิ้น |
| Embedding สำหรับ RAG storage | $0.01 | <1 วินาที |
| รวม (full pipeline) | $2.30-4.30 | ~30 วินาทีแบบเต็ม |
รอ การประมาณการคือ $30-50 ต่อ call ตัวเลขเหล่านั้นมาจากไหน? ขึ้นอยู่กับโมเดลและแนวทาง:
- ตัวเลือก Budget (GPT-4o-mini, single pass): $0.50-1.00
- ตัวเลือก Standard (GPT-4o, structured extraction + chunk analysis): $2-5
- ตัวเลือก Premium (GPT-4o, multiple passes, cross-validation, historical comparison): $15-30
- ระดับ Hedge-fund (multiple models + human review + real-time streaming): $30-50+
สำหรับ quant fund ที่ซื้อขาย 500 tickers ค่าใช้จ่ายในการประมวลผล earnings season (~2,000 calls ใน 6 สัปดาห์) คือ 10,000 ด้วยตัวเลือก standard เมื่อพิจารณา alpha เฉลี่ยต่อตำแหน่ง 1-3% — ROI นั้นมหาศาล
Latency: การแข่งขันเพื่อมิลลิวินาที
ในโลกของ HFT latency คือทุกสิ่ง แต่สำหรับกลยุทธ์ที่อิง earnings สถานการณ์แตกต่างออกไป:
- Earnings call กินเวลา 45-60 นาที — คุณมีเวลา
- PEAD ยืดออกไป 60 วัน — ไม่จำเป็นต้องเข้าในวินาทีแรก
- การเคลื่อนไหวหลักของตลาด เกิดขึ้นใน 30 นาทีแรกหลัง call จบ
กลยุทธ์ที่เหมาะสมคือ สองระยะ:
- ระยะที่ 1 (real-time): วิเคราะห์ส่วนย่อย 5 นาทีระหว่าง call สร้างสัญญาณเบื้องต้น
- ระยะที่ 2 (post-call): การวิเคราะห์เต็มรูปแบบของ transcript ทั้งหมด 2-5 นาทีหลังจากจบ
ระยะที่ 1 ให้ edge 5-10 นาทีเหนือผู้เข้าร่วมตลาดที่รอให้ call จบ สำหรับ mid-cap stocks เพียงพอแล้ว
ขยายสู่ Crypto: DeFi Governance และ DAO Proposals
ตลาด crypto เป็นสนามทดสอบในอุดมคติสำหรับ LLM alpha mining นี่คือเหตุผล:
- ผู้เล่นสถาบันน้อยกว่า — หมายความว่ามีความไม่มีประสิทธิภาพมากขึ้นที่จะใช้ประโยชน์
- Governance = earnings call — การตัดสินใจของ DAO ส่งผลโดยตรงต่อ tokenomics
- ตลาด 24/7 — คุณสามารถซื้อขายปฏิกิริยาได้ทันที
- ข้อมูลสาธารณะ — proposal และการโหวตทั้งหมดอยู่บน on-chain
ประเภท Crypto Events สำหรับการวิเคราะห์
Governance Proposals (Aave, Compound, Uniswap)
Proposal เปลี่ยนพารามิเตอร์ protocol — อัตราดอกเบี้ย, collateral factors, fee switches LLM สามารถประเมินผลกระทบทางเศรษฐกิจ:
crypto_analysis_prompt = """Analyze this DeFi governance proposal.
Extract:
1. Economic impact on token holders (positive/negative/neutral)
2. TVL impact estimate (increase/decrease/stable + magnitude)
3. Competitive positioning vs other protocols
4. Risk factors introduced by the proposal
5. Historical precedent (similar proposals in other protocols)
6. Likely voting outcome based on forum discussion sentiment
Proposal: {proposal_text}
Forum discussion: {discussion_text}
"""
Protocol Update Announcements
เมื่อ Uniswap ประกาศ v4 พร้อม hooks หรือ Aave เปิดตัว GHO — นั่นคือเทียบเท่ากับการเปิดตัวผลิตภัณฑ์ใน TradFi LLM สามารถประเมิน narrative momentum และความสำคัญทางเทคนิค
Treasury Reports
DAO ขนาดใหญ่มี treasury มูลค่าหลายร้อยล้าน รายงาน treasury รายไตรมาสเป็นตัวเลือกตรงของ earnings ระยะเวลาดำเนินงาน, อัตราการใช้จ่าย, การกระจายความเสี่ยง — ทั้งหมดรองรับการวิเคราะห์ด้วย LLM
ความเฉพาะของสัญญาณ Crypto
ต่างจาก TradFi ใน crypto:
- ข้อมูล on-chain ยืนยันหรือโต้แย้ง narrative — คุณสามารถ cross-reference สิ่งที่พูดในการประชุม governance กับ protocol metrics จริง (TVL, volume, active users)
- Whale wallets เป็น insider trading — การเคลื่อนไหวของ wallet ขนาดใหญ่หลังการอภิปราย governance มักนำหน้าการโหวต
- การขยาย sentiment ผ่าน CT (Crypto Twitter) — สัญญาณจาก governance call อาจถูกขยายหรือกดลงด้วย Twitter narratives
กับดักและข้อจำกัด
Hallucinations: เมื่อโมเดลประดิษฐ์ตัวเลข
LLM สามารถ "ดึง" guidance ที่ไม่ได้อยู่ใน transcript ซึ่งเป็นอันตรายโดยเฉพาะเมื่อวิเคราะห์ความหนาแน่นของ hedge words: โมเดลอาจนับคำมากหรือน้อยกว่าที่มีอยู่จริง
วิธีแก้ไข: การตรวจสอบสองระยะ LLM ดึง โค้ดแบบ deterministic ตรวจสอบ สำหรับ hedge words — regex counting ควบคู่กับการประเมิน LLM ความเบี่ยงเบน > 20% — ส่งไป manual review
import re
HEDGE_WORDS = [
r'\bapproximately\b', r'\bpotentially\b', r'\bsubject to\b',
r'\bmay\b', r'\bmight\b', r'\bcould\b', r'\buncertain\b',
r'\bchallenging\b', r'\bheadwinds\b', r'\bnavigate\b',
r'\bprudent\b', r'\bcautious\b', r'\bevolving\b',
r'\bdynamic\b', r'\bunprecedented\b', r'\btransitional\b',
]
def verify_hedge_count(text: str, llm_count: int) -> dict:
"""การตรวจสอบแบบ deterministic ของจำนวน hedge words จาก LLM"""
regex_count = sum(
len(re.findall(pattern, text, re.IGNORECASE))
for pattern in HEDGE_WORDS
)
deviation = abs(llm_count - regex_count) / (regex_count + 1)
return {
"llm_count": llm_count,
"regex_count": regex_count,
"deviation": deviation,
"needs_review": deviation > 0.2,
}
ข้อจำกัด Context Window
แม้แต่ 128K tokens อาจไม่เพียงพอถ้าคุณต้องการใส่:
- Transcript ปัจจุบัน (~10K tokens)
- Transcript ก่อนหน้าสำหรับการเปรียบเทียบ (~10K)
- การคาดการณ์ analyst consensus (~2K)
- ตัวอย่าง few-shot (~3K)
- System prompt (~1K)
รวม ~26K — เราพอดี แต่ถ้าคุณเพิ่มเอกสาร 10-K (~80-120K tokens) สำหรับบริบท — คุณอยู่ที่ขอบแล้ว วิธีแก้: RAG สำหรับดึงส่วนที่เกี่ยวข้องจากเอกสารยาว
Bias และข้อผิดพลาดเชิงระบบ
LLM ถูกฝึกบนข้อมูลประวัติศาสตร์ที่วลีบางอย่างเกี่ยวข้องกับผลลัพธ์บางอย่าง แต่ตลาดปรับตัว:
- ถ้าทุกคนเริ่มนับ hedge words ด้วย GPT-4 ผู้จัดการจะเปลี่ยนภาษาของตัวเอง
- โมเดลอาจให้น้ำหนักมากเกินไปกับนัยสำคัญของรูปแบบจากข้อมูลฝึก (survivorship bias)
- ภาษาองค์กรมีวิวัฒนาการ: "synergies" ในปี 2010 หมายความว่าอย่างหนึ่ง ในปี 2026 — หมายความว่าอีกอย่างหนึ่ง
ความเสี่ยงของ Crowded Trade
ถ้า quant fund 50 แห่งใช้ GPT-4 เดียวกันเพื่อวิเคราะห์ transcript เดียวกัน — สัญญาณจะเสื่อมค่า เปรียบเสมือน: เมื่อทุกคนเริ่มซื้อขาย PEAD บน numerical surprises ความผิดปกติก็ลดลง เหมือนกันจะเกิดกับสัญญาณข้อความ แต่ล่าช้ากว่า:
- ตอนนี้ (2026) — มีน้อยรายที่ใช้ LLM อย่างเป็นระบบสำหรับ earnings calls Alpha มีนัยสำคัญ
- ใน 2-3 ปี — การนำไปใช้อย่างแพร่หลาย alpha ลดลง
- ใน 5 ปี — สัญญาณ LLM พื้นฐานกลายเป็น commodity edge ยังคงอยู่เฉพาะในโมเดลที่กำหนดเองและข้อมูลเฉพาะ
นี่คือวงจรชีวิตมาตรฐานของสัญญาณ alpha ชื่นชมมันในขณะที่ยังมีอยู่
แทนที่จะสรุป: แผนปฏิบัติการ
ถ้าคุณต้องการเริ่มใช้ LLM สำหรับการวิเคราะห์ earnings call นี่คือแผน minimum viable:
- เริ่มด้วยข้อมูลฟรี — SEC EDGAR + EdgarTools สำหรับ 8-K/10-Q filings
- ใช้ structured extraction — Pydantic schemas ผ่าน OpenAI Structured Outputs
- Backtest ผ่าน event study — CAR บนข้อมูลประวัติศาสตร์ ขั้นต่ำ 200 events
- เพิ่มตัวอย่าง few-shot — ตัวอย่างที่มี label 5-10 ชิ้นช่วยปรับปรุงคุณภาพอย่างรุนแรง
- ตรวจสอบแบบ deterministic — LLM ดึง regex ตรวจสอบ มนุษย์ตรวจสอบ
- เริ่มด้วย mid-cap — alpha มากขึ้น การแข่งขันน้อยลงกับ major funds
- ขยายสู่ crypto — governance calls และ DAO proposals เป็นดินแดนที่ยังไม่มีใครสำรวจ
จำกฎสำคัญของการวิเคราะห์เชิงปริมาณ: ถ้าสัญญาณฟังดูดีเกินไปที่จะเป็นจริง — ตรวจสอบอีกครั้ง LLM สร้างภาพลวงตาของความเข้าใจ แต่เบื้องหลังมันคือการจับคู่รูปแบบทางสถิติ เครื่องมือที่ทรงพลัง — แต่เป็นเครื่องมือ ไม่ใช่ oracle
บรรณานุกรม
-
Ball, R., Brown, P. (1968). An Empirical Evaluation of Accounting Income Numbers. Journal of Accounting Research, 6(2), 159-178. — การค้นพบ PEAD ครั้งแรก
-
Bernard, V.L., Thomas, J.K. (1989). Post-Earnings-Announcement Drift: Delayed Price Response or Risk Premium? Journal of Accounting Research, 27, 1-36. — บทความ PEAD แบบ canonical
-
Loughran, T., McDonald, B. (2011). When Is a Liability Not a Liability? Textual Analysis, Dictionaries, and 10-Ks. Journal of Finance, 66(1), 35-65. — พจนานุกรม financial sentiment
-
Araci, D. (2019). FinBERT: Financial Sentiment Analysis with Pre-trained Language Models. arXiv:1908.10063. — BERT สำหรับ financial NLP, +14pp เหนือ SOTA
-
Wu, S. et al. (2023). BloombergGPT: A Large Language Model for Finance. arXiv:2303.17564. — โมเดล 50B-parameter ของ Bloomberg
-
Yang, H. et al. (2023). FinGPT: Open-Source Financial Large Language Models. arXiv:2306.06031. — ทางเลือก open-source สำหรับ BloombergGPT ความแม่นยำ 89%
-
Lopez-Lira, A., Tang, Y. (2023). Can ChatGPT Forecast Stock Price Movements? Return Predictability and Large Language Models. arXiv:2304.07619. — GPT-4 ทำนายผลตอบแทนด้วย hit rate ~90%
-
Meursault, V., Liang, P.J., Routledge, B., Scanlon, M.M. (2023). PEAD.txt: Post-Earnings-Announcement Drift Using Text. Journal of Financial and Quantitative Analysis. — PEAD แบบข้อความใหญ่กว่า PEAD แบบตัวเลขสองเท่า
-
Fatouros, G. et al. (2024). Can Large Language Models Beat Wall Street? Evaluating GPT-4's Impact on Financial Decision-Making with MarketSenseAI. Neural Computing and Applications. — กรอบงาน GPT-4 พร้อม excess alpha 10-30% บน S&P 100
-
Chen, Y. et al. (2025). GPT-Signal: Generative AI for Semi-automated Feature Engineering in the Alpha Research Process. arXiv:2410.18448. — การสร้างสัญญาณการซื้อขายอัตโนมัติผ่าน LLM
-
Zhang, X. et al. (2025). Can LLMs Hit Moving Targets? Tracking Evolving Signals in Corporate Disclosures. arXiv:2510.03195. — การตรวจจับ "moving targets" ใน corporate disclosures
-
Chen, Z. et al. (2025). Large Language Models in Equity Markets: Applications, Techniques, and Insights. Frontiers in Artificial Intelligence. — Survey ของการศึกษา LLM 84 ชิ้นในการเงิน
บทความนี้มีจุดประสงค์เพื่อการศึกษาและไม่ถือเป็นคำแนะนำในการลงทุน กลยุทธ์การซื้อขายใดๆ ที่อธิบายไว้ในที่นี้ต้องผ่านการทดสอบย้อนหลังอย่างละเอียดและการบริหารความเสี่ยงก่อนนำไปใช้กับทุนจริง
ผู้เขียน
Trading-systems engineer
Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.