Phân tích dữ liệu chứng khoán Việt Nam bằng Python

Phân tích dữ liệu chứng khoán Việt Nam bằng Python: Hành trình nhỏ với BeautifulSoup

“Tôi bắt đầu học phân tích dữ liệu chứng khoán không phải vì muốn trở thành Warren Buffett, mà chỉ vì một hôm rảnh, muốn thử crawl dữ liệu xem cảm giác hacker là như thế nào.”

Một buổi sáng đẹp trời…

Tôi ngồi cà phê ở góc quen, nghe nhạc lo-fi, và chợt nghĩ: “Nếu mình có thể lấy dữ liệu cổ phiếu từ website nào đó, rồi phân tích xem xu hướng tăng giảm, thì vui phết.” Thế là mở laptop, gõ jupyter notebook, và bắt đầu hành trình mới.

Mục tiêu hôm nay

  • Crawl dữ liệu cổ phiếu từ website CafeF hoặc VNDIRECT
  • Dùng BeautifulSoup để xử lý HTML
  • Lưu dữ liệu vào CSV
  • Phân tích nhanh xu hướng giá cổ phiếu

Chuẩn bị công cụ

pip install requests beautifulsoup4 pandas matplotlib

Code: Crawl dữ liệu cổ phiếu

Tôi chọn CafeF, vì nó đơn giản và dữ liệu hiển thị rõ ràng. Giả sử ta muốn lấy bảng giá cổ phiếu của mã VNM.

import requests
from bs4 import BeautifulSoup
import pandas as pd
import time

# Hàm crawl dữ liệu từ CafeF
def crawl_cafef(stock_code):
    url = f"https://s.cafef.vn/Lich-su-giao-dich-{stock_code}-1.chn"
    headers = {
        "User-Agent": "Mozilla/5.0"
    }
    
    res = requests.get(url, headers=headers)
    res.encoding = 'utf-8'  # rất quan trọng với trang tiếng Việt

    soup = BeautifulSoup(res.text, "html.parser")
    
    table = soup.find("table", id="tblData")
    rows = table.find_all("tr")[1:]  # bỏ header

    data = []
    for row in rows:
        cols = row.find_all("td")
        if len(cols) >= 6:
            item = {
                "date": cols[0].text.strip(),
                "close": cols[1].text.strip().replace(",", ""),
                "change": cols[2].text.strip(),
                "volume": cols[4].text.strip().replace(",", "")
            }
            data.append(item)

    df = pd.DataFrame(data)
    df["close"] = pd.to_numeric(df["close"], errors='coerce')
    df["volume"] = pd.to_numeric(df["volume"], errors='coerce')
    df["date"] = pd.to_datetime(df["date"], format="%d/%m/%Y")

    return df

Phân tích đơn giản

Lấy dữ liệu mã VNM:

df = crawl_cafef("VNM")
df = df.sort_values("date")  # sắp xếp theo thời gian tăng dần
df.head()

Vẽ biểu đồ giá đóng cửa:

import matplotlib.pyplot as plt

plt.figure(figsize=(10,5))
plt.plot(df["date"], df["close"], label="Giá đóng cửa")
plt.xlabel("Ngày")
plt.ylabel("Giá (VND)")
plt.title("Diễn biến giá cổ phiếu VNM")
plt.grid(True)
plt.legend()
plt.show()

Một vài insight nhỏ

  • Có thể thấy giá VNM biến động khá đều, không “lắc” như mấy mã đầu cơ.
  • Khối lượng giao dịch cũng giúp ta đo được mức độ quan tâm của thị trường.

Vậy rồi sao?

Tôi không định trở thành chuyên gia tài chính. Nhưng sau hôm đó, tôi hiểu thêm về web scraping, về cách xử lý dữ liệu dạng bảng HTML, và về cách Python có thể giúp mình tiếp cận những thế giới dữ liệu mà trước đây tôi từng nghĩ là “chỉ có chuyên gia mới đụng tới được”.

“Biết thêm một thứ mới, dù nhỏ, cũng là một cách để sống nhiều hơn một đời.”


🔚 Kết luận

Nếu bạn đang đọc đến đây và thấy hứng thú, hãy thử tự crawl một mã cổ phiếu mà bạn yêu thích. Có thể bạn sẽ phát hiện ra điều gì đó thú vị. Hoặc ít nhất, bạn sẽ biết cách lấy dữ liệu từ một website một kỹ năng không hề vô dụng trong thế giới hiện đại.

Nếu muốn nâng tầm, có thể thử:

  • Crawl nhiều trang, nhiều mã
  • Tự động hóa cập nhật hàng ngày
  • Dùng Plotly hoặc Dash để làm dashboard
  • Dùng phân tích kỹ thuật với thư viện như ta-lib hoặc bt

Một số nguồn dữ liệu khác


“Hãy bắt đầu từ việc nhỏ. Một đoạn code. Một biểu đồ. Rồi một ngày, bạn sẽ thấy mình đang đứng giữa một rừng dữ liệu nhưng không còn thấy lạc.”


Viết bởi một đứa học crawl web vì buồn ngủ mà cà phê không đủ đô.