Trang chủBlogTâm Lý TradingSentiment Analysis biến văn bản tin tức thành điểm số tích cực, tiêu cực và trung tính ra sao?
Sentiment Analysis biến văn bản tin tức thành điểm số tích cực, tiêu cực và trung tính ra sao?
Tâm Lý Trading

Sentiment Analysis biến văn bản tin tức thành điểm số tích cực, tiêu cực và trung tính ra sao?

Sentiment Analysis

Ngọc Hải LươngNgọc Hải Lương
6/8/2026
19 phút phút đọc
30 lượt xem

Sentiment Analysis biến văn bản tin tức thành điểm số tích cực, tiêu cực và trung tính ra sao?

Mỗi ngày, thị trường xuất hiện hàng nghìn tiêu đề, thông báo doanh nghiệp, báo cáo phân tích và bài đăng mạng xã hội. Nhà đầu tư có thể đọc từng bài để đánh giá tin nào tích cực, tin nào tiêu cực, nhưng cách làm thủ công khó mở rộng khi số lượng văn bản quá lớn. Sentiment Analysis giải quyết vấn đề này bằng cách chuyển ngôn ngữ tự nhiên thành dữ liệu có cấu trúc. Thay vì chỉ lưu một tiêu đề như “Lợi nhuận quý II tăng 35% nhưng dòng tiền kinh doanh âm”, hệ thống có thể tạo ra ba điểm số như tích cực 0,46, tiêu cực 0,38 và trung tính 0,16. Những điểm số đó chưa phải tín hiệu mua bán, nhưng chúng giúp máy tính sắp xếp, so sánh và theo dõi tâm lý của hàng nghìn tin tức theo thời gian.

Điểm cần hiểu là Sentiment Analysis trong tài chính không đơn giản chỉ đếm những từ như “tăng”, “giảm”, “lãi” hay “lỗ”. Một câu có từ “giảm” vẫn có thể mang ý nghĩa tích cực, chẳng hạn “nợ vay giảm mạnh” hoặc “mức lỗ giảm so với cùng kỳ”. Ngược lại, một câu có từ “tăng” vẫn có thể tiêu cực như “nợ xấu tăng”, “chi phí lãi vay tăng” hoặc “hàng tồn kho tăng nhanh hơn doanh thu”. Vì ngôn ngữ tài chính có ý nghĩa phụ thuộc vào ngữ cảnh, mô hình phải hiểu cả từ ngữ, thứ tự xuất hiện, đối tượng được nhắc tới và mối quan hệ giữa các vế câu.

ed8143d8-9daa-4d95-9d30-9468614e63f2.png

Phần 1: Từ một câu tin tức đến ba điểm số được thực hiện như thế nào?

Quy trình Sentiment Analysis thường bắt đầu bằng việc thu thập văn bản cùng thông tin thời gian và đối tượng liên quan. Một bản tin hoàn chỉnh không nên chỉ có nội dung, mà cần đi kèm thời điểm xuất bản, nguồn tin, mã cổ phiếu, doanh nghiệp được nhắc tới và loại sự kiện. Những trường này giúp hệ thống hiểu điểm sentiment đang nói về ai và có thể được sử dụng từ thời điểm nào.

Ví dụ, chúng ta có câu:

FPT ghi nhận lợi nhuận trước thuế tăng 18%, doanh thu ký mới mảng công nghệ nước ngoài tăng hơn 30%.

Bước đầu tiên là làm sạch văn bản. Hệ thống có thể chuyển chữ về cùng một dạng, loại bỏ ký tự thừa, chuẩn hóa khoảng trắng và xử lý các từ viết tắt. Tuy nhiên, không nên xóa tùy tiện các con số, dấu phần trăm hoặc từ phủ định vì đây thường là những phần mang ý nghĩa quan trọng trong tin tài chính.

Bước tiếp theo là tách văn bản thành các đơn vị nhỏ hơn, thường gọi là token. Với mô hình đơn giản, token có thể là từng từ. Với mô hình Transformer, một từ có thể được chia thành nhiều mảnh nhỏ để mô hình xử lý được cả những từ ít gặp. Sau đó, mỗi token được chuyển thành một dãy số đại diện cho ý nghĩa của nó trong câu.

Mô hình không nhìn thấy chữ theo cách con người nhìn thấy. Nó nhận một chuỗi số, xử lý chuỗi đó qua nhiều lớp và cuối cùng tạo ra ba giá trị thô tương ứng với ba nhãn:

positive
negative
neutral

Ba giá trị thô được chuyển thành xác suất. Tổng ba xác suất thường bằng 1. Ví dụ minh họa:

positive = 0.82
negative = 0.05
neutral  = 0.13

Kết quả này có thể được hiểu rằng mô hình đánh giá câu tin tức có xác suất tích cực là 82%, tiêu cực 5% và trung tính 13%. Nhãn cuối cùng thường là nhãn có xác suất cao nhất, nhưng trong phân tích Quant, giữ lại cả ba xác suất sẽ hữu ích hơn chỉ lưu một nhãn.

Một điểm sentiment liên tục có thể được tạo bằng cách lấy xác suất tích cực trừ xác suất tiêu cực:

sentiment_score = positive_probability - negative_probability

Với ví dụ trên:

sentiment_score = 0.82 - 0.05
sentiment_score = 0.77

Điểm số này thường nằm trong khoảng từ -1 đến 1. Điểm gần 1 thể hiện khuynh hướng tích cực mạnh, điểm gần -1 thể hiện khuynh hướng tiêu cực mạnh, còn điểm gần 0 cho thấy nội dung trung tính hoặc có hai chiều tích cực và tiêu cực tương đối cân bằng.

Cần lưu ý rằng “trung tính” không đồng nghĩa với “không quan trọng”. Câu “Công ty sẽ tổ chức đại hội cổ đông bất thường vào ngày 20/8” có thể được mô hình đánh giá trung tính vì bản thân câu chưa cho biết tốt hay xấu. Tuy nhiên, đây vẫn có thể là một sự kiện quan trọng nếu nội dung đại hội liên quan đến phát hành cổ phiếu, thay đổi nhân sự hoặc tái cấu trúc doanh nghiệp.

Một vấn đề khác là mức độ chắc chắn của mô hình. Giả sử mô hình trả về:

positive = 0.38
negative = 0.34
neutral  = 0.28

Dù positive là nhãn cao nhất, khoảng cách giữa positive và negative rất nhỏ. Đây không nên được xem là một tín hiệu tích cực mạnh. Hệ thống có thể đặt thêm điều kiện rằng xác suất cao nhất phải vượt 0,55 hoặc chênh lệch giữa hai nhãn cao nhất phải đủ lớn mới chấp nhận kết quả.

Ví dụ:

Nếu xác suất cao nhất dưới 0.55:
Gắn nhãn uncertain

Nếu positive - negative lớn hơn 0.30:
Xem là tích cực tương đối rõ

Nếu negative - positive lớn hơn 0.30:
Xem là tiêu cực tương đối rõ

Các ngưỡng trên chỉ là ví dụ. Ngưỡng phù hợp phải được kiểm tra trên tập dữ liệu đã gắn nhãn thực tế, không nên chọn chỉ vì nó làm kết quả backtest đẹp hơn.

Phần 2: Ba cách phổ biến để biến tin tức thành điểm sentiment

Cách đơn giản nhất là phương pháp từ điển. Người nghiên cứu xây dựng một danh sách từ tích cực và tiêu cực, sau đó cộng điểm dựa trên số lần các từ xuất hiện. Ví dụ, các cụm “vượt kế hoạch”, “lợi nhuận kỷ lục”, “giảm nợ”, “nâng hạng” có thể mang điểm tích cực; trong khi “thua lỗ”, “nợ xấu tăng”, “xử phạt”, “đình chỉ” hoặc “mất khả năng thanh toán” mang điểm tiêu cực.

Đoạn code dưới đây minh họa một mô hình từ điển rất cơ bản cho văn bản tiếng Việt. Code có thể copy và chạy trực tiếp bằng Python mà không cần cài thêm thư viện.

import math
import re


POSITIVE_PHRASES = {
    "vượt kế hoạch": 2.0,
    "lợi nhuận kỷ lục": 2.0,
    "giảm nợ": 1.5,
    "nâng hạng": 1.5,
    "tăng trưởng mạnh": 1.5,
    "cải thiện biên lợi nhuận": 1.8,
    "dòng tiền dương": 1.4,
}

NEGATIVE_PHRASES = {
    "thua lỗ": 2.0,
    "nợ xấu tăng": 1.8,
    "bị xử phạt": 1.7,
    "đình chỉ giao dịch": 2.0,
    "mất khả năng thanh toán": 2.5,
    "dòng tiền âm": 1.5,
    "suy giảm lợi nhuận": 1.6,
}

POSITIVE_WORDS = {
    "tăng": 0.8,
    "lãi": 1.0,
    "tích cực": 1.2,
    "phục hồi": 1.0,
    "mở rộng": 0.8,
    "cải thiện": 1.0,
    "vượt": 0.8,
}

NEGATIVE_WORDS = {
    "giảm": 0.8,
    "lỗ": 1.2,
    "tiêu cực": 1.2,
    "rủi ro": 0.8,
    "suy yếu": 1.0,
    "chậm": 0.6,
    "xử phạt": 1.3,
}

NEGATIONS = {
    "không",
    "chưa",
    "chẳng",
}

BOOSTERS = {
    "mạnh": 1.4,
    "đáng kể": 1.3,
    "kỷ lục": 1.5,
}


def softmax(values):
    max_value = max(values)
    exp_values = [
        math.exp(value - max_value)
        for value in values
    ]
    total = sum(exp_values)

    return [
        value / total
        for value in exp_values
    ]


def sentiment_lexicon(text):
    cleaned_text = text.lower().strip()

    positive_raw = 0.0
    negative_raw = 0.0

    # Chấm điểm các cụm từ trước
    for phrase, weight in POSITIVE_PHRASES.items():
        if phrase in cleaned_text:
            positive_raw += weight
            cleaned_text = cleaned_text.replace(phrase, " ")

    for phrase, weight in NEGATIVE_PHRASES.items():
        if phrase in cleaned_text:
            negative_raw += weight
            cleaned_text = cleaned_text.replace(phrase, " ")

    # Tách các từ còn lại
    tokens = re.findall(
        r"\w+",
        cleaned_text,
        flags=re.UNICODE
    )

    for index, token in enumerate(tokens):
        score = 0.0

        if token in POSITIVE_WORDS:
            score = POSITIVE_WORDS[token]

        elif token in NEGATIVE_WORDS:
            score = -NEGATIVE_WORDS[token]

        if score == 0:
            continue

        # Kiểm tra từ phủ định trong ba từ phía trước
        previous_tokens = tokens[
            max(0, index - 3):index
        ]

        if any(
            word in NEGATIONS
            for word in previous_tokens
        ):
            score = -score

        # Kiểm tra từ nhấn mạnh ngay phía sau
        if index + 1 < len(tokens):
            next_token = tokens[index + 1]

            if next_token in BOOSTERS:
                score *= BOOSTERS[next_token]

        if score > 0:
            positive_raw += score
        else:
            negative_raw += abs(score)

    # Neutral cao hơn khi ít từ mang cảm xúc
    neutral_raw = max(
        0.4,
        1.5 - abs(positive_raw - negative_raw)
    )

    probabilities = softmax([
        positive_raw,
        negative_raw,
        neutral_raw
    ])

    result = {
        "positive": round(probabilities[0], 4),
        "negative": round(probabilities[1], 4),
        "neutral": round(probabilities[2], 4),
    }

    result["sentiment_score"] = round(
        result["positive"] - result["negative"],
        4
    )

    result["label"] = max(
        [
            "positive",
            "negative",
            "neutral"
        ],
        key=lambda label: result[label]
    )

    return result


examples = [
    "Doanh nghiệp ghi nhận lợi nhuận kỷ lục và vượt kế hoạch năm.",
    "Công ty bị xử phạt và dòng tiền âm trong quý II.",
    "Công ty tổ chức đại hội cổ đông vào ngày 20 tháng 8.",
    "Lợi nhuận không tăng như kỳ vọng.",
]

for text in examples:
    print(text)
    print(sentiment_lexicon(text))
    print("-" * 60)

Kết quả sẽ có dạng:

Doanh nghiệp ghi nhận lợi nhuận kỷ lục và vượt kế hoạch năm.
{
    'positive': 0.93,
    'negative': 0.01,
    'neutral': 0.06,
    'sentiment_score': 0.92,
    'label': 'positive'
}

Công ty bị xử phạt và dòng tiền âm trong quý II.
{
    'positive': 0.02,
    'negative': 0.94,
    'neutral': 0.04,
    'sentiment_score': -0.92,
    'label': 'negative'
}

Các con số đầu ra có thể thay đổi nếu thay đổi trọng số trong từ điển. Đây chỉ là mô hình minh họa, chưa phù hợp để dùng trực tiếp cho giao dịch. Điểm yếu của phương pháp từ điển là nó khó hiểu được ngữ cảnh phức tạp.

Ví dụ:

Doanh thu tăng nhưng biên lợi nhuận giảm mạnh vì chi phí vốn cao.

Trong câu này có cả tín hiệu tích cực lẫn tiêu cực. Nếu chỉ đếm từ, mô hình có thể cho điểm gần trung tính hoặc thậm chí tích cực vì nhìn thấy “doanh thu tăng”. Tuy nhiên, đối với nhà đầu tư, việc biên lợi nhuận giảm mạnh có thể quan trọng hơn doanh thu tăng.

Cách thứ hai là Machine Learning truyền thống. Văn bản được chuyển thành các đặc trưng như số lần xuất hiện của từ, cụm hai từ hoặc chỉ số TF-IDF. Sau đó, mô hình như Logistic Regression hoặc SVM học từ một tập câu đã được con người gắn nhãn. So với từ điển, mô hình này có thể tự học rằng những cụm từ nào thường đi cùng tin tích cực hoặc tiêu cực.

Quy trình có thể được hiểu như sau:

Văn bản đã gắn nhãn
→ Chuyển thành TF-IDF
→ Huấn luyện Logistic Regression
→ Dự báo xác suất của ba lớp

Điểm hạn chế là mô hình TF-IDF vẫn chủ yếu dựa trên sự xuất hiện của từ. Nó chưa hiểu sâu thứ tự và mối quan hệ ngữ nghĩa. Hai câu dùng gần giống bộ từ nhưng khác cách sắp xếp có thể mang ý nghĩa hoàn toàn khác.

Cách thứ ba là dùng mô hình ngôn ngữ Transformer. Những mô hình này tạo biểu diễn từ dựa trên ngữ cảnh của toàn câu, nhờ đó có khả năng phân biệt “giảm nợ” với “giảm lợi nhuận”, hoặc “lỗ giảm” với “lợi nhuận giảm”.

FinBERT là một mô hình BERT được tiếp tục huấn luyện trên văn bản tài chính và tinh chỉnh cho bài toán sentiment tài chính. Model card của FinBERT cho biết mô hình trả về ba đầu ra softmax tương ứng positive, negative và neutral. Nghiên cứu gốc cũng nhấn mạnh rằng ngôn ngữ tài chính có tính chuyên biệt, khiến mô hình sentiment tổng quát thường không phù hợp bằng mô hình được điều chỉnh cho lĩnh vực tài chính.

Đoạn code sau có thể chạy trên Google Colab để phân tích một câu tiếng Anh bằng FinBERT:

# Chạy dòng này trên Google Colab
# !pip install -q transformers torch

import torch

from transformers import AutoTokenizer
from transformers import AutoModelForSequenceClassification


MODEL_NAME = "ProsusAI/finbert"

tokenizer = AutoTokenizer.from_pretrained(
    MODEL_NAME
)

model = AutoModelForSequenceClassification.from_pretrained(
    MODEL_NAME
)

text = (
    "The company reported record profit growth, "
    "but operating cash flow remained negative."
)

inputs = tokenizer(
    text,
    return_tensors="pt",
    truncation=True,
    max_length=512
)

with torch.no_grad():
    outputs = model(**inputs)

logits = outputs.logits[0]

probabilities = torch.softmax(
    logits,
    dim=-1
)

scores = {}

for index, probability in enumerate(probabilities):
    label = model.config.id2label[index].lower()

    scores[label] = round(
        float(probability),
        4
    )

sentiment_score = round(
    scores.get("positive", 0)
    - scores.get("negative", 0),
    4
)

print("Text:")
print(text)

print("\nScores:")
print(scores)

print("\nSentiment score:")
print(sentiment_score)

print("\nFinal label:")
print(max(scores, key=scores.get))

Hugging Face cung cấp text-classification pipeline như một lớp tiện ích để chạy các mô hình phân loại văn bản, nhưng đoạn code trên dùng trực tiếp tokenizer và model để người đọc nhìn rõ quá trình từ văn bản đến logits, rồi từ logits đến xác suất.

FinBERT nói trên được xây dựng cho văn bản tài chính tiếng Anh. Không nên đưa trực tiếp một tiêu đề tiếng Việt vào rồi mặc định kết quả chính xác. Với tin tức tiếng Việt, có thể dùng một mô hình nền như PhoBERT, sau đó fine-tune trên tập câu tài chính tiếng Việt đã được gắn nhãn positive, negative và neutral. PhoBERT là mô hình ngôn ngữ đơn ngữ quy mô lớn cho tiếng Việt, nhưng bản thân mô hình nền không tự động trở thành bộ phân loại sentiment tài chính nếu chưa được huấn luyện cho tác vụ đó.

Một tập dữ liệu huấn luyện tiếng Việt có thể được chuẩn bị theo dạng:

text:
"Lợi nhuận sau thuế tăng 35% và vượt kế hoạch năm."

label:
positive
text:
"Doanh nghiệp bị xử phạt do vi phạm công bố thông tin."

label:
negative
text:
"Công ty thông báo ngày đăng ký cuối cùng tham dự đại hội cổ đông."

label:
neutral

Phần khó nhất không phải là chạy mô hình, mà là xây dựng quy tắc gắn nhãn nhất quán. Với câu “doanh thu tăng 20% nhưng lợi nhuận giảm 30%”, người gắn nhãn phải xác định sentiment đang hướng tới doanh nghiệp, cổ phiếu hay một chỉ tiêu cụ thể. Nếu người thứ nhất gắn positive vì doanh thu tăng, còn người thứ hai gắn negative vì lợi nhuận giảm, dữ liệu huấn luyện sẽ chứa nhiều mâu thuẫn.

Phần 3: Từ điểm sentiment đến dữ liệu phục vụ phân tích đầu tư

Sau khi mỗi tin có ba xác suất, hệ thống có thể tạo một chỉ số sentiment theo ngày cho từng mã cổ phiếu. Tuy nhiên, không nên lấy trung bình đơn giản của tất cả bài viết vì một tin quan trọng và một bài nhắc tên doanh nghiệp thoáng qua không nên có trọng số bằng nhau.

Một cách tổng hợp đơn giản là tạo điểm cho từng tin:

news_score = positive_probability - negative_probability

Sau đó nhân với một số trọng số:

weighted_score
=
news_score
× source_weight
× relevance_weight
× time_decay

Công thức trên có thể được viết trực tiếp bằng Python như sau:

from datetime import datetime
from math import exp


def calculate_weighted_sentiment(
    positive,
    negative,
    source_weight,
    relevance_weight,
    hours_since_release,
    decay_rate=0.05
):
    sentiment_score = positive - negative

    time_decay = exp(
        -decay_rate * hours_since_release
    )

    weighted_score = (
        sentiment_score
        * source_weight
        * relevance_weight
        * time_decay
    )

    return round(weighted_score, 4)


score = calculate_weighted_sentiment(
    positive=0.82,
    negative=0.05,
    source_weight=1.0,
    relevance_weight=0.9,
    hours_since_release=3
)

print(score)

source_weight có thể cao hơn với công bố chính thức của doanh nghiệp hoặc cơ quan quản lý, thấp hơn với bài viết tổng hợp và thấp hơn nữa với nguồn chưa được xác minh. relevance_weight cho biết bài viết thực sự nói về doanh nghiệp ở mức nào. Nếu FPT chỉ được nhắc một lần trong bài viết dài về ngành công nghệ, độ liên quan có thể thấp hơn một bài phân tích trực tiếp kết quả kinh doanh FPT. time_decay làm cho tin mới có trọng số lớn hơn tin cũ.

Ví dụ, trong một ngày mã ABC có ba tin:

Tin 1:
positive = 0.80
negative = 0.05
sentiment_score = 0.75

Tin 2:
positive = 0.20
negative = 0.65
sentiment_score = -0.45

Tin 3:
positive = 0.15
negative = 0.10
sentiment_score = 0.05

Nếu ba tin có trọng số bằng nhau, điểm trung bình là:

daily_sentiment
=
(0.75 - 0.45 + 0.05) / 3

daily_sentiment
=
0.1167

Kết quả hơi tích cực, nhưng mức độ không lớn vì tin tốt và tin xấu gần như bù trừ lẫn nhau. Nếu tin tiêu cực là công bố chính thức còn tin tích cực chỉ là nhận định của một bài viết thứ cấp, tổng điểm sau khi gắn trọng số có thể chuyển sang âm.

Code tổng hợp nhiều tin theo mã và ngày có thể viết như sau:

import pandas as pd


news = pd.DataFrame({
    "ticker": [
        "ABC",
        "ABC",
        "ABC",
        "XYZ"
    ],
    "published_at": pd.to_datetime([
        "2026-08-06 08:00",
        "2026-08-06 09:15",
        "2026-08-06 14:30",
        "2026-08-06 10:00"
    ]),
    "positive": [
        0.80,
        0.20,
        0.15,
        0.72
    ],
    "negative": [
        0.05,
        0.65,
        0.10,
        0.08
    ],
    "source_weight": [
        0.80,
        1.00,
        0.60,
        0.90
    ],
    "relevance_weight": [
        1.00,
        0.95,
        0.50,
        0.85
    ]
})

news["sentiment_score"] = (
    news["positive"]
    - news["negative"]
)

news["weighted_sentiment"] = (
    news["sentiment_score"]
    * news["source_weight"]
    * news["relevance_weight"]
)

news["date"] = (
    news["published_at"]
    .dt.normalize()
)

daily_sentiment = (
    news
    .groupby(
        [
            "ticker",
            "date"
        ],
        as_index=False
    )
    .agg(
        sentiment_mean=(
            "sentiment_score",
            "mean"
        ),
        sentiment_weighted=(
            "weighted_sentiment",
            "sum"
        ),
        news_count=(
            "sentiment_score",
            "size"
        )
    )
)

print(daily_sentiment)

Điểm sentiment theo ngày có thể trở thành một feature trong mô hình Quant, nhưng cần tránh ba cách hiểu sai.

Thứ nhất, sentiment tích cực không đồng nghĩa giá cổ phiếu chắc chắn tăng. Nếu thị trường đã kỳ vọng lợi nhuận tăng 50% nhưng doanh nghiệp chỉ công bố tăng 30%, văn bản vẫn có nhiều từ tích cực nhưng phản ứng giá có thể tiêu cực. Trong đầu tư, điều quan trọng không chỉ là kết quả tốt hay xấu, mà là tốt hay xấu so với kỳ vọng đã nằm trong giá.

Thứ hai, sentiment của câu chưa chắc giống tác động lên cổ đông. Tin “doanh nghiệp cắt giảm 2.000 nhân sự” có thể tiêu cực về mặt xã hội nhưng lại được thị trường xem là tích cực nếu việc cắt giảm giúp tiết kiệm chi phí. Tin “ngân hàng tăng lãi suất huy động” có thể tích cực với người gửi tiền nhưng tiêu cực với biên lợi nhuận của ngân hàng. Vì vậy, mô hình tốt cần xác định sentiment đang hướng tới đối tượng nào.

Thứ ba, một bài viết có thể chứa nhiều sentiment khác nhau. Ví dụ:

Doanh thu tăng 25%.
Biên lợi nhuận giảm.
Dòng tiền kinh doanh âm.
Doanh nghiệp giảm được nợ vay.

Nếu ép toàn bộ bài viết thành một nhãn duy nhất, nhiều thông tin quan trọng sẽ bị mất. Cách nâng cao là phân tích theo từng khía cạnh:

Sentiment về tăng trưởng doanh thu: positive
Sentiment về biên lợi nhuận: negative
Sentiment về dòng tiền: negative
Sentiment về đòn bẩy tài chính: positive

Đây được gọi là Aspect-Based Sentiment Analysis. Trong tài chính, cách tiếp cận theo khía cạnh thường hữu ích hơn việc chỉ nói toàn bài tích cực hay tiêu cực.

Thời điểm của tin cũng phải được xử lý chính xác. Một báo cáo được đăng lúc 18 giờ không thể được dùng để tạo tín hiệu mua tại giá đóng cửa của cùng ngày. Tin xuất hiện sau giờ giao dịch chỉ nên được đưa vào feature từ phiên tiếp theo. Nếu hệ thống gắn sentiment vào ngày quan sát thay vì thời điểm công bố thực tế, backtest có thể bị Data Leakage.

Một pipeline tương đối hoàn chỉnh có thể được mô tả như sau:

Thu thập tin tức
→ Làm sạch văn bản
→ Xác định doanh nghiệp được nhắc tới
→ Phân loại loại sự kiện
→ Chạy mô hình sentiment
→ Lưu ba xác suất
→ Gắn thời điểm có thể sử dụng
→ Loại tin trùng lặp
→ Gắn trọng số nguồn và độ liên quan
→ Tổng hợp theo mã và thời gian
→ Ghép với dữ liệu giá
→ Backtest trên dữ liệu ngoài mẫu

Khi đánh giá mô hình sentiment, không nên chỉ nhìn Accuracy. Nếu tập dữ liệu có quá nhiều câu trung tính, một mô hình luôn đoán neutral vẫn có thể đạt Accuracy cao. Cần xem riêng Precision, Recall và F1 của từng lớp, đặc biệt là positive và negative. Nghiên cứu FinBERT cũng đánh giá mô hình bằng nhiều thước đo và cho thấy bài toán sentiment tài chính cần dữ liệu chuyên ngành thay vì chỉ dựa vào mô hình ngôn ngữ tổng quát.

Kết luận

Sentiment Analysis biến văn bản thành điểm số bằng cách mã hóa nội dung, xử lý ngữ cảnh và phân loại xác suất cho ba trạng thái tích cực, tiêu cực và trung tính. Phương pháp từ điển dễ hiểu và dễ triển khai nhưng khó xử lý ngữ cảnh. Machine Learning truyền thống có thể học từ dữ liệu gắn nhãn nhưng vẫn phụ thuộc nhiều vào từ khóa. Các mô hình Transformer như FinBERT có khả năng hiểu ngôn ngữ tài chính tốt hơn, nhưng vẫn cần đúng ngôn ngữ, đúng lĩnh vực và một tập dữ liệu gắn nhãn phù hợp.

Điểm sentiment không phải tín hiệu mua bán hoàn chỉnh. Nó chỉ là một lớp dữ liệu mô tả sắc thái của thông tin. Muốn đưa vào đầu tư, hệ thống còn phải biết tin nói về doanh nghiệp nào, xuất hiện lúc nào, đến từ nguồn nào, có mới so với kỳ vọng hay không và thị trường đã phản ánh thông tin đó vào giá đến đâu.