📝

Draft article

This draft is visible to admins and superusers only. Sign in with an authorized account.

← Quay lại danh sách bài viết
July 24, 2026
5 phút đọc

Bên trong lát cắt: chiến thuật child-order giữa bộ lập lịch và sàn giao dịch

Bên trong lát cắt: chiến thuật child-order giữa bộ lập lịch và sàn giao dịch
#execution
#child orders
#order tactics
#queue position
#maker-taker
#iceberg orders
#microstructure
#python

Một quỹ đạo Almgren-Chriss đưa cho bạn một con số: bán 4,2 BTC trong năm phút tới. Một lịch trình VWAP đưa cho bạn con số tương tự với một cách lý giải khác. Không cái nào nói gì về việc điều gì xảy ra tiếp theo — liệu 4,2 BTC đó có đánh thẳng vào sổ lệnh như một lệnh có thể khớp ngay, nằm ở mức giá tốt nhất để hưởng phí maker, ẩn sau một khối hiển thị 0,3 BTC, hay bị định giá lại mười một lần để đuổi theo một mức giá đang trôi dạt. Lớp quyết định thứ hai đó chính là lớp chiến thuật, và trên các sổ lệnh crypto bị chi phối bởi phí giao dịch, nó thường xuyên tác động đến PnL trên mỗi lát cắt nhiều hơn cả việc chọn bộ lập lịch ở phía trên. Ngân sách theo từng khoảng thời gian của bộ lập lịch chỉ chênh nhau vài bps tác động giá giữa TWAP và một Almgren-Chriss được hiệu chỉnh tốt, tính trên toàn bộ lệnh mẹ; trong khi việc trả phí taker cho những lát cắt lẽ ra có thể làm maker, hay để mất vị trí hàng đợi vì định giá lại bất cẩn, tốn kém ngần ấy chỉ trong một giờ. Bài viết này nói về lớp mà ai cũng vận hành nhưng gần như không ai viết ra: máy trạng thái quyết định cách mỗi child order chạm vào sổ lệnh.

Hai lớp, một giao diện hẹp

Cuốn Market Microstructure in Practice (bản in lần 2, 2018) của Lehalle và Laruelle hệ thống hóa điều mà mọi bàn thực thi (execution desk) đều đi đến: một lớp chiến lược (bộ lập lịch) phân bổ khối lượng theo thời gian, và một lớp chiến thuật (microtrader) triển khai từng phần phân bổ đó trên sổ lệnh thực. Sự phân tách này không mang tính hình thức — hai lớp này sống trên những đồng hồ khác nhau và dùng dữ liệu khác nhau. Lớp chiến lược suy nghĩ theo phút, tiêu thụ dự báo biến động và khối lượng, và giải một bài toán biến phân. Lớp chiến thuật suy nghĩ theo mili-giây đến giây, tiêu thụ các delta L2 và ước lượng hàng đợi, và giải một chuỗi các bài toán dừng nhỏ.

Kiến trúc thực thi hai lớp: bộ lập lịch truyền xuống ngân sách lát cắt và mức độ khẩn cấp, lớp chiến thuật trả về khớp lệnh và độ hao hụt lên trên

Giao diện giữa chúng nên hẹp. Truyền xuống, với mỗi lát cắt kk:

  • ngân sách qkq_k — khối lượng cần thực thi trong khoảng thời gian này (chính là nkn_k của Almgren-Chriss, hoặc phần gia tăng theo đường cong khối lượng của VWAP);
  • cửa sổ τk\tau_k — độ dài của lát cắt;
  • mức độ khẩn cấp — với Almgren-Chriss, ứng viên tự nhiên là κ=λσ2/η\kappa = \sqrt{\lambda\sigma^2/\eta}, vốn đã nén mức ngại rủi ro, biến động và thanh khoản vào một tốc độ duy nhất; với bộ lập lịch VWAP, đó thường là khoảng cách so với dải mục tiêu ("chúng ta đang chậm hơn 1,8% so với đường cong mục tiêu").

Truyền lên: các lệnh khớp kèm dấu thời gian và phí, phần còn lại chưa khớp, và độ hao hụt thực thi (implementation shortfall) ở cấp lát cắt được đo so với giá giữa (mid) tại thời điểm lát cắt bắt đầu. Điều cuối cùng này rất quan trọng: tham số tác động giá η\eta của bộ lập lịch đã định giá sẵn chi phí lẽ ra phải có khi đòi hỏi thanh khoản với tốc độ qk/τkq_k/\tau_k. Toàn bộ nhiệm vụ của lớp chiến thuật gói gọn trong một câu: hiện thực hóa các lệnh khớp với chi phí tốt hơn mức mà η\eta ngụ ý, mà không để lộ sự tồn tại của lệnh mẹ. Nếu độ hao hụt lát cắt đo được của bạn liên tục vượt trội hơn chi phí mô hình, η\eta đã hiệu chỉnh có thể giảm xuống, bộ lập lịch tăng tốc, và toàn bộ hệ thống được cải thiện. Nếu bạn không thể đo độ hao hụt lát cắt tách biệt khỏi chi phí lịch trình, bạn không thể tinh chỉnh được lớp nào cả — bạn chỉ có một con số mờ nhòe và hai núm điều chỉnh.

Chính sách xử lý phần dư cũng là một phần của hợp đồng này. Khi một lát cắt kết thúc mà vẫn còn khối lượng chưa khớp, hoặc lớp chiến thuật buộc phải hoàn tất (khớp thẳng phần còn lại — mặc định khi mức khẩn cấp cao do deadline), hoặc trả phần đó lại cho bộ lập lịch để tái phân bổ vào các lát cắt còn lại (chấp nhận được ở giai đoạn đầu của một lịch trình κ\kappa thấp, nhưng độc hại khi gần deadline, nơi việc tái phân bổ âm thầm cộng dồn thành một lát cắt cuối cùng khổng lồ).

Bậc thang leo thang: thụ động trước, quyết liệt theo deadline

Kết quả lâu đời nhất trong lĩnh vực này là Harris (1998), "Optimal dynamic order submission strategies in some stylized trading problems" (Financial Markets, Institutions & Instruments 7(2)): đối với một trader thanh khoản phải hoàn tất giao dịch trước một deadline, chiến lược tối ưu mang tính động — đứng trong sổ lệnh với lệnh giới hạn khi thời gian còn rẻ, định giá lại tiến về phía thị trường khi deadline đến gần, và khớp thẳng vào lúc cuối. Mọi engine chiến thuật trong sản xuất đều là hậu duệ của hình mẫu này: đặt lệnh ở mức giá tốt nhất, chờ hết hạn, leo thang, khớp thẳng. Điều mà các biểu phí hiện đại và động lực hàng đợi bổ sung thêm là phép tính chính xác về thời điểm nào mỗi bước chuyển đổi được kích hoạt.

Điểm hòa vốn để khớp thẳng

Xét trên mỗi đơn vị, giá tính tương đối so với mid hiện tại, cho một lệnh mua. Khớp thẳng ngay bây giờ tốn nửa spread cộng phí taker:

ctake=s2+ft.c_{\text{take}} = \frac{s}{2} + f_t.

Đặt lệnh ở giá mua (bid) trong một cửa sổ τ\tau khớp với xác suất pp; một lệnh khớp thu được nửa spread và trả phí maker fmf_m (âm nếu là rebate). Nếu không khớp, phải khớp thẳng vào cuối cửa sổ sau khi giá đã, trung bình, di chuyển bất lợi cho bạn một khoảng δ(τ)=E[dịch chuyển mid baˆˊt lợikhoˆng khớp]>0\delta(\tau) = E[\,\text{dịch chuyển mid bất lợi} \mid \text{không khớp}\,] > 0 — luôn dương một cách chặt chẽ, bởi vì việc không khớp và sự dịch chuyển bất lợi là cùng một sự kiện: lệnh bid của bạn không được khớp khi thị trường trôi ra xa nó. Chi phí kỳ vọng khi đặt lệnh:

cpost=p(s2+fm)+(1p)(s2+ft+δ).c_{\text{post}} = p\left(-\frac{s}{2} + f_m\right) + (1-p)\left(\frac{s}{2} + f_t + \delta\right).

Đặt lệnh tốt hơn khớp thẳng khi và chỉ khi

  p  >  p\*=δΠ+δ,Π=s+ftfm  \boxed{\; p \;>\; p^\* = \frac{\delta}{\Pi + \delta}, \qquad \Pi = s + f_t - f_m \;}

trong đó Π\Piphần thưởng — toàn bộ khoản lợi round-trip bạn thu được khi làm maker thay vì taker: spread cộng chênh lệch phí. Đây chính là điểm hòa vốn chi phối toàn bộ kinh tế học maker-taker của việc thực thi, thu gọn về một lát cắt duy nhất.

Ví dụ số, BTCUSDT perp: mid $100.000, spread một tick s = \0,10,phıˊkiuVIP0maker2bps/taker5bps,ne^n, phí kiểu VIP0 maker 2 bps / taker 5 bps, nên f_m = $20,, f_t = $50mo^~iBTC.Pha^ˋnthưởngmỗi BTC. Phần thưởng\Pi = 0,10 + 50 - 20 = $30,10 \approx 3bpslưuyˊspreadga^ˋnnhưkho^ngđoˊnggoˊpgıˋ;tre^ncaˊccpcryptochıˊnhvispreadhp,pha^ˋnthưởngchıˊnhlaˋche^nhlchphıˊ.La^ˊybie^ˊnđộngngaˋy3 bps — lưu ý spread gần như không đóng góp gì; trên các cặp crypto chính với spread hẹp, phần thưởng *chính là* chênh lệch phí. Lấy biến động ngày 3% (\sigma_{\text{day}} = $3.000)vaˋ) và \delta(\tau) \approx 0,6,\sigma_{\text{day}}\sqrt{\tau/86400}$ (con số 0,6 là một mức chiết khấu do lựa chọn bất lợi mà bạn nên tự hiệu chỉnh, chứ không nên tin theo):

  • τ=10\tau = 10 s: \delta \approx \19,ne^n, nên p^* = 19/49 \approx 0,39$. Chỉ đặt lệnh nếu bạn kỳ vọng ít nhất 39% khớp trong vòng 10 giây.
  • τ=60\tau = 60 s: \delta \approx \47,ne^n, nên p^* = 47/77 \approx 0,61$.
  • Với rebate maker 1 bp thay vì phí 2 bp (f_m = -\10):): \Pi = $60,10,vaˋngưỡng10sgimxuo^ˊngcoˋn, và ngưỡng 10 s giảm xuống còn p^* \approx 0,24$.

Hai sự thật mang tính cấu trúc lộ ra ở đây. Thứ nhất, δ\delta tăng theo τ\sqrt{\tau} trong khi Π\Pi không đổi, nên p\*(τ)1p^\*(\tau) \to 1: sự kiên nhẫn có một hạn chót cứng, và bộ đếm giờ hết hạn không phải là một quy tắc kinh nghiệm mà là điểm giao nhau của hai đường cong — p(τ)p(\tau) ước lượng của bạn (lõm, bão hòa dần khi hàng đợi phía trước bạn cạn đi) so với p\*(τ)p^\*(\tau) (tăng dần). Thứ hai, bậc phí bạn giao dịch trên đó vật lý dịch chuyển cả bậc thang này. Một lần nâng bậc cắt giảm phí taker khiến chiến thuật tối ưu của bạn trở nên quyết liệt hơn — một mối liên hệ mà hầu hết mọi người chỉ phát hiện ra khi thống kê khớp lệnh của họ thay đổi sau khi được nâng bậc VIP.

Cont và Kukanov, "Optimal order placement in limit order markets" (Quantitative Finance 17(1), 2017; arXiv 2012), chứng minh chặt chẽ điều này trong một chu kỳ: tối thiểu hóa chi phí kỳ vọng khi thực thi SS đơn vị chia giữa lệnh thị trường và lệnh giới hạn (trên một hoặc nhiều sàn), với một khoản phạt cho phần thiếu hụt. Nghiệm cho một sàn duy nhất là tường minh và có cấu trúc kiểu newsvendor: kích thước lệnh giới hạn tối ưu được dẫn dắt bởi phân phối của dòng ra khỏi hàng đợi (queue outflow) — đặt lệnh với kích thước lớn khi hàng đợi phía trước nhỏ so với dòng ra kỳ vọng, và bù đắp rủi ro đuôi bằng lệnh thị trường. Phần mở rộng đa sàn của họ được giải bằng xấp xỉ ngẫu nhiên và là cốt lõi trí tuệ của logic phân bổ thụ động trong mọi smart order router. Cách đọc thực tiễn cho một engine chiến thuật: pp trong điểm hòa vốn ở trên không phải là hằng số — nó là một hàm của vị trí hàng đợi và tốc độ cạn hàng đợi, đó là lý do vì sao lớp chiến thuật phải tiêu thụ bộ ước lượng vị trí hàng đợi như một đầu vào hạng nhất.

Dòng thời gian lát cắt cho thấy sự leo thang từ đặt lệnh thụ động ở giá tốt nhất, qua định giá lại, đến khớp thẳng phần còn lại tại deadline

Tham số khẩn cấp nén toàn bộ bậc thang này lại. κ\kappa cao từ bộ lập lịch có nghĩa là thời gian đặc trưng θ=1/κ\theta = 1/\kappa ngắn: các cửa sổ thu hẹp, p\*p^\* tăng, và engine bỏ qua thẳng đến bước khớp — điều này đúng, vì bộ lập lịch đã tuyên bố rằng rủi ro tồn kho lấn át khoản tiết kiệm phí. κ\kappa thấp kéo dài giai đoạn thụ động. Lớp chiến thuật không bao giờ nên tự suy ra lại mức khẩn cấp từ góc nhìn riêng của nó về thị trường; đó là nhiệm vụ của bộ lập lịch, và việc lặp lại nó tạo ra hai bộ điều khiển bất đồng nhau.

Định giá lại mà không đốt mất vị trí hàng đợi của bạn

Một khi đã đặt lệnh, giá sẽ trôi dạt. Đuổi theo nó một cách ngây thơ — hủy, đặt lại ở mức giá tốt nhất mới, lặp lại — chính là cách các engine chiến thuật âm thầm phá hủy chính xác suất khớp lệnh đã biện minh cho việc đặt lệnh ngay từ đầu. Vị trí hàng đợi là một tài sản có giá trị bằng tiền đo được được (Moallemi và Yuan, 2016, định giá nó: các vị trí đầu hàng đợi trong các sổ lệnh FIFO thanh khoản tốt có giá trị bằng một phần đáng kể của spread), và mỗi quyết định định giá lại là một giao dịch: bán vị trí hàng đợi hiện tại của bạn, mua một vị trí ở cuối hàng đợi tại một mức giá khác. Giao dịch này chỉ đáng thực hiện khi giá trị của mức giá mới vượt quá giá trị của mức cũ cộng với chi phí gửi lệnh. Điều đó đòi hỏi phải biết chính xác việc amend trên mỗi sàn thực sự làm gì với vị trí của bạn trong hàng đợi — và câu trả lời khác nhau rất nhiều giữa các sàn.

CME Globex ghi rõ ngữ nghĩa rõ ràng nhất: giảm khối lượng lệnh giữ nguyên ưu tiên thời gian; tăng khối lượng hoặc đổi giá sẽ đẩy bạn xuống cuối hàng đợi. Đây là mô hình tham chiếu — giảm khối lượng là miễn phí, mọi thứ khác đều bị xếp hàng lại.

Binance spot trước đây chỉ cung cấp POST /api/v3/order/cancelReplace — một thao tác hủy-cộng-đặt-mới trông có vẻ nguyên tử nhưng thực chất không mang tính giao dịch tường minh. Có hai chế độ: STOP_ON_FAILURE (mặc định — nếu hủy thất bại, sẽ không có lệnh mới) và ALLOW_FAILURE (đặt lệnh mới ngay cả khi hủy thất bại — chào mừng đến với tình trạng phơi nhiễm kép ngoài ý muốn). Thao tác này có thể thành công một phần, được báo hiệu bằng HTTP 409, nên OMS của bạn phải đối soát cả hai nhánh một cách độc lập; và lệnh mới luôn bắt đầu một vòng đời hàng đợi mới hoàn toàn. Rồi đến năm 2025 Binance ra mắt Order Amend Keep Priority (PUT /api/v3/order/amend/keepPriority): giảm khối lượng tại chỗ, giữ nguyên ưu tiên thời gian, với chi phí bằng không về số lệnh chưa khớp. Ngữ nghĩa của CME, mười lăm năm sau — và chỉ ở nửa phần giảm khối lượng.

Binance USDT-M futures có một endpoint modify thực sự (PUT /fapi/v1/order), nhưng hãy đọc kỹ phần chữ nhỏ: chỉ áp dụng cho lệnh LIMIT, cả pricequantity đều phải được gửi, và "các lệnh đã sửa sẽ bị xếp lại thứ tự trong hàng đợi khớp lệnh" — tài liệu cam kết rõ không giữ ưu tiên ngay cả với việc giảm khối lượng thuần túy. Hãy coi mọi lần modify trên futures là một lần reset hàng đợi mà tình cờ tiết kiệm cho bạn một tin nhắn và giữ nguyên ID lệnh. Có một điểm cần lưu ý: sửa một lệnh GTX (post-only) sang mức giá sẽ gây khớp chéo sẽ khiến lệnh bị hủy, chứ không phải bị từ chối-và-giữ-nguyên — một cách triển khai peg không kiểm tra điều này thỉnh thoảng sẽ tự amend mình đến chỗ biến mất.

OKX cung cấp POST /api/v5/trade/amend-order (newPx, newSz, với cxlOnFail để tự động hủy khi amend thất bại). Đây là một tin nhắn duy nhất, giữ nguyên ID lệnh, và xác nhận bất đồng bộ — sCode = 0 có nghĩa là "yêu cầu đã được chấp nhận", còn kết quả thực tế đến qua kênh orders dưới dạng amendResult. Điều mà tài liệu công khai không hề nói rõ là hành vi ưu tiên hàng đợi. Đừng lấp đầy khoảng trống tài liệu đó bằng sự lạc quan. Hãy đo lường nó: đặt hai lệnh đánh dấu tại một mức giá yên tĩnh, amend giảm khối lượng của một trong hai, và theo dõi xem cái nào khớp trước qua vài trăm lần thử. Cho đến khi bạn có dữ liệu đó, giả định thận trọng — bất kỳ thay đổi giá nào cũng xếp hàng lại bạn ở mọi nơi, giảm khối lượng chỉ giữ ưu tiên ở nơi được ghi rõ ràng — là giả định duy nhất có thể bảo vệ được.

Ma trận các thao tác amend so với từng sàn, cho thấy thao tác nào giữ ưu tiên hàng đợi và thao tác nào làm reset nó

Hệ quả về chính sách:

  1. Trễ (hysteresis), không phải bám sát (pegging). Chỉ định giá lại khi mức giá tốt nhất đã trôi dạt hơn một dải bb tick so với giá đang treo của bạn. Trong dải này, sự trôi dạt là nhiễu và vị trí hàng đợi của bạn đáng giá hơn một tick cải thiện giá. Một dải khởi điểm hợp lý là 1–3 tick tỷ lệ theo biến động ngắn hạn; dải đúng khiến việc định giá lại biên trung lập về EV: VnewVcur=cmsgV_{\text{new}} - V_{\text{cur}} = c_{\text{msg}}, với VV là giá trị hàng đợi kiểu Moallemi-Yuan và cmsgc_{\text{msg}} là giá bóng (shadow price) của giới hạn tốc độ lệnh của bạn. Các thao tác amend/cancel-replace tiêu tốn ngân sách tốc độ lệnh trên cả hai sàn Binance; một engine chiến thuật bám sát từng tick sẽ khiến phần còn lại của hệ thống bạn đói năng lực tin nhắn.
  2. Amend giảm, không bao giờ cancel-repost giảm. Khi bộ lập lịch cắt ngân sách lát cắt giữa chừng (một bộ lập lịch POV thấy khối lượng cạn đi, một lần giải lại Almgren-Chriss sau khi khớp một phần), hãy dùng đường giữ ưu tiên ở nơi nó tồn tại. Đây là bữa trưa miễn phí duy nhất trong toàn bộ lớp này.
  3. Mức khẩn cấp bất đối xứng khi định giá lại. Định giá lại về phía thị trường (đuổi theo) reset hàng đợi của bạn ở một mức giá tệ hơn — nó chỉ nên được kích hoạt từ logic leo thang, theo bộ đếm giờ của nó. Định giá lại ra xa (thị trường đến với bạn) là một món quà, chỉ nên nhận qua dải thụ động, vì mức giá hiện tại của bạn sắp khớp rồi.

Iceberg, kích thước hiển thị, và điều gì làm lộ ý định của bạn

Kích thước hiển thị là quyết định thứ ba, và nó là một sự đánh đổi hai chiều thực sự, không phải một nút ẩn danh miễn phí. Bằng chứng thực nghiệm:

  • Frey và Sandås ("The Impact of Iceberg Orders in Limit Order Books", bài working paper 2009; Quarterly Journal of Finance, 2017), trên dữ liệu Xetra: các lệnh iceberg chiếm 9,3% khối lượng gửi và 15,9% khối lượng khớp, có kích thước gấp 12–20 lần lệnh giới hạn thông thường, và — điểm mấu chốt — khi các bên tham gia khác phát hiện ra một lệnh iceberg, họ phản ứng bằng các lệnh thị trường khớp tương ứng. Kích thước ẩn, một khi bị suy luận ra, thu hút dòng lệnh: việc tìm kiếm thanh khoản ẩn hoạt động theo cả hai chiều.
  • Bessembinder, Panayides và Venkataraman ("Hidden liquidity: an analysis of order exposure strategies in electronic stock markets", JFE 94(3), 2009), trên Euronext Paris, nơi các lệnh ẩn chiếm 44% khối lượng mẫu: việc ẩn giúp giảm độ hao hụt thực thi nhưng cũng giảm xác suất khớp toàn bộ và kéo dài thời gian hoàn tất. Sự phơi bày mua được các lệnh khớp và phải trả giá cho chúng bằng tác động giá; lựa chọn này được sử dụng đúng như lý thuyết dự đoán — lệnh quyết liệt phơi bày để thu hút đối tác, khối lượng kiên nhẫn thì ẩn đi.
  • Esser và Mönch ("The navigation of an iceberg", Finance Research Letters 4(2), 2007) coi kích thước đỉnh hiển thị (peak size) như một bài toán tối ưu hóa: hiển thị lớn hơn khớp nhanh hơn, hiển thị nhỏ hơn lộ ít hơn, và điểm tối ưu nằm ở giữa.

Về mặt cơ chế trước tiên, vì nó ràng buộc bài toán tối ưu: trên hầu hết mọi sàn hỗ trợ iceberg gốc (Binance spot qua icebergQty, OKX qua các lệnh thuật toán iceberg), mỗi lần nạp lại phần đỉnh hiển thị đều vào cuối hàng đợi tại mức giá đó. Vì vậy một lệnh iceberg không phải là "một lệnh với kích thước ẩn" — nó là một chuỗi các lệnh nhỏ, mỗi lệnh phải chịu toàn bộ thời gian chờ hàng đợi, được kích hoạt tự động. Ở điểm hòa vốn phí đã nói ở trên, điều này quan trọng: pp hiệu dụng trên mỗi đỉnh là xác suất khớp ở cuối hàng đợi, không phải của vị trí ban đầu của bạn. Các hàng đợi sâu trừng phạt các đỉnh nhỏ hai lần — khớp chậm hơn và nhiều lượt nạp lại hơn đồng nghĩa với nhiều lựa chọn bất lợi hơn.

Rồi đến vấn đề lộ tín hiệu. Chính phương pháp phát hiện của Frey và Sandås là bài học cảnh giác: bộ phát hiện tần suất luận (frequentist) của họ dựa vào hai kiểu mẫu triển khai cẩu thả phổ biến nhất — kích thước đỉnh không đổidấu thời gian nạp lại trùng với dấu thời gian của giao dịch khớp. Bất kỳ bên tham gia nào chạy bộ phát hiện đó (và trên các sàn crypto, không ít người làm vậy — dữ liệu metadata khớp lệnh của chính sàn giao dịch còn khiến việc này dễ dàng hơn với dòng lệnh đặt gần máy chủ sàn) có thể tái dựng lại kích thước ẩn của bạn chỉ sau vài lần nạp lại. Các kênh lộ tín hiệu, xếp hạng theo tần suất tôi thường gặp trong thực tế:

  1. Kích thước hiển thị không đổi hoặc là số tròn (0,5 BTC, mỗi lần).
  2. Nạp lại ngay lập tức, có tính quyết định sau khi khớp hết một đỉnh — chữ ký cùng-dấu-thời-gian.
  3. Bộ đếm giờ leo thang mang tính quyết định: khớp thẳng đúng 30 giây vào mỗi lát cắt và băng ghi lệnh (tape) hiện ra như một chiếc đồng hồ đếm nhịp.
  4. Độ trễ và dải định giá lại cố định — nhịp độ amend của bạn là một dấu vân tay nhận dạng không kém gì kích thước lệnh của bạn, chủ đề của bài viết về dấu vân tay số và nhận dạng trader.

Cái giá của việc bị phát hiện không phải là điều giả định. Van Kervel và Menkveld ("High-frequency trading around large institutional orders", Journal of Finance 74(3), 2019) cho thấy các HFT ban đầu nghiêng về hướng chống lại các metaorder của tổ chức — cung cấp thanh khoản mà chiến thuật thụ động của bạn tiêu thụ — rồi sau đó chuyển sang giao dịch cùng chiều với lệnh đó một khi tính bền bỉ của nó tiết lộ thông tin, đuổi theo phần còn lại (back-running) và làm tăng đáng kể chi phí của lệnh mẹ. Các tổ chức của họ đã phản ứng bằng cách đánh đổi giữa lợi nhuận đầu cơ và rủi ro bị phát hiện. Lớp chiến thuật của bạn chính là nơi sự đánh đổi đó được hiện thực hóa: ngẫu nhiên hóa kích thước hiển thị (đồng đều 30–70% của một mức cơ sở tỷ lệ theo biến động là ổn), rung ngẫu nhiên (jitter) mỗi bộ đếm giờ ±20–30%, thỉnh thoảng để một lần nạp lại phải chờ, và không bao giờ để hai child order chia sẻ cùng kích thước, cùng pha bộ đếm giờ, và cùng hồ sơ độ trễ. Không điều nào trong số này tốn chất lượng khớp lệnh đo được; tất cả đều nâng sàn nhiễu lên cho bất kỳ ai đang cố khớp một bộ phát hiện vào dòng lệnh của bạn.

Một engine chiến thuật tối giản

Toàn bộ lớp ở trên nén lại thành một máy trạng thái nhỏ cho mỗi lát cắt: IDLE → POSTED → (vòng lặp reprice) → CROSSING → DONE, với cổng điểm hòa vốn ở lối vào, một dải trễ khi đang đặt lệnh, và leo thang theo deadline. Phiên bản dưới đây cố tình tối giản — không có adapter cho từng sàn, không có quản lý iceberg — nhưng nó hướng sự kiện (event-driven) và không gây tác dụng phụ (side-effect-free), nên nó có thể cắm thẳng vào bộ mô phỏng nhận biết hàng đợi bậc 4 từ chuỗi mô phỏng khớp lệnh: bộ mô phỏng gọi on_tick/on_fill, và diễn giải các hành động là post → GTX/post-only, cross → IOC, cancel_replace/amend_down → ngữ nghĩa của từng sàn theo ma trận ở trên.

import math
from dataclasses import dataclass
from enum import Enum, auto

class State(Enum):
    IDLE = auto(); POSTED = auto(); CROSSING = auto(); DONE = auto()

@dataclass
class Fees:
    maker: float          # $ per unit; negative = rebate
    taker: float          # $ per unit

@dataclass
class Cfg:
    tick: float
    sigma_1s: float       # $ per sqrt(second), from your live vol estimator
    adverse_frac: float = 0.6   # E[adverse move | no fill] ~ 0.6 * sigma; calibrate
    reprice_band: float = 2.0   # ticks of touch drift tolerated before repricing
    escalate_frac: float = 0.7  # cross the remainder at this fraction of the window

class SliceTactic:
    """One instance per scheduler slice. Drive it from a fill simulator or OMS."""

    def __init__(self, side: str, qty: float, window: float, fees: Fees, cfg: Cfg):
        self.side, self.qty, self.window = side, qty, window
        self.fees, self.cfg = fees, cfg
        self.filled, self.state, self.px, self.t0 = 0.0, State.IDLE, None, None

    def p_star(self, spread: float, tau: float) -> float:
        """Break-even fill probability for posting over a window tau."""
        delta = self.cfg.adverse_frac * self.cfg.sigma_1s * math.sqrt(tau)
        prize = spread + self.fees.taker - self.fees.maker
        return delta / (prize + delta)

    def p_fill(self, queue_ahead: float, drain: float, tau: float) -> float:
        """Crude queue-drain estimate; swap in your calibrated fill model."""
        if drain <= 0: return 0.0
        return min(1.0, drain * tau / max(queue_ahead + self.qty, 1e-9))

    def on_tick(self, t, bid, ask, queue_ahead, drain):
        if self.state == State.DONE: return []
        if self.t0 is None: self.t0 = t
        left = self.qty - self.filled
        elapsed, remain = t - self.t0, self.window - (t - self.t0)
        touch = bid if self.side == "buy" else ask

        if elapsed >= self.cfg.escalate_frac * self.window and left > 0:
            self.state = State.CROSSING          # deadline: pay up, finish
            return [("cross", left)]

        if self.state == State.IDLE:
            if self.p_fill(queue_ahead, drain, remain) >= self.p_star(ask - bid, remain):
                self.state, self.px = State.POSTED, touch
                return [("post", touch, left)]    # GTX / post-only
            self.state = State.CROSSING           # posting is -EV here
            return [("cross", left)]

        if self.state == State.POSTED:
            if abs(touch - self.px) / self.cfg.tick > self.cfg.reprice_band:
                self.px = touch                   # hysteresis breached:
                return [("cancel_replace", touch)]  # accept the queue reset
        return []

    def on_fill(self, t, fill_qty):
        self.filled += fill_qty
        if self.filled >= self.qty - 1e-9:
            self.state = State.DONE
            return [("slice_done", self.filled)]
        return []

    def on_budget_cut(self, new_qty):
        """Scheduler revised the slice down: amend-down keeps queue priority
        where documented (CME, Binance spot amend/keepPriority)."""
        self.qty = new_qty
        left = new_qty - self.filled
        return [("amend_down", left)] if left > 0 else [("cancel",)]

Ba lưu ý trung thực. p_fill ở đây là một tỷ lệ giữ chỗ — trong môi trường sản xuất, nó nên là mô hình đã phân nhóm (bucketed), hiệu chỉnh trực tuyến từ bài viết về mô phỏng khớp lệnh, bởi vì toàn bộ cổng post/cross chỉ tốt bằng đúng chất lượng của ước lượng đó. adverse_frac che giấu đại lượng khó nhất trong bài viết (δ\delta phụ thuộc chế độ thị trường và tăng vọt đúng lúc việc đặt lệnh hấp dẫn nhất); hãy ước lượng nó từ chính các kết quả không-khớp-lệnh của bạn, phân nhóm theo chế độ biến động. Và engine ở trên định giá lại qua cancel-replace một cách vô điều kiện — một phiên bản nhận biết theo sàn nên định tuyến các thay đổi giảm khối lượng qua đường giữ ưu tiên, và tính mỗi hành động vào một ngân sách tin nhắn.

Hãy chạy nó bên trong bộ mô phỏng với một băng replay trước khi tin vào bất kỳ tham số nào. Thí nghiệm quan trọng nhất: cố định bộ lập lịch, quét escalate_fracreprice_band, rồi vẽ đồ thị độ hao hụt lát cắt so với chi phí mô hình ngụ ý bởi η\eta. Bề mặt này có một cao nguyên — các dải tham số gần tối ưu rộng — và hai vách đá: leo thang quá trễ (phần dư chưa khớp bị khớp thẳng vào lúc thị trường đang có động lượng) và định giá lại quá hăng hái (toàn bộ giá trị hàng đợi bị đốt cháy). Bạn muốn biết các vách đá của mình nằm ở đâu trước khi môi trường sản xuất tìm ra chúng thay bạn.

Những điều cần rút ra

  1. Hai lớp, một hợp đồng. Bộ lập lịch quyết định bao nhiêu và đến khi nào; chiến thuật quyết định như thế nào. Giao diện là ngân sách, cửa sổ, mức khẩn cấp truyền xuống; các lệnh khớp và độ hao hụt lát cắt so với mid tại thời điểm bắt đầu truyền lên. Nếu bạn không thể quy độ hao hụt về đúng lớp gây ra nó, bạn không thể tinh chỉnh được lớp nào.
  2. Cổng post/cross là phép tính, không phải cảm tính. Đặt lệnh khi và chỉ khi p>δ/(Π+δ)p > \delta/(\Pi + \delta) với Π=s+ftfm\Pi = s + f_t - f_m. Trên các sổ lệnh crypto có spread hẹp, phần thưởng chính là chênh lệch phí, nên bậc phí của bạn quyết định chiến thuật của bạn — hãy tinh chỉnh lại bậc thang này sau mỗi lần đổi bậc phí.
  3. Bộ đếm giờ hết hạn là điểm giao nhau của hai đường cong — xác suất khớp lệnh bão hòa dần so với lựa chọn bất lợi tăng theo τ\sqrt{\tau} — chứ không phải những hằng số truyền miệng.
  4. Vị trí hàng đợi là một tài sản; hãy hiểu ngữ nghĩa amend của từng sàn trước khi tiêu nó. CME: giảm khối lượng giữ nguyên ưu tiên. Binance spot: cancelReplace luôn xếp hàng lại, amend-keepPriority của năm 2025 giữ nguyên ưu tiên cho việc cắt giảm khối lượng. Binance futures: mọi lần modify đều xếp hàng lại. OKX: không được ghi rõ trong tài liệu — hãy đo lường, và trong lúc chờ đợi hãy giả định trường hợp xấu nhất.
  5. Iceberg là một chuỗi các lệnh ở cuối hàng đợi, và những lệnh cẩu thả thì dễ bị đọc ra. Các đỉnh không đổi và các lần nạp lại cùng dấu thời gian là một chữ ký phát hiện đã được công bố; hãy ngẫu nhiên hóa kích thước và bộ đếm giờ, hoặc chấp nhận bị đuổi theo (back-run).
  6. Đưa máy trạng thái vào bộ mô phỏng khớp lệnh của bạn trước tiên. Lớp chiến thuật là phần của hệ thống mà backtest và môi trường sản xuất phân kỳ mạnh nhất — đó chính xác là lý do nó thuộc về bên trong bộ mô phỏng, chứ không phải được gắn thêm vào sau.

Liên kết hữu ích

  1. Harris, L. — Optimal Dynamic Order Submission Strategies in Some Stylized Trading Problems, Financial Markets, Institutions & Instruments 7(2), 1-76 (1998)
  2. Cont, R., Kukanov, A. — Optimal Order Placement in Limit Order Markets, Quantitative Finance 17(1), 21-39 (2017)
  3. Frey, S., Sandås, P. — The Impact of Iceberg Orders in Limit Order Books (2009)
  4. Bessembinder, H., Panayides, M., Venkataraman, K. — Hidden Liquidity: An Analysis of Order Exposure Strategies in Electronic Stock Markets, Journal of Financial Economics 94(3), 361-383 (2009)
  5. van Kervel, V., Menkveld, A. — High-Frequency Trading around Large Institutional Orders, Journal of Finance 74(3), 1091-1137 (2019)
  6. Moallemi, C., Yuan, K. — A Model for Queue Position Valuation in a Limit Order Book (2016)
  7. Lehalle, C.-A. — Market Microstructure Knowledge Needed for Controlling an Intra-Day Trading Process (2011)
  8. Binance Spot API — Order Amend Keep Priority
  9. Binance Spot API — Trading endpoints (cancelReplace semantics)
  10. Binance USDT-M Futures API — Modify Order
  11. OKX API v5 — Amend order
  12. CME Group — Order Functionalities (modification and time priority)

Trích dẫn

@article{soloviov2026childordertactics,
  author = {Soloviov, Eugen},
  title = {Inside the slice: child-order tactics between your scheduler and the exchange},
  year = {2026},
  url = {https://marketmaker.cc/blog/child-order-execution-tactics},
  description = {The tactics layer between execution schedulers and the exchange: passive-then-aggressive escalation with maker-taker break-even math, amend vs cancel-replace queue semantics across venues, iceberg anti-signaling, and a per-slice Python state machine for fill simulators.}
}
Tuyên bố miễn trừ trách nhiệm: Thông tin được cung cấp trong bài viết này chỉ nhằm mục đích giáo dục và thông tin, không cấu thành lời khuyên về tài chính, đầu tư hoặc giao dịch. Giao dịch tiền mã hóa tiềm ẩn rủi ro thua lỗ đáng kể.

Tác Giả

Eugen Soloviov
Eugen Soloviov

Trading-systems engineer

Trading-systems engineer building bots since 2017: cross-exchange arbitrage (connected up to 30 venues), cointegration-based pairs arbitrage across spot and futures, scalping, news and sentiment-driven strategies, trend algorithms, and portfolio management and balancing algorithms. Also builds sub-millisecond order execution, big-data warehouses, backtesting engines, AI agents, and trading interfaces (incl. open-source profitmaker.cc). Stack: JS/TS, Python, Rust/Zig/Go, DevOps, backend, frontend, architecture.

Newsletter

Đi Trước Thị Trường

Đăng ký nhận bản tin của chúng tôi để có những thông tin chuyên sâu độc quyền về AI trading, phân tích thị trường và các cập nhật nền tảng.

Chúng tôi tôn trọng quyền riêng tư của bạn. Hủy đăng ký bất kỳ lúc nào.