Rebalancing danh mục đầu tư là một trong những chiến lược quản lý vốn đã được chứng minh qua nhiều thập kỷ. Bot Python có thể tự động hóa toàn bộ quy trình này — từ tính toán tỷ trọng, thực hiện giao dịch đến báo cáo hiệu suất.
Tại Sao Cần Rebalancing Tự Động?
Giả sử danh mục mục tiêu của bạn: 60% BTC, 30% ETH, 10% USDT.
Sau 3 tháng BTC tăng mạnh, tỷ trọng tự nhiên thay đổi: 75% BTC, 20% ETH, 5% USDT. Danh mục bây giờ quá tập trung vào BTC — rủi ro tăng cao.
Rebalancing = bán bớt BTC, mua thêm ETH/USDT để về đúng 60/30/10. Bot làm điều này tự động, kỷ luật, không cảm xúc.
Cấu Trúc Bot Portfolio
from dataclasses import dataclass
from typing import Dict
import ccxt
import pandas as pd
from datetime import datetime
@dataclass
class PortfolioConfig:
target_weights: Dict[str, float] # {"BTC/USDT": 0.6, "ETH/USDT": 0.3}
rebalance_threshold: float = 0.05 # Rebalance khi lệch > 5%
min_trade_value: float = 10.0 # Không trade nếu < $10
class PortfolioBot:
def __init__(self, exchange: ccxt.Exchange, config: PortfolioConfig):
self.exchange = exchange
self.config = config
def get_portfolio_value(self) -> Dict[str, float]:
"""Lấy giá trị hiện tại của danh mục"""
balance = self.exchange.fetch_balance()
tickers = self.exchange.fetch_tickers(list(self.config.target_weights.keys()))
portfolio = {}
for symbol, weight in self.config.target_weights.items():
coin = symbol.split('/')[0]
qty = balance.get(coin, {}).get('total', 0)
price = tickers[symbol]['last']
portfolio[symbol] = qty * price
return portfolio
def calculate_rebalance_orders(self) -> list:
"""Tính toán các lệnh cần thiết để rebalance"""
portfolio = self.get_portfolio_value()
total_value = sum(portfolio.values())
orders = []
for symbol, target_weight in self.config.target_weights.items():
current_value = portfolio.get(symbol, 0)
current_weight = current_value / total_value
target_value = total_value * target_weight
diff = target_value - current_value
diff_weight = abs(current_weight - target_weight)
# Chỉ rebalance nếu lệch đủ nhiều
if (diff_weight > self.config.rebalance_threshold and
abs(diff) > self.config.min_trade_value):
orders.append({
'symbol': symbol,
'side': 'buy' if diff > 0 else 'sell',
'value': abs(diff),
'current_weight': f"{current_weight*100:.1f}%",
'target_weight': f"{target_weight*100:.1f}%"
})
return orders
def execute_rebalance(self):
"""Thực hiện rebalance"""
orders = self.calculate_rebalance_orders()
if not orders:
print(f"{datetime.now()}: Portfolio cân bằng, không cần rebalance")
return
for order in orders:
ticker = self.exchange.fetch_ticker(order['symbol'])
price = ticker['last']
quantity = order['value'] / price
print(f"Rebalancing: {order['side'].upper()} {order['symbol']} "
f"${order['value']:.2f} | "
f"{order['current_weight']} → {order['target_weight']}")
self.exchange.create_market_order(
order['symbol'],
order['side'],
round(quantity, 6)
)
Tính Hiệu Suất Danh Mục
def calculate_performance(portfolio_history: pd.DataFrame) -> dict:
"""
portfolio_history: DataFrame với index=date, column='value'
"""
daily_returns = portfolio_history['value'].pct_change().dropna()
total_return = (portfolio_history['value'].iloc[-1] /
portfolio_history['value'].iloc[0] - 1) * 100
# Sharpe Ratio (giả sử risk-free rate = 4%/năm)
rf_daily = 0.04 / 252
sharpe = (daily_returns.mean() - rf_daily) / daily_returns.std() * (252 ** 0.5)
# Max Drawdown
rolling_max = portfolio_history['value'].cummax()
drawdown = (portfolio_history['value'] - rolling_max) / rolling_max
max_drawdown = drawdown.min() * 100
return {
'total_return': f"{total_return:.2f}%",
'sharpe_ratio': f"{sharpe:.2f}",
'max_drawdown': f"{max_drawdown:.2f}%",
'volatility': f"{daily_returns.std() * (252**0.5) * 100:.2f}%"
}
Gửi Báo Cáo Telegram Hàng Ngày
import requests
def send_telegram_report(bot_token: str, chat_id: str, report: dict):
portfolio = report['portfolio']
perf = report['performance']
message = f"""
📊 *Báo Cáo Danh Mục Hôm Nay*
📅 {datetime.now().strftime('%d/%m/%Y %H:%M')}
💼 *Tổng giá trị:* ${report['total_value']:,.2f}
*Phân bổ hiện tại:*
"""
for symbol, data in portfolio.items():
message += f"• {symbol}: ${data['value']:,.2f} ({data['weight']:.1f}%)\n"
message += f"""
📈 *Hiệu suất:*
• Tổng lợi nhuận: {perf['total_return']}
• Sharpe Ratio: {perf['sharpe_ratio']}
• Max Drawdown: {perf['max_drawdown']}
"""
requests.post(
f"https://api.telegram.org/bot{bot_token}/sendMessage",
json={"chat_id": chat_id, "text": message, "parse_mode": "Markdown"}
)
Lên Lịch Chạy Tự Động
import schedule
bot = PortfolioBot(exchange, PortfolioConfig(
target_weights={"BTC/USDT": 0.6, "ETH/USDT": 0.3, "BNB/USDT": 0.1}
))
# Rebalance mỗi tuần vào thứ Hai lúc 8:00
schedule.every().monday.at("08:00").do(bot.execute_rebalance)
# Báo cáo hàng ngày lúc 20:00
schedule.every().day.at("20:00").do(lambda: send_telegram_report(...))
while True:
schedule.run_pending()
time.sleep(60)
Xây dựng hệ thống quản lý danh mục đầu tư tự động hoàn chỉnh tại Hướng Nghiệp Dữ Liệu.