Chuyển tới nội dung chính

🐍 Ngày 43 Python 365 ngày | Phân tích dữ liệu giao dịch từ API Binance

🗓 Ngày 43: Phân tích dữ liệu giao dịch từ API Binance​

Hôm nay, bạn sẽ học cách thu thập dữ liệu giao dịch từ Binance và thực hiện phân tích cơ bản với Python.


🎯 Mục tiêu​

  • Hiểu cấu trúc dữ liệu giao dịch từ Binance.
  • Trích xuất dữ liệu giao dịch (trades).
  • Phân tích khối lượng, giá trung bình và thời gian giao dịch.

🧰 Cài đặt công cụ​

pip install python-binance pandas

🔌 Lấy dữ liệu giao dịch​

from binance.client import Client
import pandas as pd

api_key = "your_api_key"
api_secret = "your_api_secret"

client = Client(api_key, api_secret)

trades = client.get_recent_trades(symbol='BTCUSDT')
df = pd.DataFrame(trades)
print(df.head())

📊 Phân tích dữ liệu​

df['price'] = df['price'].astype(float)
df['qty'] = df['qty'].astype(float)

# Tính tổng khối lượng
total_volume = df['qty'].sum()

# Giá trung bình
avg_price = (df['price'] * df['qty']).sum() / total_volume

print("Tổng khối lượng:", total_volume)
print("Giá trung bình:", round(avg_price, 2))

📈 Vẽ biểu đồ giá và khối lượng​

import matplotlib.pyplot as plt

plt.figure(figsize=(10, 4))
plt.plot(df['price'], label='Giá BTC')
plt.xlabel('Lệnh giao dịch')
plt.ylabel('Giá')
plt.title('Biến động giá BTC - gần nhất')
plt.legend()
plt.grid(True)
plt.show()

📌 Bài tập gợi ý​

  • Vẽ biểu đồ giá và khối lượng theo thời gian.
  • So sánh giá trung bình giữa BTCUSDT và ETHUSDT.
  • Lưu dữ liệu về file .csv để huấn luyện mô hình sau này.


📊 Các endpoint dữ liệu giao dịch của Binance​

EndpointDữ liệuSố bản ghi tối đa
/api/v3/tradesGiao dịch gần đây1000
/api/v3/historicalTradesGiao dịch lịch sử1000
/api/v3/aggTradesGiao dịch đã gộp1000
/api/v3/klinesNến OHLCV1000

aggTrades khác trades ở đâu: trades trả về từng giao dịch riêng lẻ (một lệnh lớn khớp với 5 lệnh nhỏ → 5 bản ghi). aggTrades gộp các giao dịch cùng giá và cùng thời điểm thành một bản ghi — gọn hơn nhiều khi phân tích.

import urllib.request
import json
import pandas as pd


def lay_giao_dich(symbol: str = "BTCUSDT", so_luong: int = 1000) -> pd.DataFrame:
"""Lấy giao dịch gần đây và chuyển thành DataFrame."""
url = f"https://api.binance.com/api/v3/aggTrades?symbol={symbol}&limit={so_luong}"

with urllib.request.urlopen(url, timeout=20) as r:
du_lieu = json.loads(r.read().decode())

df = pd.DataFrame(du_lieu)
df = df.rename(columns={
"a": "ma_giao_dich",
"p": "gia",
"q": "khoi_luong",
"T": "thoi_gian_ms",
"m": "la_nguoi_mua_chu_dong",
})

# BẮT BUỘC: chuyển kiểu dữ liệu
df["gia"] = df["gia"].astype(float)
df["khoi_luong"] = df["khoi_luong"].astype(float)
df["gia_tri"] = df["gia"] * df["khoi_luong"]
df["thoi_gian"] = pd.to_datetime(df["thoi_gian_ms"], unit="ms")

return df[["ma_giao_dich", "thoi_gian", "gia", "khoi_luong",
"gia_tri", "la_nguoi_mua_chu_dong"]]


df = lay_giao_dich("BTCUSDT", 1000)
print(df.head())
print(f"\n{len(df)} giao dịch | từ {df['thoi_gian'].min()} đến {df['thoi_gian'].max()}")

🎯 Phân tích dòng tiền chủ động (taker flow)​

Đây là phân tích quan trọng nhất từ dữ liệu giao dịch — cho biết ai đang kiểm soát thị trường.

# m=True  → người MUA là taker (chấp nhận giá bán) = chủ động MUA
# m=False → người BÁN là taker (chấp nhận giá mua) = chủ động BÁN

mua_chu_dong = df[df["la_nguoi_mua_chu_dong"]]
ban_chu_dong = df[~df["la_nguoi_mua_chu_dong"]]

print(f"Chủ động MUA: {len(mua_chu_dong):>5} lệnh | "
f"{mua_chu_dong['khoi_luong'].sum():>12,.4f} BTC | "
f"{mua_chu_dong['gia_tri'].sum():>16,.0f} USDT")
print(f"Chủ động BÁN: {len(ban_chu_dong):>5} lệnh | "
f"{ban_chu_dong['khoi_luong'].sum():>12,.4f} BTC | "
f"{ban_chu_dong['gia_tri'].sum():>16,.0f} USDT")

tong_khoi_luong = df["khoi_luong"].sum()
chenh = (mua_chu_dong["khoi_luong"].sum() - ban_chu_dong["khoi_luong"].sum())

print(f"\nChênh lệch: {chenh:+,.4f} BTC ({chenh / tong_khoi_luong * 100:+.2f}%)")

print("\n📊 Nhận xét:")
if chenh > tong_khoi_luong * 0.1:
print(" 🟢 Người MUA đang chủ động — áp lực tăng")
elif chenh < -tong_khoi_luong * 0.1:
print(" 🔴 Người BÁN đang chủ động — áp lực giảm")
else:
print(" ➖ Cân bằng — chưa rõ hướng")

Vì sao chỉ số này có giá trị: giá có thể tăng vì thiếu người bán (thanh khoản mỏng) hoặc vì người mua thật sự chủ động. Phân tích taker flow phân biệt được hai trường hợp này — điều mà biểu đồ giá thuần không làm được.

💰 VWAP — giá bình quân theo khối lượng​

import numpy as np


def tinh_vwap(df: pd.DataFrame) -> float:
"""VWAP = tổng (giá × khối lượng) / tổng khối lượng."""
return float((df["gia"] * df["khoi_luong"]).sum() / df["khoi_luong"].sum())


def tinh_vwap_truot(df: pd.DataFrame, cua_so: int = 200) -> pd.Series:
"""VWAP trong cửa sổ trượt — theo dõi giá bình quân thay đổi thế nào."""
gia_tri = df["gia"] * df["khoi_luong"]
return gia_tri.rolling(cua_so).sum() / df["khoi_luong"].rolling(cua_so).sum()


vwap = tinh_vwap(df)
gia_hien_tai = df["gia"].iloc[-1]

print(f"VWAP: {vwap:,.2f}")
print(f"Giá hiện tại: {gia_hien_tai:,.2f}")
print(f"Chênh lệch: {(gia_hien_tai - vwap) / vwap * 100:+.3f}%")
print()

if gia_hien_tai > vwap:
print("📈 Giá trên VWAP — người mua gần đây đang có lợi nhuận")
else:
print("📉 Giá dưới VWAP — người mua gần đây đang lỗ")

df["vwap_truot"] = tinh_vwap_truot(df, 200)
print(f"\nVWAP 200 giao dịch gần nhất: {df['vwap_truot'].iloc[-1]:,.2f}")

💡 VWAP quan trọng vì sao: các tổ chức lớn thường đo hiệu quả giao dịch của họ so với VWAP — mua dưới VWAP là tốt, mua trên là kém. Khi giá ở xa VWAP, nhiều thuật toán mean-reversion sẽ hoạt động.

📦 Phân tích giao dịch lớn (whale detection)​


# --- Tìm giao dịch lớn bất thường ---
nguong = df["gia_tri"].quantile(0.99) # top 1%
lon = df[df["gia_tri"] >= nguong].copy()
lon["huong"] = np.where(lon["la_nguoi_mua_chu_dong"], "MUA", "BÁN")

print(f"Ngưỡng giao dịch lớn: {nguong:,.0f} USDT")
print(f"Số giao dịch lớn: {len(lon)}")

print("\n🐳 Top 5 giao dịch lớn nhất:")
for _, r in lon.nlargest(5, "gia_tri").iterrows():
print(f" {r['thoi_gian']:%H:%M:%S} {r['huong']:<4} "
f"{r['khoi_luong']:>8,.4f} BTC @ {r['gia']:>10,.2f} "
f"= {r['gia_tri']:>14,.0f} USDT")

# Giao dịch lớn nghiêng về bên nào?
tong_mua_lon = lon.loc[lon["la_nguoi_mua_chu_dong"], "gia_tri"].sum()
tong_ban_lon = lon.loc[~lon["la_nguoi_mua_chu_dong"], "gia_tri"].sum()

print(f"\nTổng giá trị giao dịch lớn:")
print(f" Mua: {tong_mua_lon:>16,.0f} USDT")
print(f" Bán: {tong_ban_lon:>16,.0f} USDT")

if tong_mua_lon > tong_ban_lon * 1.2:
print(" → 🟢 Cá mập đang MUA")
elif tong_ban_lon > tong_mua_lon * 1.2:
print(" → 🔴 Cá mập đang BÁN")
else:
print(" → ➖ Cá mập hành động cả hai chiều")

📝 Bài tập mở rộng​

Bài 1: So sánh taker flow giữa các cặp​

Lấy 1000 giao dịch của BTC, ETH, SOL. Cặp nào có áp lực mua chủ động mạnh nhất?

Bài 2: Theo dõi theo thời gian​

Chia 1000 giao dịch thành 10 nhóm theo thời gian, tính imbalance của từng nhóm. Imbalance đang tăng hay giảm?

Bài 3: Phát hiện giao dịch lớn bất thường​

Tìm các giao dịch có giá trị > 1 triệu USDT và lưu danh sách ra CSV.

Bài 4: Vẽ biểu đồ​

Vẽ biểu đồ thể hiện khối lượng mua chủ động và bán chủ động theo từng phút.

Bài 5: So sánh với dữ liệu nến​

Lấy dữ liệu nến 1 phút cùng khoảng thời gian, so sánh tổng khối lượng từ hai nguồn. Có khớp không?

🎯 Tóm tắt ngày 43​

✅ Phân biệt trades và aggTrades ✅ Chuyển dữ liệu giao dịch thành DataFrame — luôn .astype(float) ✅ Phân tích taker flow — biết ai đang chủ động ✅ Tính VWAP — giá bình quân theo khối lượng ✅ Phát hiện giao dịch lớn (whale detection) ✅ Hiểu vì sao phân tích dòng tiền mạnh hơn phân tích giá thuần


Phân tích dữ liệu là bước đầu tiên để hiểu thị trường và phát triển chiến lược giao dịch hiệu quả hơn!