Dentro do slice: táticas de child order entre o seu scheduler e a exchange
Uma trajetória Almgren-Chriss entrega um número: vender 4,2 BTC nos próximos cinco minutos. Um schedule VWAP entrega o mesmo tipo de número com uma justificativa diferente. Nenhum dos dois diz nada sobre o que acontece a seguir — se esses 4,2 BTC atingem o book como uma ordem marketable, ficam parados no touch coletando taxas de maker, se escondem atrás de um display de 0,3 BTC, ou são repreçados onze vezes perseguindo uma cotação que se desloca. Essa segunda camada de decisão é a camada tática, e em books de cripto dominados por taxas ela rotineiramente move mais PnL por slice do que a escolha do scheduler acima dela. Os orçamentos de intervalo do scheduler diferem entre TWAP e um Almgren-Chriss bem calibrado em alguns bps de impacto ao longo de toda a ordem-mãe; pagar taxas de taker em slices que poderiam ter sido feitas como maker, ou sangrar posição na fila por repreçamento descuidado, custa isso por hora. Este artigo é sobre a camada que todo mundo executa e quase ninguém documenta: a máquina de estados que decide como cada child order toca o book.
Duas camadas, uma interface estreita
Lehalle e Laruelle, em Market Microstructure in Practice (2ª ed., 2018), formalizam o que toda mesa de execução converge para: uma camada estratégica (o scheduler) que aloca quantidade ao longo do tempo, e uma camada tática (o microtrader) que trabalha cada alocação contra o book ao vivo. A separação não é estética — as duas camadas vivem em relógios diferentes e em dados diferentes. O scheduler pensa em minutos, consome previsões de volatilidade e volume, e resolve um problema variacional. A camada tática pensa em milissegundos a segundos, consome deltas de L2 e estimativas de fila, e resolve uma sequência de pequenos problemas de parada.

A interface entre elas deve ser estreita. Para baixo, por slice :
- orçamento — a quantidade a executar nesse intervalo (o do Almgren-Chriss, ou o incremento da curva de volume do VWAP);
- janela — a duração do slice;
- urgência — para Almgren-Chriss, o candidato natural é , que já comprime aversão a risco, volatilidade e liquidez em uma única taxa; para um scheduler VWAP costuma ser uma distância de banda ("estamos 1,8% atrás da curva alvo").
Para cima: fills com timestamps e taxas, o remanescente não preenchido, e o implementation shortfall no nível do slice medido contra o mid de chegada do intervalo. Esse último ponto importa: o parâmetro de impacto do scheduler já precifica o que demandar liquidez à taxa deveria custar. A descrição de trabalho inteira da camada tática cabe em uma linha: realizar fills a um custo melhor do que o implicado por , sem vazar a existência da ordem-mãe. Se o seu shortfall de slice medido consistentemente supera o custo do modelo, o seu calibrado pode cair, o scheduler acelera, e toda a pilha melhora. Se você não consegue medir o shortfall de slice separadamente do custo do schedule, não consegue calibrar nenhuma das duas camadas — você tem um único número borrado e dois botões.
A política de remanescente também faz parte do contrato. Quando um slice termina com quantidade não preenchida, ou a camada tática força a conclusão (cruzar o remanescente — o padrão sob urgência de deadline) ou o devolve ao scheduler para reamortização sobre os slices restantes (aceitável no início de um schedule de baixo, venenoso perto do deadline, onde a reamortização silenciosamente se acumula em um slice final enorme).
A escada de escalonamento: passivo primeiro, agressivo por deadline
O resultado mais antigo nessa área é Harris (1998), "Optimal dynamic order submission strategies in some stylized trading problems" (Financial Markets, Institutions & Instruments 7(2)): para um trader de liquidez que precisa completar uma operação até um deadline, a estratégia ótima é dinâmica — ficar no book com ordens limitadas enquanto o tempo é barato, repreçar em direção ao mercado à medida que o deadline se aproxima, e cruzar no final. Todo motor tático de produção é descendente dessa forma: postar no touch, envelhecer, escalonar, cruzar. O que os fee schedules e a dinâmica de fila modernos adicionam é a aritmética de exatamente quando cada transição dispara.
O break-even para cruzar
Trabalho por unidade, preços relativos ao mid atual, para uma compra. Cruzar agora custa metade do spread mais a taxa de taker:
Postar no bid ao longo de uma janela preenche com probabilidade ; um fill ganha o meio-spread e paga a taxa de maker (negativa se for um rebate). Nenhum fill significa cruzar no final da janela depois que o preço, em média, se moveu contra você em — estritamente positivo, porque não-fill e drift adverso são o mesmo evento: seu bid não é atingido quando o mercado se afasta dele subindo. Custo esperado de postar:
Postar vence cruzar sse
onde é o prêmio — o round-trip completo que você captura ao ser maker em vez de taker: o spread mais o diferencial de taxas. Esse é o mesmo break-even que governa toda a economia maker-taker da execução, condensado a um único slice.
Números, perp de BTCUSDT: mid $100.000, spread de um tick s = \0,10f_m = $20f_t = $50\Pi = 0,10 + 50 - 20 = $30,10 \approx 3\sigma_{\text{day}} = $3{.}000\delta(\tau) \approx 0,6,\sigma_{\text{day}}\sqrt{\tau/86400}$ (o 0,6 é um haircut de seleção adversa que você deve calibrar, não confiar cegamente):
- s: \delta \approx \19p^* = 19/49 \approx 0,39$. Só poste se esperar pelo menos 39% de fill em 10 segundos.
- s: \delta \approx \47p^* = 47/77 \approx 0,61$.
- Com um rebate de maker de 1 bp em vez de uma taxa de 2 bps (f_m = -\10\Pi = $60,10p^* \approx 0,24$.
Dois fatos estruturais decorrem disso. Primeiro, cresce como enquanto é constante, então : a paciência tem um prazo de validade rígido, e o timer de age-out não é uma heurística, mas o ponto de cruzamento de duas curvas — o seu estimado (côncavo, saturando à medida que a fila à sua frente se esvazia) contra (crescente). Segundo, o tier de taxas em que você opera move fisicamente a escada. Um upgrade de tier que corta taxas de taker torna a sua tática ótima mais agressiva — um acoplamento que a maioria das pessoas descobre só quando as estatísticas de fill mudam depois de um re-tier VIP.
Cont e Kukanov, "Optimal order placement in limit order markets" (Quantitative Finance 17(1), 2017; arXiv 2012), tornam isso rigoroso em um único período: minimizar o custo esperado de executar unidades divididas entre ordens de mercado e ordens limitadas (em uma ou várias venues), com uma penalidade para o shortfall. A solução de venue única é explícita e tem estrutura de newsvendor: o tamanho ótimo da ordem limitada é guiado pela distribuição do fluxo de saída da fila — poste tamanho agressivamente quando a fila à frente é pequena em relação ao fluxo de saída esperado, e cubra o risco de cauda com ordens de mercado. A extensão multi-venue deles é resolvida por aproximação estocástica e é o núcleo intelectual da lógica de alocação passiva de todo smart order router. A leitura prática para um motor tático: o no break-even acima não é uma constante — é uma função da posição na fila e da taxa de drenagem, motivo pelo qual a camada tática precisa consumir o estimador de posição na fila como insumo de primeira classe.

O parâmetro de urgência comprime toda essa escada. alto vindo do scheduler significa que o tempo característico é curto: as janelas encolhem, sobe, e o motor pula direto para cruzar — corretamente, porque o scheduler já declarou que o risco de inventário domina a economia de taxas. baixo estica a fase passiva. A camada tática nunca deve re-derivar urgência a partir da sua própria visão do mercado; isso é trabalho do scheduler, e duplicá-lo cria dois controladores em desacordo.
Repreçando sem queimar sua posição na fila
Uma vez postada, a cotação vai se deslocando. Persegui-la ingenuamente — cancelar, repostar no novo touch, repetir — é como motores táticos silenciosamente destroem a própria probabilidade de fill que justificou postar. Posição na fila é um ativo com valor em dólar mensurável (Moallemi e Yuan, 2016, colocam um preço nela: posições na frente da fila em books FIFO líquidos valem uma fração significativa do spread), e cada decisão de repreçamento é uma troca: vender sua posição atual na fila, comprar uma no fim de um nível de preço diferente. A troca só vale a pena quando o valor do novo nível excede o do antigo mais os custos de mensageria. Isso exige saber o que o amend de cada venue realmente faz com o seu lugar na fila — e a resposta é extremamente não uniforme.
CME Globex documenta a semântica mais limpa: reduzir a quantidade da ordem mantém a prioridade de tempo; aumentar a quantidade ou mudar o preço manda você para o fim da fila. Esse é o modelo de referência — quantidade para baixo é grátis, tudo o mais é um re-enfileiramento.
Binance spot historicamente oferecia apenas POST /api/v3/order/cancelReplace — um cancel-mais-new que parece atômico mas é explicitamente não transacional. Dois modos: STOP_ON_FAILURE (padrão — se o cancelamento falhar, nenhuma nova ordem) e ALLOW_FAILURE (coloca a nova ordem mesmo que o cancelamento falhe — olá, exposição dupla acidental). A operação pode ter sucesso parcial, sinalizado por HTTP 409, então o seu OMS precisa reconciliar as duas pernas de forma independente; e a nova ordem sempre começa uma vida de fila do zero. Depois, em 2025, a Binance lançou o Order Amend Keep Priority (PUT /api/v3/order/amend/keepPriority): reduz a quantidade no lugar, mantém a prioridade de tempo, a custo zero de contagem de ordens não preenchidas. Semântica CME, quinze anos depois — e apenas a metade de quantidade para baixo.
Binance USDT-M futures tem um endpoint de modificação verdadeiro (PUT /fapi/v1/order), mas leia as letras miúdas: apenas ordens LIMIT, tanto price quanto quantity devem ser enviados, e "modified orders will be reordered in the match queue" — a documentação promete nenhuma retenção de prioridade mesmo para reduções puras de quantidade. Trate cada modify de futures como um reset de fila que por acaso economiza uma mensagem e mantém o ID da ordem. Uma pegadinha que vale conhecer: modificar uma ordem GTX (post-only) para um preço que cruzaria faz a ordem ser cancelada, não rejeitada-e-mantida — uma implementação de peg que não verifica isso ocasionalmente vai se amendar até desaparecer.
OKX expõe POST /api/v5/trade/amend-order (newPx, newSz, com cxlOnFail para auto-cancelar em caso de falha do amend). É uma única mensagem, preserva o ID da ordem, e confirma de forma assíncrona — sCode = 0 significa "pedido aceito", e o resultado real chega no canal de ordens como amendResult. O que a documentação pública conspicuamente não especifica é o comportamento de prioridade na fila. Não preencha essa lacuna de documentação com otimismo. Meça: poste duas ordens marcadoras em um nível calmo, faça o amend do tamanho de uma delas para baixo, e observe qual preenche primeiro ao longo de algumas centenas de testes. Até você ter esse dado, a suposição conservadora — qualquer mudança de preço reenfileira você em todo lugar, quantidade para baixo preserva prioridade só onde explicitamente documentado — é a única defensável.

As consequências de política:
- Histerese, não pegging. Repreçe apenas quando o touch se deslocou mais do que uma banda de ticks em relação ao seu preço em repouso. Dentro da banda, o drift é ruído e a sua posição na fila vale mais do que um tick de melhoria de preço. Uma banda inicial sensata é de 1 a 3 ticks escalados pela vol de curto horizonte; a banda correta torna o repreçamento marginal EV-neutro: , com o valor de fila estilo Moallemi-Yuan e o seu preço-sombra de rate-limit. Operações de amend/cancel-replace consomem orçamento de taxa de ordens em ambas as venues Binance; um motor tático que faz pegging a cada tick vai esgotar a capacidade de mensagens do resto do seu sistema.
- Faça amend para baixo, nunca cancel-repost para baixo. Quando o scheduler corta um orçamento de slice em pleno voo (um scheduler POV vendo o volume secar, um re-resolve de Almgren-Chriss após fills parciais), use o caminho que preserva prioridade onde ele existir. Esse é o único almoço grátis de toda a camada.
- Urgência assimétrica no repreçamento. Repreçar em direção ao mercado (perseguindo) reseta a sua fila a um preço pior — deve disparar apenas a partir da lógica de escalonamento, no seu timer. Repreçar para longe (o mercado veio até você) é um presente; aproveite-o apenas via a banda passiva, porque o seu nível atual está prestes a preencher de qualquer forma.
Icebergs, tamanho de display, e o que vaza sua intenção
O tamanho de display é a terceira decisão, e é uma troca genuinamente de dois lados, não um botão de furtividade grátis. O registro empírico:
- Frey e Sandås ("The Impact of Iceberg Orders in Limit Order Books", working paper de 2009; Quarterly Journal of Finance, 2017), em dados da Xetra: ordens iceberg carregaram 9,3% do volume submetido e 15,9% do volume executado, tinham entre 12 e 20x o tamanho de ordens limitadas comuns, e — o ponto principal — quando outros participantes detectam um iceberg, respondem com ordens de mercado correspondentes. Tamanho oculto, uma vez inferido, atrai fluxo: a busca por liquidez latente funciona nos dois sentidos.
- Bessembinder, Panayides e Venkataraman ("Hidden liquidity: an analysis of order exposure strategies in electronic stock markets", JFE 94(3), 2009), na Euronext Paris, onde ordens ocultas eram 44% do volume da amostra: esconder reduz o implementation shortfall mas também reduz a probabilidade de execução completa e alonga o tempo até a conclusão. Exposição compra fills e paga por eles em impacto; a opção é usada exatamente como a teoria prevê — ordens agressivas se expõem para atrair contrapartes, tamanho paciente se esconde.
- Esser e Mönch ("The navigation of an iceberg", Finance Research Letters 4(2), 2007) tratam o tamanho do peak como uma otimização: display maior preenche mais rápido, display menor vaza menos, e o ótimo é interior.
Primeiro a mecânica, porque ela condiciona a otimização: em praticamente toda venue que suporta icebergs nativos (Binance spot via icebergQty, OKX via suas ordens de algo iceberg), cada refill do peak visível entra no fim da fila naquele preço. Um iceberg, portanto, não é "uma ordem com tamanho oculto" — é uma sequência de pequenas ordens, cada uma pagando a espera completa na fila, disparadas automaticamente. No break-even de taxas acima, isso importa: o efetivo por peak é a probabilidade de fill no fim da fila, não a da sua posição original. Filas profundas punem peaks pequenos duas vezes — fills mais lentos e mais rodadas de refill valendo seleção adversa.
Depois vem o problema da sinalização. O próprio método de detecção de Frey e Sandås é o conto de advertência: o detector frequentista deles se baseia nos dois padrões de preguiça de implementação mais comuns — tamanho de peak constante e timestamps de refill idênticos ao timestamp da negociação executora. Qualquer participante rodando esse detector (e em venues de cripto, muitos o fazem — os próprios metadados de matching da exchange tornam isso ainda mais fácil para fluxo colocalizado) reconstrói o seu tamanho oculto em poucos refills. Os vetores de vazamento, ordenados por quão frequentemente eu os vejo na prática:
- Tamanhos de display constantes ou redondos (0,5 BTC, sempre).
- Refill instantâneo e determinístico após uma execução de peak completo — a assinatura de mesmo timestamp.
- Timers de escalonamento determinísticos: cruzar exatamente 30 s dentro de cada slice e a tape mostra um metrônomo.
- Latência e banda de repreçamento fixas — a sua cadência de amend é uma impressão digital tão identificável quanto os tamanhos das suas ordens, tema de impressões digitais e identificação de traders.
O custo de ser detectado não é hipotético. Van Kervel e Menkveld ("High-frequency trading around large institutional orders", Journal of Finance 74(3), 2019) mostram que HFTs inicialmente se posicionam contra metaordens institucionais — fornecendo a liquidez que a sua tática passiva consome — depois viram para negociar a favor da ordem assim que a sua persistência revela informação, fazendo back-running do remanescente e elevando materialmente o custo da ordem-mãe. As instituições estudadas responderam trocando lucro especulativo por risco de detecção. A sua camada tática é exatamente onde essa troca é implementada: aleatorize o tamanho de display (uniforme entre 30-70% de uma base escalada por vol funciona bem), aplique jitter de ±20-30% em cada timer, ocasionalmente deixe um refill esperar, e nunca deixe duas child orders compartilharem um tamanho, uma fase de timer, e um perfil de latência. Nada disso custa qualidade de fill mensurável; tudo isso eleva o piso de ruído para quem estiver ajustando um detector ao seu fluxo.
Um motor tático mínimo
Toda a camada acima se comprime em uma pequena máquina de estados por slice: IDLE → POSTED → (loop de reprice) → CROSSING → DONE, com o gate de break-even na entrada, uma banda de histerese enquanto postado, e escalonamento por deadline. A versão abaixo é deliberadamente mínima — sem adapters de venue, sem gestão de iceberg — mas é orientada a eventos e livre de efeitos colaterais, então ela se encaixa diretamente no simulador consciente de fila do degrau 4 da escada de simulação de fills: o simulador chama on_tick/on_fill, e interpreta ações como post → GTX/post-only, cross → IOC, cancel_replace/amend_down → a semântica da venue conforme a matriz acima.
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",)]
Três ressalvas honestas. p_fill aqui é uma razão de placeholder — em produção deveria ser o modelo em buckets, calibrado ao vivo, do artigo de simulação de fills, porque todo o gate post/cross é apenas tão bom quanto essa estimativa. adverse_frac esconde a quantidade mais difícil do artigo ( é dependente de regime e dispara exatamente quando postar é mais tentador); estime-o a partir dos seus próprios resultados de não-fill, agrupados por regime de vol. E o motor acima repreça via cancel-replace incondicionalmente — uma versão consciente de venue deveria rotear mudanças de quantidade para baixo pelo caminho que preserva prioridade e cobrar cada ação contra um orçamento de mensagens.
Rode-o dentro do simulador contra uma fita de replay antes de acreditar em qualquer um dos parâmetros. O experimento que importa: fixe o scheduler, varra escalate_frac e reprice_band, e plote o shortfall de slice contra o custo de modelo implicado por . A superfície tem um platô — bandas amplas de parâmetros quase ótimos — e dois precipícios: escalonar tarde demais (remanescentes não preenchidos cruzando para dentro de momentum) e repreçar com ansiedade demais (todo o valor de fila queimado). Você quer saber onde estão os seus precipícios antes que a produção os encontre por você.
O que levar
- Duas camadas, um contrato. O scheduler decide quanto e até quando; a tática decide como. A interface é orçamento, janela, urgência para baixo; fills e shortfall de slice vs. mid de chegada do intervalo para cima. Se você não consegue atribuir o shortfall a uma camada, não consegue calibrar nenhuma delas.
- O gate post/cross é aritmética, não vibe. Poste sse com . Em books de cripto apertados, o prêmio é o diferencial de taxas, então o seu tier de taxas define a sua tática — reajuste a escada depois de cada re-tier.
- Timers de age-out são o ponto de cruzamento de duas curvas — probabilidade de fill saturando contra seleção adversa que cresce em — não constantes de folclore.
- Posição na fila é um ativo; conheça a semântica de amend de cada venue antes de gastá-la. CME: quantidade para baixo mantém prioridade. Binance spot: cancelReplace sempre reenfileira, o amend-keepPriority de 2025 preserva a prioridade para cortes de quantidade. Binance futures: todo modify reenfileira. OKX: não documentado — meça, e assuma o pior enquanto isso.
- Icebergs são uma sequência de ordens no fim da fila, e os preguiçosos são legíveis. Peaks constantes e refills de mesmo timestamp são uma assinatura de detecção publicada; aleatorize tamanhos e timers ou aceite ser alvo de back-running.
- Coloque a máquina de estados no seu simulador de fills primeiro. A camada tática é a parte da pilha onde backtest e produção mais divergem — motivo exato pelo qual ela pertence dentro do simulador, não parafusada depois.
Links úteis
- Harris, L. — Optimal Dynamic Order Submission Strategies in Some Stylized Trading Problems, Financial Markets, Institutions & Instruments 7(2), 1-76 (1998)
- Cont, R., Kukanov, A. — Optimal Order Placement in Limit Order Markets, Quantitative Finance 17(1), 21-39 (2017)
- Frey, S., Sandås, P. — The Impact of Iceberg Orders in Limit Order Books (2009)
- 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)
- van Kervel, V., Menkveld, A. — High-Frequency Trading around Large Institutional Orders, Journal of Finance 74(3), 1091-1137 (2019)
- Moallemi, C., Yuan, K. — A Model for Queue Position Valuation in a Limit Order Book (2016)
- Lehalle, C.-A. — Market Microstructure Knowledge Needed for Controlling an Intra-Day Trading Process (2011)
- Binance Spot API — Order Amend Keep Priority
- Binance Spot API — Trading endpoints (cancelReplace semantics)
- Binance USDT-M Futures API — Modify Order
- OKX API v5 — Amend order
- CME Group — Order Functionalities (modification and time priority)
Citation
@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.}
}
Authors
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.