[ blog · use-case ]9 min read

Xây dựng tác nhân thẩm định (due diligence) trên hồ sơ SEC (10-K, 10-Q, 8-K, báo cáo lợi nhuận)

Sarah ChoyĐăng ngày 3 tháng 5, 20269 phút đọc
Xây dựng tác nhân thẩm định (due diligence) trên hồ sơ SEC (10-K, 10-Q, 8-K, báo cáo lợi nhuận)

Đọc một bản 10-K phần lớn là Ctrl+F. Làm điều đó cho năm mươi công ty là cả một công việc. Hãy thay 80% nhàm chán bằng một tác nhân search-and-extract chạy trên SEC EDGAR — và giữ lại 20% thực sự quan trọng cho nhà phân tích con người.

Tóm tắt

  • Kiến trúc: tra cứu ticker → SEC Filings Search (hồ sơ + báo cáo lợi nhuận + thống kê equity) → URL Extract cho các đoạn dài → câu trả lời của LLM với trích dẫn ở cấp mục.
  • Trần chi phí: SEC Filings Search tốn 120 credits mỗi lần gọi (≈0,12$); một lượt rà soát công ty 3 câu hỏi điển hình tốn ~0,40$ credits + ~0,05$ token LLM.
  • Những gì tác nhân làm đúng: tra cứu dữ kiện (doanh thu theo phân khúc, xu hướng capex, quản trị, thay đổi yếu tố rủi ro theo từng năm), tóm tắt thù lao điều hành, các sự kiện 8-K gần đây.
  • Những gì vẫn cần con người: các phán đoán về chất lượng ban lãnh đạo, định vị thị trường, các vấn đề đặc thù của thương vụ, bất kỳ điều gì nằm ngoài ngôn ngữ của hồ sơ.

Vì sao việc này đáng để tự động hóa

Một lượt đọc thẩm định ban đầu về một công ty đại chúng phần lớn mang tính máy móc: kéo bản 10-K mới nhất, quét các yếu tố rủi ro và phần MD&A, kiểm tra các 8-K gần đây, liếc qua buổi công bố lợi nhuận mới nhất. Một nhà phân tích cấp associate mất 2–4 giờ cho việc này mỗi công ty. Đầu ra hiếm khi là một hiểu biết sâu sắc — đó là một mẫu hình dữ kiện có cấu trúc mà sau đó một người khác, kỳ cựu hơn, sẽ suy luận trên đó.

Bước tạo mẫu-hình-dữ-kiện đó chính xác là thứ mà một tác nhân nhỏ có thể tiếp quản. Tìm trong SEC, trích xuất các đoạn liên quan, tóm tắt kèm trích dẫn. Người kỳ cựu vẫn làm phần suy luận — nhưng họ bắt đầu từ một lượt đọc 5 phút thay vì 4 giờ.

Ba điều khiến việc này trở nên khả thi vào lúc này:

  • Tìm kiếm ngữ nghĩa trên hồ sơ nghĩa là bạn có thể hỏi 'doanh thu theo phân khúc đã thay đổi thế nào' và nhận lại đúng đoạn văn từ đúng biểu mẫu, thay vì đọc 200 trang.
  • Các LLM ngữ cảnh dài có thể giữ trọn một bản 10-K cùng vài bản 8-K trong bộ nhớ làm việc và trả lời các câu hỏi xuyên tài liệu.
  • Kỷ luật trích dẫn trong prompt khiến đầu ra có thể kiểm chứng trong vài giây — đúng thứ mà các quy trình compliance và rà soát đòi hỏi.

Kiến trúc

question + ticker
       ├─ /api/company/facts (2 credits)
       │  ↳ confirm ticker, get CIK and sector
       ├─ /api/search/sec (120 credits)
       │  ↳ semantic search across 10-K/10-Q/8-K/earnings/equity stats
       ├─ /api/extract (2 credits per URL)
       │  ↳ pull full text of the top 3-5 most relevant filings
       └─ Claude / GPT-4 with citation-required prompt
          ↳ "answer + [Form, Fiscal Period, Section]"

Chi phí cho một câu hỏi đơn lẻ: ~130 credits (~0,13$) API + ~0,03$ LLM. Một lượt rà soát công ty ba câu hỏi (xu hướng tài chính, diff yếu tố rủi ro, sự kiện trọng yếu gần đây) rơi vào ~0,45–0,60$. So với một giờ làm việc của nhà phân tích ở bất kỳ mức phí hợp lý nào, phép tính đã quá rõ ràng.

System prompt đáng đồng tiền bát gạo

Yếu tố quyết định lớn nhất đến chất lượng đầu ra trong RAG tài chính chính là system prompt. Cái mà chúng tôi dùng:

You are a financial research assistant for an investment team. You answer
questions about US public companies using SEC filings, earnings call
transcripts, and equity statistics retrieved by your tools.

Rules — non-negotiable:

1. Cite every numeric claim with: [Form, Fiscal Period, Section]. Example:
   "Operating income rose 12% YoY to $4.1B [10-K FY2025, Item 7 MD&A]."

2. Quote numbers verbatim. Do not round, paraphrase, or convert. If a
   filing says "$4,127M", do not say "$4.1B" unless the filing itself does.

3. If the answer requires content you have not extracted, say so:
   "I could not retrieve the FY2024 10-K for the segment-level breakdown.
   Please re-run with that filing in scope."

4. Do not infer from training-data knowledge. If your tools didn't return
   it, you don't know it.

5. Default to the most recent fiscal period available. State the period
   you used.

6. Format multi-figure answers as a small markdown table with one column
   per fiscal period. Always end with a one-line "How I read this" summary.

Tone: precise, terse, no marketing language.

Quy tắc 1, 2 và 4 gộp lại loại bỏ ~90% các vấn đề bịa đặt mà chúng tôi đã đo được. Quy tắc 3 (lời "tôi không biết" một cách lịch thiệp) là thứ phân biệt cái này với một chatbot tự tin bịa ra các con số.

Các query mẫu mà tác nhân xử lý gọn gàng

  • 'So sánh xu hướng doanh thu dịch vụ của Apple trong 5 năm tài chính gần nhất.' → kéo từ các bản 10-K liên quan, trả về một bảng kèm trích dẫn đến MD&A.
  • 'Các yếu tố rủi ro của NVIDIA đã thay đổi gì giữa FY2023 và FY2025?' → diff xuyên tài liệu, trích dẫn Item 1A trong từng biểu mẫu.
  • 'Tóm tắt 4 bản 8-K gần nhất của $TICKER.' → tìm kiếm ngữ nghĩa lọc theo 8-K, sắp xếp theo ngày nộp hồ sơ.
  • 'CFO của Microsoft đã nói gì về capex cho AI trong buổi công bố lợi nhuận gần nhất?' → tìm trong các bản ghi, trích xuất đoạn Q&A liên quan, trích nguyên văn.

Nơi nó hụt hơi — và sự bàn giao đúng cho con người

Tác nhân vấp ở ba chỗ có thể đoán trước:

  • Phán đoán về chất lượng ban lãnh đạo. Hồ sơ cho bạn biết họ đã làm gì, chứ không phải họ có năng lực hay không. Đừng hỏi tác nhân.
  • So sánh ngành ngoài phạm vi hồ sơ. Nếu câu hỏi là 'biên lợi nhuận gộp này so với các đối thủ thế nào', tác nhân chỉ biết những gì có trong các hồ sơ đã tìm. Để so sánh với đối thủ, bạn cần một dataset riêng hoặc chạy tác nhân một lần cho mỗi công ty rồi tổng hợp.
  • Bình luận hướng tương lai. Hồ sơ chứa các forward-looking statements nhưng mô hình lại coi chúng đúng như mặt chữ trừ khi được dặn khác đi. Hãy thêm vào prompt: 'Đánh dấu rõ ràng các forward-looking statements. Đừng trình bày guidance như một sự thật.'

Bản build tối thiểu khả thi

Vẫn áp dụng đúng mẫu vòng lặp tool-use của Claude từ hướng dẫn research-agent — chỉ có các công cụ và system prompt thay đổi:

from anthropic import Anthropic
import requests

KEY = "pk_yourkey"
client = Anthropic()

def fetch_tool(path: str) -> dict:
    return requests.get(f"https://www.apipick.com{path}/tool-schema").json()["claude"]

TOOLS = [
    fetch_tool("/api/search/sec"),
    fetch_tool("/api/extract"),
    fetch_tool("/api/company/facts"),
]

def call_tool(block):
    name_to_path = {
        "sec_search": "/api/search/sec",
        "extract_urls": "/api/extract",
        "company_facts": "/api/company/facts",
    }
    path = name_to_path[block.name]
    method = "GET" if block.name == "company_facts" else "POST"
    if method == "GET":
        resp = requests.get(
            f"https://www.apipick.com{path}",
            params=block.input,
            headers={"x-api-key": KEY},
            timeout=30,
        )
    else:
        resp = requests.post(
            f"https://www.apipick.com{path}",
            json=block.input,
            headers={"x-api-key": KEY},
            timeout=30,
        )
    return {
        "type": "tool_result",
        "tool_use_id": block.id,
        "content": resp.text,
        "is_error": resp.status_code != 200,
    }

def due_dil(question: str) -> str:
    messages = [{"role": "user", "content": question}]
    while True:
        r = client.messages.create(
            model="claude-sonnet-4-6",
            max_tokens=2048,
            system=SYSTEM_PROMPT,  # the one above
            tools=TOOLS,
            messages=messages,
        )
        messages.append({"role": "assistant", "content": r.content})
        if r.stop_reason == "end_turn":
            return "\n".join(b.text for b in r.content if b.type == "text")
        if r.stop_reason == "tool_use":
            results = [call_tool(b) for b in r.content if b.type == "tool_use"]
            messages.append({"role": "user", "content": results})

print(due_dil("Compare Snowflake's product revenue YoY for the last 4 quarters."))

Đưa nó đi tiếp đến đâu

  • Mẫu cho các lượt rà soát lặp lại. Gói tác nhân vào một CLI nhỏ nhận một ticker và xuất ra một bản brief markdown theo định dạng cố định: 'Các 8-K gần đây', 'Xu hướng doanh thu theo phân khúc', 'Delta yếu tố rủi ro'. Cùng một tác nhân, các prompt được viết sẵn theo script.
  • Chế độ watchlist. Chạy tác nhân trên một ticker mỗi sáng và diff câu trả lời hôm nay với hôm qua. Chỉ làm nổi bật các delta. Phối hợp tốt với mẫu briefing buổi sáng.
  • Kết hợp với bằng sáng chế và prediction markets. Với các tên tuổi tech / biotech, hãy bổ sung Patent Search cho các thay đổi về IP và Prediction Markets cho các kết cục mà đám đông ngụ ý (ví dụ: xác suất được phê duyệt của một loại thuốc).

Mẫu hình này có thể tổng quát hóa. SEC là corpus dày đặc nhất, thân thiện với schema nhất mà chúng tôi cung cấp — nhưng vòng lặp ('tìm kiếm ngữ nghĩa → trích xuất URL → trả lời kèm trích dẫn') áp dụng cho bất kỳ corpus tài liệu có cấu trúc nào bạn quan tâm: hồ sơ pháp lý, tóm tắt khoa học, yêu sách bằng sáng chế. Hãy xây tác nhân thẩm định trước, rồi chuyển kiến trúc đó sang ngang.

Câu hỏi thường gặp

Chỉ mục SEC mới đến mức nào?

Hồ sơ được lập chỉ mục trong vòng vài giờ sau khi được EDGAR chấp nhận. Với 8-K (loại nhạy cảm về thời gian — sự kiện trọng yếu, thay đổi lãnh đạo, thương vụ mua lại), điều này thường đủ nhanh cho các quy trình cuối ngày. Nếu bạn cần thông báo về 8-K mới trong vòng chưa đầy một giờ, hãy ghép việc tìm kiếm với một feed RSS riêng của SEC và chỉ dùng tác nhân để phân tích nội dung, không phải để phát hiện.

Nó có bao gồm bản ghi các buổi công bố lợi nhuận không?

Có — chỉ mục SEC Filings Search bao gồm bản ghi các buổi công bố lợi nhuận của Mỹ và thống kê equity (giá/khối lượng, lịch sử vốn hóa thị trường) bên cạnh chính các hồ sơ. Một query ngữ nghĩa duy nhất có thể lấy dữ liệu từ bất kỳ nguồn nào trong số này.

Đâu là các đòn bẩy chi phí nếu tôi làm điều này ở quy mô lớn?

Ba. (1) Lọc trước bằng Company Facts (2 credits) để xác nhận một ticker là công ty đại chúng thật trước khi tiêu 120 credits cho một lượt tìm kiếm SEC. (2) Cache kết quả tìm kiếm theo (ticker, quý) — hồ sơ chỉ cập nhật theo lịch của chúng. (3) Dùng một lượt tìm kiếm rộng cho mỗi câu hỏi thay vì nhiều lượt hẹp; tác nhân giỏi tổng hợp xuyên suốt các kết quả.

Tác nhân có xử lý được hồ sơ ngoài Mỹ không?

SEC Filings Search bao quát các công ty niêm yết tại Mỹ (10-K, 10-Q, 8-K). Với công ty Anh, hãy ghép UK Legal Search và Web Search. Với các khu vực pháp lý khác, hãy quay về dùng Web Search + URL Extract trên trang của cơ quan quản lý quốc gia liên quan (Companies House, SEDAR, v.v.).

Làm sao để tránh các con số bịa đặt (hallucinated)?

Ba quy tắc trong system prompt tạo ra khác biệt lớn nhất. (1) 'Trích nguyên văn các con số từ văn bản đã trích xuất — không bao giờ diễn giải lại hay làm tròn.' (2) 'Luôn kèm theo loại biểu mẫu hồ sơ, kỳ tài chính và một tham chiếu mục.' (3) 'Nếu hồ sơ liên quan chưa được trích xuất, hãy nói rõ điều đó — đừng suy diễn từ dữ liệu huấn luyện.' Ba quy tắc này cùng nhau loại bỏ phần lớn việc bịa đặt.

Các API dùng trong bài viết này

Sarah Choy
Viết bởi
Sarah Choy
CEO, API Pick

Sarah Choy là CEO của API Pick. Cô viết về việc xây dựng các API sẵn sàng cho production cho AI agent và quy trình LLM.