← Voltar aos artigos
August 11, 2026
5 min read

Knowledge Distillation: Compressing Trading Models for Low-Latency Deployment

Knowledge Distillation: Compressing Trading Models for Low-Latency Deployment
#model-compression
#distillation
#latency
#HFT
#deployment

A tensão entre precisão e latência na negociação orientada por ML já tem uma resposta publicada neste blog. Modelagem de propagação com aprendizado de máquina recomenda uma divisão em dois estágios: um modelo rápido de aumento de gradiente faz a cotação em tempo real crítica para latência, enquanto um modelo profundo é executado de forma assíncrona e alimenta-o com um sinal secundário ou ajusta seus parâmetros. Dois modelos, dois relógios, um sistema.

A destilação do conhecimento é uma resposta diferente para a mesma tensão. Em vez de executar o modelo lento junto com o rápido, você o usa uma vez, off-line, para treinar o rápido – o aluno aprende a distribuição completa de probabilidades do professor sobre os resultados, e não apenas os rótulos rígidos, e o professor então abandona completamente o caminho quente. Um modelo no momento da inferência, sem acoplamento assíncrono, sem janela de obsolescência.

A resposta vencedora é empírica e este artigo ainda não a responde. O que se segue é o maquinário, além de uma declaração explícita das medidas que o decidiriam. Nada aqui é um resultado de referência; onde normalmente iria um número, há um marcador dizendo o que deve ser executado.

Uma correção de enquadramento inicial, de DeepLOB e aprendizado profundo na carteira de pedidos: alta precisão de classificação não se traduz automaticamente em lucro – o movimento previsto deve limpar o spread de compra e venda. "Preservar a precisão direcional do professor" é, portanto, a coisa errada para otimizar uma configuração de destilação.

A estrutura professor-aluno

Modelo de professor grande transferindo insights para um aluno compacto

A formulação original de Hinton, Vinyals e Dean (2015) é direta. Você tem um modelo de professor TT (grande, lento, preciso) e um modelo de estudante SS (pequeno, rápido, para ser treinado). O aluno aprende com dois sinais simultaneamente:

  1. Alvos difíceis: os rótulos de verdade yy (por exemplo, o preço subiu ou desceu)
  2. Metas flexíveis: a distribuição de probabilidade de produção do professor qTq_T em todas as aulas

A função de perda do aluno combina ambos:

L=αLCE(y,σ(zS))+(1α)T2DKL(σ(zTT)σ(zST))\mathcal{L} = \alpha \cdot \mathcal{L}_{\text{CE}}(y, \sigma(z_S)) + (1 - \alpha) \cdot T^2 \cdot D_{\text{KL}}\left(\sigma\left(\frac{z_T}{T}\right) \| \sigma\left(\frac{z_S}{T}\right)\right)

onde zTz_T e zSz_S são os logits do professor e do aluno, σ\sigma é a função softmax, TT é o parâmetro de temperatura, e α\alpha controla o equilíbrio entre os dois componentes de perda.

Por que as metas flexíveis são importantes para a negociação

A formulação de três classes de preço médio ascendente/estacionário/descendente, o ±α\pm\alpha limiar e por que o desequilíbrio resultante significa que você relata F1 ponderado em vez de precisão estão todos configurados em DeepLOB - assuma esse esquema de rótulo aqui. O ponto específico da destilação é o que o professor emite antes do argmax: um hard "up" carrega um bit, enquanto 0,72/0,21/0,07 também diz que o movimento pode parar e quase certamente não será revertido. Essa estrutura entre classes é o sinal extra de treinamento, e é por isso que um aluno com alvo leve pode generalizar melhor do que o mesmo aluno treinado apenas com rótulos.

Um aviso sobre o que essa confiança não é. A saída do Softmax não é uma incerteza calibrada, e tratar 0,55 vs. 0,85 como uma entrada de dimensionamento de posição é o atalho que previsão conforme para negociação existe para recusar - deriva o dimensionamento da largura do intervalo, uma proporção de borda e um filtro sem negociação quando o intervalo ultrapassa zero, nenhum dos quais um softmax bruto oferece a você. Ganhar a reivindicação de dimensionamento aqui significa medir a calibração do aluno em relação à do professor (diagrama de confiabilidade, ECE) e mostrar que a destilação a preserva. Esse resultado ainda não está neste artigo.

Temperatura e alvos flexíveis

Suavizando alvos de probabilidade neural

O parâmetro de temperatura TT controla a "suavidade" da distribuição de probabilidade. Dados dados ziz_i, o softmax com temperatura é:

σ(zi;T)=exp(zi/T)jexp(zj/T)\sigma(z_i; T) = \frac{\exp(z_i / T)}{\sum_j \exp(z_j / T)}

Quando T=1T = 1 (softmax padrão), a distribuição é pontiaguda – a classe dominante obtém a maior parte da massa de probabilidade. Como TT aumenta, a distribuição se achata, revelando mais claramente as magnitudes relativas dos logits.

Temperatura Efeito Caso de uso
T=1T = 1 Softmax padrão, pico Inferência normal
T=25T = 2\text{--}5 Suavização moderada Destilação geral
T=510T = 5\text{--}10 Suavização pesada Quando o professor está muito confiante
T>20T > 20 Quase uniforme Raramente útil, apaga o sinal

Há um argumento plausível de que os modelos de negociação desejam uma temperatura moderada: as previsões financeiras são muito menos confiáveis ​​do que a classificação de imagens, portanto, um professor pode produzir 0,55/0,30/0,15 em vez de 0,99/0,005/0,005, deixando menos pico para suavizar antes que o sinal desapareça. Isto é um argumento, não uma conclusão – o intervalo tem de provir de uma varredura em dados reais, pontuados por F1 ponderado, e pode diferir consoante o regime.

O T2T^2 O fator no termo de divergência KL compensa as magnitudes reduzidas do gradiente em temperaturas mais altas. Sem ele, a perda de destilação tornar-se-ia insignificantemente pequena, uma vez que TT aumenta.

Escolhendo a temperatura por meio da pesquisa em grade

import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch.utils.data import DataLoader
from sklearn.metrics import f1_score

def distillation_loss(
    student_logits: torch.Tensor,
    teacher_logits: torch.Tensor,
    labels: torch.Tensor,
    temperature: float,
    alpha: float,
) -> torch.Tensor:
    """Combined hard-target + soft-target distillation loss."""
    hard_loss = F.cross_entropy(student_logits, labels)

    soft_teacher = F.log_softmax(teacher_logits / temperature, dim=-1)
    soft_student = F.log_softmax(student_logits / temperature, dim=-1)

    soft_loss = F.kl_div(
        soft_student,
        soft_teacher,
        log_target=True,
        reduction="batchmean",
    )

    return alpha * hard_loss + (1.0 - alpha) * (temperature ** 2) * soft_loss


def search_temperature(
    teacher: nn.Module,
    student_factory,       # callable returning a fresh student
    train_loader: DataLoader,
    val_loader: DataLoader,
    temperatures: list[float] = [1, 2, 3, 5, 8, 12],
    alpha: float = 0.3,
    epochs: int = 30,
    lr: float = 1e-3,
    device: str = "cuda",
):
    """Grid search over temperature, scored by weighted F1 (not accuracy:
    the up/flat/down label scheme is heavily imbalanced toward flat)."""
    best_f1, best_T, best_student = 0.0, 1.0, None

    for T in temperatures:
        student = student_factory().to(device)
        optimizer = torch.optim.AdamW(student.parameters(), lr=lr)

        for epoch in range(epochs):
            student.train()
            for X, y in train_loader:
                X, y = X.to(device), y.to(device)
                with torch.no_grad():
                    teacher_logits = teacher(X)
                student_logits = student(X)

                loss = distillation_loss(
                    student_logits, teacher_logits, y, T, alpha
                )
                optimizer.zero_grad()
                loss.backward()
                optimizer.step()

        student.eval()
        preds, targets = [], []
        with torch.no_grad():
            for X, y in val_loader:
                preds.append(student(X.to(device)).argmax(dim=-1).cpu())
                targets.append(y)

        f1 = f1_score(
            torch.cat(targets), torch.cat(preds), average="weighted"
        )
        print(f"T={T:>4.1f}  val_weighted_f1={f1:.4f}")
        if f1 > best_f1:
            best_f1, best_T, best_student = f1, T, student

    print(f"\nBest temperature: T={best_T}, val_weighted_f1={best_f1:.4f}")
    return best_T, best_student

Destilando conjuntos em um único modelo

Muitos conjuntos de modelos convergindo para um núcleo

Um conjunto quântico mistura vieses indutivos: uma árvore intensificada por gradiente em recursos de carteira de pedidos, um 1D-CNN sobre ticks recentes, um transformador em janelas de vários períodos de tempo, um modelo linear em fatores macro. A média é mais estável do que qualquer membro sozinho, e a execução de todos os quatro multiplica a latência e o custo - a situação que a divisão em dois estágios da modelagem de propagação com aprendizado de máquina lida ao rebaixar membros lentos para um canal lateral assíncrono. Em vez disso, a destilação colapsa todos os quatro em um único aluno no caminho quente.

A produção do professor do conjunto é a média das saídas softmax de seus membros:

qensemble(x)=1Kk=1Kσ(zk(x)/T)q_{\text{ensemble}}(x) = \frac{1}{K} \sum_{k=1}^{K} \sigma(z_k(x) / T)

onde KK é o número de membros do conjunto. O aluno é treinado contra essa distribuição média.

class EnsembleTeacher(nn.Module):
    """Wraps K models, returns averaged logits for distillation."""

    def __init__(self, models: list[nn.Module]):
        super().__init__()
        self.models = nn.ModuleList(models)

    @torch.no_grad()
    def forward(self, x: torch.Tensor) -> torch.Tensor:
        logits = torch.stack([m(x) for m in self.models], dim=0)
        return logits.mean(dim=0)   # average logits, not softmax


class TradingStudent(nn.Module):
    """Lightweight MLP for sub-millisecond inference."""

    def __init__(self, input_dim: int, hidden: int = 64, n_classes: int = 3):
        super().__init__()
        self.net = nn.Sequential(
            nn.Linear(input_dim, hidden),
            nn.ReLU(),
            nn.BatchNorm1d(hidden),
            nn.Linear(hidden, hidden),
            nn.ReLU(),
            nn.BatchNorm1d(hidden),
            nn.Linear(hidden, n_classes),
        )

    def forward(self, x: torch.Tensor) -> torch.Tensor:
        return self.net(x)

A assimetria de contagem de parâmetros é o ponto principal: um MLP de duas camadas com 64 unidades ocultas tem cerca de 8.000 parâmetros para uma tarefa de 60 recursos e 3 classes, contra um conjunto cuja contagem combinada chega a milhões.

O que o aluno retém e o que perde

Esta é a questão empírica fundamental e o artigo não a responde. A intuição é que o aluno acompanha o conjunto na distribuição e cai em regimes de tensão, onde a diversidade do conjunto está a fazer o trabalho - mas um valor de retenção significa apenas algo medido em dados reais da carteira de encomendas, dividido por regime, e reportado como ponderado F1. Um aluno que se mantém firme em dias calmos e desmaia durante uma cascata de liquidação é um produto diferente daquele que se degrada graciosamente, e um número agregado não consegue diferenciá-los.

Vale a pena testar três mitigações em relação a essa medição, em vez de afirmar antecipadamente:

  1. Inclua períodos de estresse no conjunto de destilação, para que o aluno veja os regimes onde se espera que a lacuna se abra.
  2. Destilação baseada em recursos — combine representações intermediárias, não apenas resultados finais.
  3. Regime auxiliar no aluno, forçando recursos com reconhecimento de regime no tronco compartilhado.

Autodestilação: quando o aluno se torna professor

Um modelo refinando sua própria representação

A autodestilação é uma técnica em que um modelo destila o conhecimento de si mesmo.

Redes Nascidas de Novo (BANs)

Treine um aluno com arquitetura idêntica à do professor. O aluno “nascido de novo” geralmente supera o original e o processo repete:

M0distillM1distillM2distillM_0 \xrightarrow{\text{distill}} M_1 \xrightarrow{\text{distill}} M_2 \xrightarrow{\text{distill}} \cdots

Cada geração treina com base em alvos fáceis da anterior, com ganhos tipicamente saturados após algumas gerações. Para modelos de negociação, isso não custa nada em termos de arquitetura — sem novos recursos, sem novos dados, apenas um procedimento de treinamento diferente — o que também significa que é barato testar e não há desculpa para relatá-lo como não testado.

Autodestilação em profundidade

Anexe classificadores auxiliares em camadas intermediárias. A saída mais profunda serve de professora para as mais rasas. Na inferência você escolhe uma saída: superficial para menor latência, profunda para máxima precisão.

Esta é a ideia que melhor se adapta a um sistema de negociação, porque a profundidade de saída se torna um botão de latência do tempo de execução: uma rede treinada cobre uma variedade de orçamentos em vez de se comprometer com uma única arquitetura no momento do treinamento. Quando o livro está se movendo rápido você pega a saída rasa e aceita uma posterior pior; quando está quieto você paga pela profundidade total. Ambas as curvas de precisão por saída e latência por saída são mensuráveis, e seu cruzamento decide se vale a pena ter o botão.

class SelfDistillingNet(nn.Module):
    """Network with early-exit classifiers for variable-latency inference."""

    def __init__(self, input_dim: int, n_classes: int = 3):
        super().__init__()
        self.block1 = nn.Sequential(
            nn.Linear(input_dim, 128), nn.ReLU(), nn.BatchNorm1d(128)
        )
        self.block2 = nn.Sequential(
            nn.Linear(128, 64), nn.ReLU(), nn.BatchNorm1d(64)
        )
        self.block3 = nn.Sequential(
            nn.Linear(64, 32), nn.ReLU(), nn.BatchNorm1d(32)
        )

        self.exit1 = nn.Linear(128, n_classes)
        self.exit2 = nn.Linear(64, n_classes)
        self.exit3 = nn.Linear(32, n_classes)  # final exit

    def forward(
        self, x: torch.Tensor, exit_layer: int = 3
    ) -> torch.Tensor:
        h1 = self.block1(x)
        if exit_layer == 1:
            return self.exit1(h1)

        h2 = self.block2(h1)
        if exit_layer == 2:
            return self.exit2(h2)

        h3 = self.block3(h2)
        return self.exit3(h3)

    def forward_all_exits(self, x: torch.Tensor):
        """Return logits from all exits (for self-distillation training)."""
        h1 = self.block1(x)
        h2 = self.block2(h1)
        h3 = self.block3(h2)
        return self.exit1(h1), self.exit2(h2), self.exit3(h3)


def self_distillation_step(
    model: SelfDistillingNet,
    x: torch.Tensor,
    y: torch.Tensor,
    temperature: float = 4.0,
    alpha: float = 0.5,
) -> torch.Tensor:
    """One training step with self-distillation from deepest exit."""
    logits_1, logits_2, logits_3 = model.forward_all_exits(x)

    loss_hard = F.cross_entropy(logits_3, y)

    loss_distill_1 = distillation_loss(
        logits_1, logits_3.detach(), y, temperature, alpha
    )
    loss_distill_2 = distillation_loss(
        logits_2, logits_3.detach(), y, temperature, alpha
    )

    return loss_hard + 0.5 * loss_distill_1 + 0.5 * loss_distill_2

De onde vem o orçamento de inferência

Orçamento de computação fluindo para um modelo rápido

A destilação só importa se a inferência tiver que ficar dentro de um orçamento rígido, e a escada completa do tick-to-trade - NIC-to-userspace, desvio do kernel, o total abaixo de 100 µs e o nível sub-10 µs que força o FPGA e a memória compartilhada - já está definido em dados e comunicação na negociação algorítmica. A linha que a escada deixa aberta é a inferência do modelo, e é a linha que a destilação está tentando preencher.

Resista ao preenchimento das outras linhas com uma tabela de latência de classe de modelo. Modelagem de propagação com aprendizado de máquina já publica a comparação GBM vs-deep-learning mais a ressalva que importa mais do que os números: a latência depende da implementação, e o mesmo modelo LightGBM leva dezenas de microssegundos por linha do Python, mas alguns microssegundos de um preditor compilado. Qualquer reivindicação de latência aqui deve nomear a estrutura, o núcleo e o tamanho do lote, ou será ruído.

Especificamente em GPUs: a sobrecarga fixa por inicialização deve ser amortizada antes que um dispositivo ajude, e a inferência de linha única fica bem à esquerda da linha do telhado, onde nunca está. Quando a GPU compensa mede essa curva de amortização adequadamente com uma varredura em lote, incluindo como uma placa PCIe discreta empurra a crista mais para a direita - leia isso em vez de confiar em uma constante citada na memória.

Quantização após destilação

Um aluno destilado comprime ainda mais: pesos INT8 (aproximadamente 2x na CPU com AVX-512 VNNI), pesos binários/ternários que transformam multiplicações em adições e poda para pular computação próxima de zero.

A afirmação tentadora é que a destilação seguida de quantização preserva mais precisão do que apenas a quantização, uma vez que o aluno já aprendeu uma representação compacta. Não envie nele. A armadilha de precisão da GPU é a posição do blog sobre precisão numérica reduzida: ele silenciosamente retornou lixo de aparência plausível, e o que tornou o caminho rápido distribuível foi uma porta de equivalência quantificada - preenchimentos deslocados, delta PnL em bps - não uma afirmação. Um aluno INT8 é um modelo diferente até que esse portão seja medido em relação ao aluno FP32.

import torch.quantization as quant

def quantize_student(student: nn.Module, calibration_loader: DataLoader):
    """Post-training static quantization for CPU deployment."""
    student.cpu()
    student.eval()
    student.qconfig = quant.get_default_qconfig("x86")

    student_prepared = quant.prepare(student)

    with torch.no_grad():
        for X, _ in calibration_loader:
            student_prepared(X)

    student_quantized = quant.convert(student_prepared)
    return student_quantized

Implantação de FPGA: o pipeline de destilação para bitstream

Modelo neural compacto cristalizando em hardware FPGA

FPGAs são a camada abaixo de 10 µs na escada de latência e a revisão de Tbricks/Broadridge cobre-os na produção junto com NICs de bypass de kernel - latência determinística, sem jitter do sistema operacional, co-localizado com a pilha de rede. O que não é abordado em nenhum lugar deste blog é como um modelo destilado chega a um.

Notas de produção do DeepLOB lista ONNX/TensorRT, quantização INT8 e implantação de FPGA como três opções e para por aí. É nisso que o terceiro se expande:

1. Train ensemble teacher (offline, GPU cluster, hours/days)
       |
2. Distill to small MLP student (offline, single GPU, minutes)
       |
3. Quantize student to INT8 / fixed-point (offline, CPU)
       |
4. Convert to HLS (High-Level Synthesis) or RTL
       |
5. Synthesize FPGA bitstream (offline, hours)
       |
6. Deploy to FPGA card in production server
       |
7. Inference: market data -> FPGA -> trading signal

A restrição de ligação é que o modelo deve caber nos elementos lógicos do dispositivo – LUTs, fatias DSP, bloco de RAM. Como um orçamento de ordem de grandeza, em vez de uma medida: um MLP de 2 camadas com 64 unidades ocultas e pesos INT8 é da ordem de 8.000 acumulações multiplicadas por inferência e ~16 KB de pesos, uma pequena fração de uma parte intermediária. É aqui que a destilação ganha seu sustento - o professor do conjunto não cabe em nenhum orçamento; o aluno não está nem perto do limite.

As ferramentas que automatizam PyTorch/ONNX para hardware sintetizável incluem AMD/Xilinx Vitis AI, hls4ml (do CERN) e FINN (da Xilinx Research).

Exemplo: Conversão hls4ml

import hls4ml
import onnx

dummy_input = torch.randn(1, 60)  # 60 input features
torch.onnx.export(student, dummy_input, "student.onnx", opset_version=13)

hls_config = hls4ml.utils.config_from_onnx_model(
    onnx.load("student.onnx"),
    granularity="name",
    default_precision="ap_fixed<16,8>",
    default_reuse_factor=1,          # full parallelism
)

hls_model = hls4ml.converters.convert_from_onnx_model(
    "student.onnx",
    hls_config=hls_config,
    output_dir="hls_student",
    backend="VivadoAccelerator",
    board="alveo-u250",
)

hls_model.compile()
hls_model.build(csim=True, synth=True)

hls_model.report()

hls_model.report() é a única fonte confiável de números de recursos e latência para um determinado modelo, placa, precisão e fator de reutilização - os números mudam substancialmente com default_reuse_factor sozinho. Citar uma tabela de síntese "típica" sem executá-la é adivinhação.

Considerações Práticas

Equilibrando forças de implantação de modelo prático

Pré-computando Logits do Professor

A destilação precisa de previsões do professor sobre todo o conjunto de treinamento – um custo off-line único que vale a pena pagar deliberadamente: execute o conjunto uma vez, persista os logits, treine os alunos contra o cache. Varreduras de temperatura e pesquisas de arquitetura não custam nada a mais nas passagens do professor, o que torna as varreduras acima práticas.

O único monitor específico para destilação

Higiene do pipeline de recursos, normalização contínua devido ao desvio dos parâmetros de pontuação z, monitoramento de mudança de distribuição de entrada e retreinamento acionado por regime são todos abordados na seção de produção do DeepLOB e aplicam-se inalterados aqui.

O monitor específico para destilação é divergência KL professor-aluno em dados ao vivo. O professor ainda existe offline; execute-o em uma amostra de entradas ao vivo e compare as distribuições. O aumento do KL significa que a aproximação do aluno é degradante em regimes em que não foi destilado – e dispara antes da precisão, porque não espera por rótulos. O limite de reciclagem deve ser calibrado em relação ao KL observado em períodos sabidamente bons e sabidamente degradados; escolhido a priori é arbitrário.

Quando não destilar

  • O professor já é pequeno (um modelo linear, um GBM raso): a destilação adiciona um estágio de pipeline para não haver compressão.
  • A latência não é uma restrição (rebalanceamento diário, sinais de fim do dia): implante o professor.
  • A interpretabilidade supera a velocidade: uma rede destilada é mais difícil de explicar do que o conjunto de árvores que ela substituiu.
  • A divisão em dois estágios já funciona: se o modelo lento assíncrono na arquitetura de modelagem de propagação estiver funcionando, a destilação terá que superá-lo em uma comparação medida antes de justificar a substituição de um sistema em funcionamento.

Resumo

Inteligência de mercado compactada em um núcleo de baixa latência

A destilação é uma alternativa coerente à divisão rápida/lenta de dois estágios: treinar o melhor professor que você puder pagar off-line, transferir sua estrutura de alvo flexível para um aluno pequeno o suficiente para o caminho quente, quantizar, implantar em CPU ou FPGA. A variante em profundidade vai além e torna a latência uma escolha de tempo de execução, em vez de uma escolha de tempo de treinamento.

O que este artigo deliberadamente não afirma é que nada disso supera o que o blog já publica. Esse veredicto precisa de três medições em dados reais da carteira de pedidos: a curva de retenção F1 ponderada entre aluno e conjunto dividida por regime, a varredura de temperatura e uma porta de paridade INT8 no estilo da armadilha de precisão da GPU. Até que existam, esta é uma descrição de uma técnica, não uma recomendação para implementá-la.

Referências

  1. Hinton, G., Vinyals, O., & Dean, J. (2015). Destilando o Conhecimento em uma Rede Neural. arXiv:1503.02531

  2. Furlanello, T., Lipton, ZC, Tschannen, M., Itti, L., & Anandkumar, A. (2018). Redes Neurais Nascidas de Novo. ICML. arXiv:1805.04770

  3. Zhang, L., Song, J., Gao, A., Chen, J., Bao, C., & Ma, K. (2019). Seja seu próprio professor: melhore o desempenho de redes neurais convolucionais por meio de autodestilação. ICCV. arXiv:1905.08094

  4. Romero, A., Ballas, N., Kahou, SE, Chassang, A., Gatta, C., & Bengio, Y. (2015). FitNets: dicas para redes finas e profundas. ICLR. arXiv:1412.6550

  5. Gou, J., Yu, B., Maybank, SJ e Tao, D. (2021). Destilação de Conhecimento: Uma Pesquisa. Jornal Internacional de Visão Computacional, 129, 1789-1819. arXiv:2006.05525

6.Duarte, J., et al. (2018). Inferência rápida de redes neurais profundas em FPGAs para física de partículas (hls4ml). Jornal de Instrumentação, 13, P07027. arXiv:1804.06913

  1. Umuroglu, Y., et al. (2017). FINN: Uma Estrutura para Inferência de Rede Neural Binarizada Rápida e Escalável. FPGA '17. arXiv:1612.07119

  2. Zhang, Z., Zohren, S. e Roberts, S. (2019). DeepLOB: Redes Neurais Convolucionais Profundas para Livros de Pedidos Limitados. Transações IEEE sobre processamento de sinais, 67(11), 3001-3012. arXiv:1808.03668

blog.disclaimer

Authors

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

Fique à frente do mercado

Assine nossa newsletter para insights exclusivos sobre trading com IA, análises de mercado e atualizações da plataforma.

Respeitamos sua privacidade. Cancele a inscrição a qualquer momento.