VPS chạy trading bot cần quan tâm gì?
Tìm hiểu VPS chạy trading bot thực sự cần gì: systemd tự restart sau exception, đồng hồ đúng giờ, bảo vệ API key, heartbeat và giới hạn latency, thay vì tin uptime 99.9%.
VPS cần gì cho trading bot
Một VPS chạy trading bot được đánh giá dựa trên 4 yếu tố: tiến trình có khởi động lại sau khi bị dừng hay không, đồng hồ hệ thống có đúng giờ không, các API (application programming interface) key có khó bị đánh cắp không, và bạn có phát hiện được khi bot dừng hay không. Tốc độ thô không nằm ở vị trí cao trong danh sách này đối với một bot bán lẻ, vì phần chậm trong đường đi của lệnh thường là broker và khoảng cách đến broker, không phải host chạy Python.
Đây là hướng dẫn kỹ thuật. Nội dung này không phải tư vấn tài chính và không bàn về chiến lược.
Uptime là kỷ luật restart, không phải một con số trên trang bán hàng
Cam kết uptime được quảng cáo không giống nhau. AWS quy định tối thiểu 99.5 phần trăm cho một EC2 instance đơn lẻ và 99.99 phần trăm cho các deployment đủ điều kiện trên nhiều availability zone. Các cam kết đó chỉ áp dụng cho availability của hạ tầng, không áp dụng cho tình trạng hoạt động của bot. Bot có thể dừng vì unhandled exception, websocket không bao giờ reconnect, hoặc OOM (out of memory) killer, trong khi server vẫn hoạt động suốt thời gian đó. Vì vậy, câu hỏi hữu ích là process của bạn sẽ làm gì trong mười giây sau khi thoát.
Chạy bot dưới dạng systemd service và để init system quản lý việc restart. Một unit file có thể thực hiện việc này.
[Unit]
Description=Trading bot
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=0
[Service]
Type=simple
User=bot
WorkingDirectory=/opt/tradingbot
EnvironmentFile=/etc/tradingbot/api.env
ExecStart=/opt/tradingbot/venv/bin/python -m tradingbot
Restart=always
RestartSec=10
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/lib/tradingbot
[Install]
WantedBy=multi-user.targetStartLimitIntervalSec=0 là dòng mà nhiều người bỏ qua. Các giá trị mặc định của systemd upstream cho phép 5 lần start trong 10 giây, bao gồm lần start ban đầu và các lần start thủ công; cấu hình của manager có thể ghi đè các giá trị mặc định đó. Khi chạm giới hạn, systemd dừng các lần thử restart tự động, nhưng unit vẫn có thể được start thủ công hoặc bởi timer hay socket sau khi khoảng thời gian đó kết thúc. Đặt giá trị này thành 0 sẽ tắt rate limit, nên bot bị crash-loop sẽ tiếp tục thử thay vì im lặng dừng lại. RestartSec=10 ngăn vòng lặp đó liên tục gửi reconnect đến exchange.
Kiểm tra file trước khi tin tưởng cấu hình, rồi start service:
sudo systemd-analyze verify /etc/systemd/system/tradingbot.service
sudo systemctl daemon-reload
sudo systemctl enable --now tradingbot
systemctl status tradingbotenable là phần giúp service tiếp tục hoạt động sau reboot, trong khi kernel update đồng nghĩa với việc phải reboot. Để biết bot có đang âm thầm dừng hay không, yêu cầu systemd hiển thị bộ đếm restart:
systemctl show tradingbot -p NRestarts
journalctl -u tradingbot --since "24 hours ago" | tail -50NRestarts=0 đếm số restart job tự động kể từ lần bộ đếm được reset gần nhất; nó không chứng minh rằng bot đã hoạt động ổn định hoặc không crash trong cả tuần. Các lần restart thủ công và systemctl reset-failed sẽ reset bộ đếm, còn bot bị treo vẫn có thể hiển thị giá trị 0. NRestarts=812 đếm 812 restart job, không phải số lần reconnect thành công đến exchange hoặc số giao dịch, và không cho biết chúng xảy ra vào thời điểm nào. Kiểm tra journal để biết thời điểm và nguyên nhân, bao gồm cả các lỗi xảy ra trước khi bot kết nối. Phần giải thích đầy đủ về cấu trúc unit file, bao gồm timer cho các job được lập lịch như báo cáo hằng ngày, có trong chạy một chương trình dưới dạng systemd service.
Đặt đồng hồ về UTC và xác nhận đồng hồ đã đồng bộ
Các API giao dịch dùng timestamp để xác thực request đã ký; Binance Spot mặc định dùng receive window 5 giây và từ chối timestamp sớm hơn thời gian trên server ít nhất 1 giây. Đồng hồ bị lệch tạo ra các lỗi trông giống lỗi xác thực, nên nhiều người xoay vòng key trong nhiều giờ trước khi kiểm tra thời gian. Trên các API kiểu Binance, thông báo lỗi ghi rõ: Timestamp for this request was 1000ms ahead of the server's time.
Đặt server về UTC. Múi giờ địa phương có thể tạo ra các bước nhảy do daylight saving trong thời gian hiển thị; Unix timestamp mà API sử dụng không thay đổi khi đổi múi giờ hiển thị.
sudo timedatectl set-timezone UTC
timedatectlUbuntu dùng mặc định chrony từ phiên bản 25.10 trở đi; các bản cài đặt cũ có thể dùng systemd-timesyncd, một client SNTP (simple network time protocol). systemd-timesyncd điều chỉnh đồng hồ, nhưng không thể poll nhiều server cùng lúc để phát hiện nguồn thời gian không chính xác. Thay vào đó, dùng chrony:
sudo apt update && sudo apt install -y chrony
sudo systemctl enable --now chrony
chronyc tracking
chronyc sources -vDòng cần đọc từ chronyc tracking là System time, ví dụ System time : 0.000031415 seconds fast of NTP time. Giá trị nhỏ cho biết phần hiệu chỉnh còn lại đối với đồng hồ NTP của chrony là nhỏ; trước khi đánh giá độ chính xác, hãy kiểm tra cả trạng thái đồng bộ, Root delay và Root dispersion. Nếu giá trị là Leap status : Not synchronised, chrony chưa được đồng bộ, ngay cả khi các server đã phản hồi; các phép đo có thể bị loại vì quá thiếu chính xác. Chờ một phút rồi kiểm tra lại trước khi thay đổi firewall rules.
Đừng để API keys trong những nơi bạn thường sao chép
Một exchange key bị lộ nguy hiểm hơn một SSH key bị lộ, vì quyền rút tiền có thể biến nó thành tiền ngay lập tức. Hai thói quen sau giúp xử lý phần lớn rủi ro.
Thứ nhất, không bao giờ cấp quyền rút tiền cho key của bot. Nếu exchange hỗ trợ, hãy giới hạn key cho địa chỉ IP của server. Đây là biện pháp kiểm soát duy nhất khiến key bị đánh cắp gần như vô dụng.
Thứ hai, không để secret trong thư mục code. Mọi thứ nằm trong /opt/tradingbot sớm muộn cũng sẽ xuất hiện trong git repository hoặc backup archive. Hãy đặt secret trong một file thuộc sở hữu của root để systemd đọc:
sudo install -d -m 750 -o root -g bot /etc/tradingbot
sudo install -m 640 -o root -g bot /dev/null /etc/tradingbot/api.env
sudo nano /etc/tradingbot/api.envFile này chứa các dòng KEY=value dạng plain, không có dấu ngoặc kép và không có export. Mode 640 cho phép owner là root đọc/ghi và các thành viên của group bot đọc, đồng thời không cấp quyền nào cho user khác. Xác minh bằng sudo -u bot cat /etc/tradingbot/api.env, sau đó kiểm tra bằng một user không có quyền đặc biệt và không thuộc group bot; thao tác này phải thất bại với Permission denied.
Bot cũng không nên chạy dưới root hoặc user dùng để đăng nhập. Hãy tạo một system account với shell nologin và /var/lib/tradingbot làm thư mục home trước khi khởi động service hoặc tạo các file thuộc group bot:
sudo useradd --system --shell /usr/sbin/nologin --home-dir /var/lib/tradingbot --create-home botPhần giải thích cho từng flag và giới hạn thực tế của ProtectSystem=strict nằm trong chạy service dưới user không có quyền đặc biệt. Các thiết lập nền tảng còn lại của server, gồm SSH keys và firewall, được trình bày trong 10 phút đầu tiên trên một VPS mới.
Phát hiện bot đã dừng trước khi broker của bạn phát hiện
systemctl status cho biết tiến trình đang chạy. Nó không cho biết bot có đang làm gì hay không. Một tiến trình bị kẹt trong vòng lặp retry khi kết nối đến websocket đã ngừng hoạt động vẫn vượt qua các bước kiểm tra tiến trình trong unit ở trên.
Thay vào đó, hãy dùng heartbeat. Uptime Kuma có push monitor: nó chờ bot gọi một URL theo lịch, rồi cảnh báo khi không còn nhận được cuộc gọi. Đặt lệnh gọi ở cuối vòng lặp chính, sau phần xác nhận bot vẫn hoạt động, chẳng hạn như đọc dữ liệu thị trường thành công.
curl -fsS "http://monitor.example.com:3001/api/push/YOUR_TOKEN?status=up&msg=loop_ok"Đặt interval của monitor xấp xỉ gấp đôi thời gian chạy vòng lặp để jitter thông thường không tạo cảnh báo giả. Chạy monitor trên server khác với server chạy bot, vì monitor chết cùng thứ mà nó theo dõi thì sẽ không báo gì. Xem hướng dẫn thiết lập tại giám sát trạng thái tự host bằng Uptime Kuma.
Cũng hãy thêm cảnh báo dung lượng disk. Bot ghi log quá chi tiết có thể làm đầy root filesystem trong vài tuần. Khi disk đầy, database write bị dừng chứ không phải network call, nên triệu chứng thường khó đoán. journalctl --vacuum-time=14d và một dòng SystemMaxUse= trong /etc/systemd/journald.conf giúp giới hạn kích thước journal.
Phần cần nói rõ: độ trễ phần lớn không nằm ở máy chủ của bạn
Đây là lúc thị trường VPS cho trading không còn mang tính kỹ thuật. Các trang marketing đưa ra con số dưới một mili giây và ám chỉ rằng máy chủ là yếu tố quyết định bạn có khớp lệnh hay không. Với hầu hết bot bán lẻ, điều đó không đúng.
Lệnh của bạn đi từ bot đến endpoint của sàn hoặc broker qua Internet công cộng. Đường truyền này chủ yếu bị chi phối bởi khoảng cách địa lý và kết nối peering giữa nhà cung cấp của bạn với nhà cung cấp của sàn hoặc broker. Sau đó, hệ thống của broker còn thêm thời gian xếp hàng, kiểm tra rủi ro và giới hạn tốc độ.
Hãy đo thay vì phỏng đoán. curl báo cáo thời gian kết nối và thời gian nhận byte đầu tiên từ một endpoint thực:
curl -s -o /dev/null -w 'dns=%{time_namelookup}s connect=%{time_connect}s ttfb=%{time_starttransfer}s\n' \
https://api.kraken.com/0/public/Time
mtr -rwzc 100 api.kraken.comChạy lệnh này trên server ứng viên trước khi quyết định. Nếu connect là 0.180 giây, giá trị đó bao gồm thời gian phân giải DNS và thiết lập kết nối TCP; nó không cho biết bạn đang ở châu lục nào. Nếu connect là 0.004 giây và ttfb là 0.140 giây, phần chênh lệch bao gồm quá trình thiết lập TLS, truyền request, độ trễ mạng và thời gian xử lý của server. Việc đổi host có thể ảnh hưởng đến một số thành phần đó, vì vậy hãy so sánh kết quả đo từ các vị trí ứng viên.
Vậy khi nào host thực sự quan trọng? Khi bạn colocate hoặc cross-connect với venue và cạnh tranh về vị trí trong queue. Đây là một mô hình kinh doanh khác với ngân sách khác. Host cũng quan trọng khi chính code của bạn là bottleneck: một bot tính lại indicator trên toàn bộ lịch sử ở mỗi tick có thể tiêu tốn 200 mili giây CPU cho mỗi vòng lặp. Đây là độ trễ thực tế mà bạn có thể kiểm soát miễn phí. Hãy profile vòng lặp trước khi tìm server nhanh hơn.
Điều thực sự quan trọng ở host bạn chọn là vị trí địa lý, mạng ổn định và đủ memory để OOM killer không bao giờ phải can thiệp. Hãy tăng memory nếu bạn lưu lịch sử tick trong database cục bộ.
Checklist ngắn trước khi chạy production
systemctl is-enabled tradingbotin raenabledvà service vẫn chạy sausudo reboot.chronyc trackingbáo trạng thái đồng bộ, độ lệch giờ hệ thống dưới vài mili giây, đồng thời root delay và dispersion nằm trong ngân sách sai số thời gian của bạn.- API key có quyền giao dịch, không có quyền rút tiền và có IP allowlist nếu sàn hỗ trợ.
- Dừng process bằng
sudo systemctl kill -s SIGKILL tradingbotsẽ làm process khởi động lại sau thời gian trễRestartSecvà thời gian startup. - Hệ thống heartbeat monitor gửi cảnh báo cho bạn sau khoảng thời gian đã cấu hình và retry khi bạn cố ý dừng bot.
- Log có giới hạn dung lượng và filesystem root còn đủ chỗ trống trong
df -h.
Chạy toàn bộ quy trình trong sandbox của sàn hoặc ở paper mode trong 1 tuần trước khi dùng tiền thật. Mỗi mục ở trên sẽ fail ít nhất 1 lần trong tuần đó. Đó chính là mục đích của việc chạy thử trong 1 tuần.
FAQ
Bot giao dịch có cần server độ trễ thấp hoặc bare metal không?
Chỉ khi bạn cạnh tranh về tốc độ thực thi với các bên tự động khác tại cùng venue, trường hợp này thường cần colocation thay vì VPS đa dụng. Với bot bán lẻ, round trip chủ yếu bị chi phối bởi khoảng cách địa lý và thời gian xử lý của broker, nên hãy chọn server gần API endpoint rồi đo bằng curl và mtr trước khi trả tiền cho phần cứng nhanh hơn.
Bot giao dịch cần bao nhiêu RAM và CPU?
Hầu hết bot chạy một chiến lược đều bị giới hạn bởi network và thường idle giữa các event. Memory trở thành giới hạn khi bạn giữ lịch sử tick trong process hoặc chạy database cục bộ, nên hãy theo dõi free -h và journal để tìm thông báo OOM kill thay vì đoán.
Vì sao exchange API từ chối request với lỗi timestamp?
Timestamp của request nằm ngoài cửa sổ mà exchange chấp nhận; clock drift và độ trễ của request đều ảnh hưởng. Cài chrony, xác nhận chronyc tracking hiển thị offset nhỏ System time và trạng thái leap đã được đồng bộ, đồng thời kiểm tra cả root delay và dispersion. Đặt máy dùng UTC giúp thời gian hiển thị nhất quán nhưng không sửa được clock drift. Rotate API key không giải quyết được vấn đề về clock.
Làm cách nào để ngăn bot dừng qua đêm mà tôi không biết?
Chạy bot dưới systemd với Restart=always và StartLimitIntervalSec=0 để crash loop tiếp tục retry thay vì chạm start rate limit, sau đó thêm heartbeat do bot gửi ở cuối mỗi loop thành công. Cơ chế restart xử lý process. Heartbeat phát hiện trường hợp process vẫn sống nhưng bị treo.
Có thể chạy bot và hệ thống monitoring trên cùng một VPS không?
Có thể, và monitoring sẽ báo sai đúng vào ngày bạn cần nó nhất, vì một outage làm bot dừng cũng sẽ làm monitor dừng theo. Hãy đặt alerting trên một máy riêng, tốt nhất là khác provider hoặc region, và chỉ dùng server của bot cho bot cùng log của nó.