
jev-trader hoạt động như thế nào
jev-trader là bot giao dịch theo từng block dành cho sổ lệnh Kuru MON-USDC trên Monad. Ở mỗi block mới, bot đọc sổ lệnh hiện tại, yêu cầu một mô hình quyết định mua hoặc bán, rồi tạo một lệnh giới hạn chỉ đặt lệnh (post-only) ở phía đã chọn.
Lệnh được định giá vào bên trong giá khớp hiện tại QUOTE_INSIDE_TICKS tick. Nếu chênh lệch giá quá hẹp, giá sẽ được giới hạn ở mức giá khớp. Bot hủy các lệnh đang chờ trước đó và đăng lệnh thay thế trong một lần gọi Kuru batchUpdate.
Vì là lệnh chỉ đặt lệnh, lệnh được thiết kế để nằm trên sổ lệnh thay vì khớp ngay lập tức. Lệnh được khớp khi một người tham gia khác gửi lệnh taker vượt qua mức giá của lệnh đó. Điều này cho phép chiến lược kiếm chênh lệch giá thay vì trả chênh lệch giá, dù các rủi ro về khớp lệnh, tồn kho, gas và thị trường vẫn áp dụng.
Tính năng chính
- Một quyết định cho mỗi block Monad: Bot xử lý block mới nhất khoảng 300 ms một lần.
- Dữ liệu sổ lệnh Kuru theo thời gian thực: Một trình đọc tùy chỉnh giải mã
getL2Bookvà hợp nhất vault AMM vào sổ lệnh. - Hai tùy chọn mô hình: Mô hình mock mặc định sử dụng heuristic động lượng, trong khi
MODEL=jevbật mô hình Jev TypeSafe. - Chế độ chạy thử an toàn: Khi không có
PRIVATE_KEY, bot sử dụng sổ lệnh và giao dịch thị trường thực nhưng mô phỏng các lệnh và lần khớp của chính nó. - Thay thế lệnh chỉ đặt lệnh: Mỗi lần cập nhật, bot hủy các lệnh đang chờ đã biết và gửi một lệnh chỉ đặt lệnh mới trong cùng một batch.
- Theo dõi vị thế và P&L: Các sự kiện báo cáo vị thế, kết quả đã thực hiện và chưa thực hiện, chi phí gas, số lần khớp và các tổng số khác.
- Giám sát HTTP và SSE: Một máy chủ Bun nhỏ cung cấp snapshot mới nhất, tối đa 1.000 sự kiện block trong lịch sử và luồng sự kiện trực tiếp.
- Xác nhận bất đồng bộ: Giao dịch trực tiếp được gửi trên luồng xử lý chính, còn biên lai và các kiểm tra liên quan được xử lý sau.
Kiến trúc dự án
Cây mã nguồn tách biệt việc tiếp nhận block, truy cập thị trường, đánh giá mô hình, logic giao dịch và giám sát:
src/config.tstải cấu hình môi trường.src/chain.tsnhận các cập nhậtnewHeadsqua WebSocket, sử dụng polling dự phòng và chỉ giữ lại block mới nhất.src/book.tsđọc và giải mã sổ lệnh bằng mộteth_call.src/market.tsxử lý việc đọc sổ lệnh Kuru, nạp tiền ký quỹ, nonce cục bộ, cập nhật theo batch và xác nhận bất đồng bộ.src/model.tsđịnh nghĩa giao diện mô hình và cung cấpJevModelcùngMockModel.src/trader.tschạy vòng lặp giao dịch và theo dõi vị thế cùng P&L.src/server.tscung cấp snapshot, lịch sử và Server-Sent Events bằngBun.serve.
Cài đặt và thiết lập
1. Chuẩn bị tệp môi trường
Từ thư mục repository, sao chép cấu hình mẫu:
cp .env.example .envKiểm tra tệp .env vừa tạo trước khi khởi động ứng dụng. Hành vi quan trọng nhất được kiểm soát bởi việc PRIVATE_KEY có tồn tại hay không.
Để trống
PRIVATE_KEYtrong lần chạy đầu tiên. Ứng dụng sẽ chạy thử với dữ liệu thị trường thực mà không phát tán các lệnh của chính nó.
2. Cài đặt các dependency
Dự án sử dụng Bun để quản lý và thực thi dependency:
bun install3. Khởi động trader
bun run startVới cấu hình mặc định, mô hình động lượng mock đóng vai trò thay thế cho suy luận. Sau đó, máy chủ cung cấp trạng thái trader và luồng sự kiện thông qua các endpoint HTTP.
Chọn mô hình ra quyết định
Sử dụng mô hình mock mặc định
Mô hình mock mặc định phù hợp để kiểm thử toàn bộ pipeline mà không gọi Jev. Mô hình đưa ra quyết định bằng heuristic động lượng, giúp bạn xác thực việc đọc sổ lệnh, lệnh mô phỏng, lần khớp, hạch toán và truyền sự kiện.
Bật mô hình Jev
Để sử dụng Jev, hãy cấu hình các giá trị sau trong .env:
MODEL=jev
TYPESAFE_AI_API_KEY=your_api_keyỞ mỗi block, mô hình đã chọn được hỏi về biến động dự kiến trong HORIZON_BLOCKS. Giá trị mặc định là 100 block, tương đương khoảng 30 giây theo README của dự án.
Quyết định thông thường là buy hoặc sell. Kết quả hold không đại diện cho chiến lược thứ ba của mô hình: nó chỉ xuất hiện khi mô hình bỏ lỡ thời hạn của block hiện tại. Trong trường hợp đó, decision.late là true và không có lệnh nào được đăng cho block đó.
Chạy an toàn ở chế độ chạy thử
Khi PRIVATE_KEY chưa được cấu hình, jev-trader không gửi giao dịch trực tiếp. Bot vẫn đọc sổ lệnh Kuru thực và tạo ra các quyết định thực từ mô hình.
Báo giá mô phỏng có status: "sim". Báo giá nằm trên sổ lệnh trong một block và chỉ được xem là đã khớp khi một giao dịch thị trường thực vượt qua mức giá của nó. Lần khớp kết quả có simulated: true.
Chế độ này hữu ích để kiểm tra:
- Các cập nhật sổ lệnh có đến ổn định hay không.
- Độ trễ của mô hình có nằm trong ngân sách của block hay không.
- Báo giá sẽ được khớp thường xuyên đến mức nào.
- Vị thế và P&L thay đổi như thế nào theo các quy tắc mô phỏng.
- Dashboard hoặc một client SSE khác có xử lý đúng mọi loại sự kiện hay không.
Kiểm tra các endpoint HTTP
Một instance chạy thử đã triển khai sử dụng mô hình mock hiện có tại https://jev-trader-production.up.railway.app.
Đọc ảnh chụp mới nhất
Endpoint gốc báo cáo mô hình đang hoạt động, số dư ví, trạng thái chạy thử và sự kiện block gần nhất:
curl https://jev-trader-production.up.railway.app/Đọc lịch sử gần đây
Endpoint lịch sử trả về 1.000 sự kiện block gần nhất:
curl https://jev-trader-production.up.railway.app/historyTheo dõi luồng SSE trực tiếp
Sử dụng curl -N để giữ kết nối mở và hiển thị các sự kiện khi chúng đến:
curl -N https://jev-trader-production.up.railway.app/eventsLuồng gửi một sự kiện snapshot khi client kết nối, sau đó là một sự kiện block cho mỗi block được xử lý. Biên nhận giao dịch trực tiếp tạo ra các bản cập nhật quote, còn các lần khớp lệnh được phát hiện tạo ra sự kiện fill.
Tìm hiểu sự kiện block
Sự kiện block kết hợp trạng thái thị trường, quyết định của mô hình, ý định báo giá mới, thanh khoản đang chờ, thông tin vị thế và các tổng số lũy kế. Ví dụ rút gọn:
{
"block": 105488269,
"mid": 0.022636,
"bestBid": 0.022628,
"bestAsk": 0.022644,
"spreadBps": 7.07,
"decision": {
"action": "buy",
"probabilities": { "buy": 0.77, "sell": 0.23, "hold": 0 },
"upIn10": 0.77,
"latencyMs": 81,
"late": false
},
"quote": {
"side": "buy",
"price": 0.022629,
"size": 200,
"status": "sent",
"capped": false
}
}mid,bestBidvàbestAskmô tả thị trường được quan sát.spreadBpsbiểu thị spread hiện tại theo điểm cơ bản.decision.actionlà hướng được mô hình lựa chọn.decision.probabilitiesgiữ nguyên xác suất mua và bán của mô hình.upIn10bằng với xác suất mua.decision.latencyMsbáo cáo độ trễ đánh giá mô hình.quotemô tả lệnh được thử trong block này.quote.cancelxác định các lệnh đang chờ trước đó được đưa vào để hủy.restingghi nhận quy mô bid và ask mà bot biết sau khi cập nhật.positionbáo cáo hướng, quy mô, giá vào lệnh và kết quả chưa thực hiện.totalscộng dồn số block, quyết định, báo giá, lần khớp, lần đảo chiều, block trễ, chi phí mô hình, gas và P&L.
Giới hạn vị thế và nguồn vốn
Nếu giới hạn vị thế ngăn cản phía được yêu cầu hoặc tiền ký quỹ trực tiếp không đủ, báo giá sẽ được đặt ở phía đối diện. Trong trường hợp này, quote.capped là true. Xác suất ban đầu của mô hình vẫn được giữ nguyên, cho phép các bên sử dụng phân biệt dự đoán của mô hình với phía thực sự được báo giá.
Tìm hiểu xác nhận báo giá trực tiếp
Các lệnh gửi trực tiếp được thực hiện mà không chờ kết quả để vòng lặp giao dịch không phải đợi biên nhận. Vì vậy, sự kiện block ban đầu chứa một ý định với status: "sent".
gasMon được báo cáo được tính bằng giới hạn gas nhân với tổng phí cơ sở và phí ưu tiên được biết gần nhất. Dự án ghi chú rằng Monad tính phí theo giới hạn gas, vì vậy đây được xem là chi phí thực tế dù giao dịch thành công hay bị hoàn nguyên.
Biên nhận thường đến sau một hoặc hai block và tạo ra một sự kiện quote riêng:
event: quote
data: {
"block": 105488269,
"quote": {
"status": "placed",
"orderId": 100295812,
"gasMon": 0.0357
}
}Một báo giá trực tiếp có thể chuyển sang một trong các trạng thái sau:
placed: Giao dịch thành công và bao gồm mã lệnh.reverted: Sổ lệnh đã di chuyển qua mức giá được gửi trước khi được đưa vào block, hoặc yêu cầu hủy nhắm đến một lệnh đã được khớp.lost: Không tìm thấy biên nhận sau 10 block.
Tìm hiểu sự kiện khớp lệnh
Các lần khớp không xảy ra trong giao dịch đặt lệnh của chính bot. Chúng xảy ra khi lệnh taker của một nhà giao dịch khác khớp vào lệnh đang chờ. Bot phát hiện log Trade tương ứng thông qua cùng quy trình polling eth_getLogs cung cấp thông tin thị trường cho mô hình.
event: fill
data: {
"block": 105488271,
"fill": {
"side": "buy",
"size": 200,
"price": 0.022629,
"txHash": "0x…",
"orderId": 100295812,
"simulated": false
}
}txHash của lần khớp thuộc về giao dịch taker. Khi một lần khớp được xử lý, luồng cũng phản ánh dữ liệu vị thế đã cập nhật, P&L đã thực hiện và tổng số lần khớp lũy kế.
Chuyển sang giao dịch trực tiếp
Thiết lập PRIVATE_KEY sẽ chuyển ứng dụng từ chế độ chạy thử sang gửi giao dịch trực tiếp. Trước khi thực hiện, hãy xác minh cấu hình môi trường, nguồn tiền ký quỹ, giới hạn vị thế, quy mô giao dịch, việc đặt báo giá, giới hạn phí và độ tin cậy của RPC.
Chế độ trực tiếp gửi các lệnh Kuru post-only thực và phát sinh chi phí gas thực. Trước tiên hãy kiểm thử toàn bộ quy trình ở chế độ chạy thử và sử dụng các giới hạn thận trọng khi bật khóa đã được cấp vốn.
Các cài đặt chính liên quan đến chiến lược được dự án mô tả gồm:
TRADE_SIZE_MONcho quy mô lệnh.QUOTE_INSIDE_TICKScho vị trí đặt lệnh so với mức giá hiện hành.HORIZON_BLOCKScho khoảng dự đoán của mô hình.MAX_FEE_GWEIcho giới hạn phí giao dịch type-2.READ_RPC_URLcho việc đọc sổ lệnh.RPC_URLcho việc gửi giao dịch.
Cách bot đáp ứng ngân sách 300 ms
Đường xử lý chính được thiết kế với đúng hai lượt khứ hồi RPC:
- Một lệnh
eth_callđọc sổ lệnh hiện tại thông quaREAD_RPC_URL. - Một lệnh
eth_sendRawTransactiongửi bản cập nhật đã ký thông quaRPC_URLvà trả về ngay khi được chấp nhận.
Vòng lặp này cố ý tránh một số thao tác có thể tốn nhiều chi phí:
- Không gọi
eth_estimateGascho từng block; giới hạn gas được cố định hoặc tính một lần khi khởi động. - Không dùng
eth_sendRawTransactionSync, vốn chờ đến khi giao dịch được đề xuất. - Không tra cứu giá gas trên đường xử lý chính; các giao dịch sử dụng thiết lập phí tĩnh type-2 với phí ưu tiên 2 gwei và giới hạn
MAX_FEE_GWEI. - Không chờ receipt trong vòng lặp quyết định.
- Không kiểm tra vault hoặc phí nội tuyến, vì có thể làm chậm lệnh.
README ghi nhận benchmark dry-run với mô hình giả lập đạt khoảng 18 ms p50 cho lần đọc sổ lệnh và 100 ms p50 cho toàn bộ vòng lặp, trong đó khoảng 80 ms đến từ phần thay thế suy luận giả lập.
Kiểm thử và benchmark
Benchmark trình đọc sổ lệnh tùy chỉnh
Chạy benchmark đi kèm để so sánh trình đọc tùy chỉnh với SDK về độ chính xác và độ trễ:
bun run scripts/bench-read.tsXác minh mã hóa giao dịch ngoại tuyến
Script mã hóa dry-run ký một lệnh mua và một lệnh bán mà không phát chúng, sau đó kiểm tra calldata được tạo có khớp với SDK hay không:
bun run scripts/dry-encode.tsĐiều này đặc biệt hữu ích trước khi bật chế độ live, vì module thị trường tối ưu hóa sử dụng calldata batchUpdate được mã hóa thủ công.
Mẹo vận hành nâng cao
- Theo dõi các quyết định trễ: Theo dõi
decision.latevàtotals.lateBlocks. Phản hồi mô hình đến trễ nghĩa là không có lệnh nào được đăng cho block đó. - Tách ý định khỏi xác nhận: Không xem
status: "sent"là một lệnh đã được đặt. Hãy chờ sự kiệnquoteđến sau với trạng tháiplaced,revertedhoặclost. - Theo dõi các báo giá bị giới hạn: Khi
cappedlà true, hãy so sánh phía đã gửi với các xác suất mô hình không thay đổi để hiểu vì sao quá trình thực thi lệch khỏi tín hiệu. - Sử dụng snapshot SSE: Các client giám sát mới nên khởi tạo từ sự kiện
snapshotđầu tiên, sau đó áp dụng các cập nhật block, quote và fill tiếp theo. - Đo lường cả hai đường RPC: Việc đọc chậm làm chậm quyết định, trong khi việc gửi chậm làm giảm khả năng quote được thực hiện trước khi thị trường biến động.
- Tính đến giới hạn gas bị tính phí: Một giao dịch bị revert vẫn có thể phát sinh chi phí đáng kể, vì vậy hãy theo dõi
gasMon,gasUsdvà tổng số lần revert thay vì chỉ đánh giá các fill. - Xác thực bằng bản in dry-run: Các fill mô phỏng phụ thuộc vào các giao dịch thực tế chạm mức giá lệnh, khiến chế độ dry-run thực tế hơn giả định khớp lệnh ngay lập tức, nhưng vẫn khác với vị trí thực tế trong hàng đợi và quá trình thực thi.
Kết luận
jev-trader kết hợp trình đọc sổ lệnh Kuru trực tiếp, mô hình quyết định giả lập hoặc Jev, cơ chế gửi giao dịch Monad được tối ưu hóa, tính toán vị thế và dịch vụ giám sát SSE. Hãy khởi động mà không có PRIVATE_KEY, kiểm tra snapshot và luồng sự kiện, benchmark đường xử lý quan trọng, đồng thời xác minh việc mã hóa trước khi cân nhắc thực thi trực tiếp. Trong môi trường production, hãy cùng lúc theo dõi xác nhận, các block trễ, giới hạn, giao dịch revert, tồn kho, P&L và chi phí gas.
