🐍 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
| Endpoint | Dữ liệu | Số bản ghi tối đa |
|---|---|---|
/api/v3/trades | Giao dịch gần đây | 1000 |
/api/v3/historicalTrades | Giao dịch lịch sử | 1000 |
/api/v3/aggTrades | Giao dịch đã gộp | 1000 |
/api/v3/klines | Nến OHLCV | 1000 |
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!