2
focar em
439
Seguidores

Uma exploração prática das estratégias de arbitragem com entrega à vista: as armadilhas entre o ideal e a realidade.

Criado em: 2025-11-28 14:22:49, atualizado em: 2025-12-16 11:31:06
comments   0
hits   345

Uma exploração prática das estratégias de arbitragem com entrega à vista: as armadilhas entre o ideal e a realidade.

Prefácio

Recentemente, um amigo me perguntou se eu poderia criar uma estratégia de arbitragem, algo que não existia na plataforma Inventor. Achei que não seria difícil, mas levei cerca de um mês para conseguir fazer a lógica básica funcionar. Olhando para trás agora, percebo que os obstáculos que encontrei desde a ideia inicial até a sua implementação foram muito mais numerosos do que eu imaginava.

Este artigo documenta os problemas práticos encontrados e as soluções desenvolvidas durante a elaboração desta estratégia de arbitragem.Apenas para fins de aprendizagem e referência; não possui valor prático de investimento.

A lógica básica da estratégia

Existe uma diferença de preço entre o contrato de entrega e o preço à vista, que normalmente flutua em torno de uma determinada média. Quando essa diferença de preço se desvia muito, teoricamente existem oportunidades de arbitragem.

A ideia inicial era simples:

  • Monitore a diferença de preço entre contratos à vista e contratos com entrega física.
  • Abra uma posição quando a diferença de preço exceder 2 vezes o desvio padrão.
  • Obtenha lucro fechando suas posições quando a diferença de preço retornar ao seu valor original.

Parece ótimo, não é? Mas, na prática, você descobrirá que existem inúmeros detalhes a serem considerados apenas na etapa de “abrir uma posição”.

O primeiro obstáculo: a estabilidade dos spreads de preços.

Inicialmente, usamos o desvio do spread de preços como um indicador direto, mas descobrimos que, às vezes, o spread de preços continuava a aumentar e nunca retornava ao seu estado anterior. Mais tarde, percebemos…Nem todos os spreads de preços são estáveis.

Principalmente à medida que a data de entrega se aproxima, o comportamento do spread pode mudar. Portanto, o teste ADF foi adicionado para determinar se a série do spread é estacionária.

function adfTest(series, maxLag=null){
  const n = series.length;
  if(n<10) throw new Error('series too short');
  if(maxLag===null) maxLag = Math.floor(12*Math.pow(n/100, 1/4));
  
  // ... ADF检验的核心计算逻辑
  
  const res = ols(rows, Ys);
  const tstat = tStat(res.beta, res.cov, 1);
  return { tStat: tstat, pValue: pval, usedLag: p };
}

Inicialmente, adicionamos vários testes, incluindo o teste da razão de variância, o teste da meia-vida e o teste KS, mas descobrimos que muitos testes reduziam significativamente o número de oportunidades para abrir posições. No final, simplificamos para apenas o teste ADF e definimos o limite do valor p em 0,1.

Mais importante ainda, um extra foi adicionado.contador de falhas contínuas

if (!adfPass) {
  stationarityFailCount[deliverySymbol] = (stationarityFailCount[deliverySymbol] || 0) + 1;
} else {
  stationarityFailCount[deliverySymbol] = 0;
}

let consecutiveFails = stationarityFailCount[deliverySymbol];
let canTrade = consecutiveFails < CONFIG.consecutiveFailThreshold;

A negociação é proibida se o teste falhar três vezes seguidas. Isso pode impedir a abertura de posições às cegas quando o mercado estiver em um estado anormal.

O segundo problema: a confusão em torno das estatísticas de lucros e prejuízos em tempo real.

Calcular lucros e prejuízos em uma conta de futuros é simples: basta observar as variações do USDT. Mas as contas à vista são diferentes, pois contêm tanto USDT quanto criptomoedas. Como calcular isso?

Eis um detalhe que passa facilmente despercebido:O custo de manter mercadorias à vista varia conforme as negociações.Por exemplo, se você comprar uma moeda por 100 USDT, vendê-la por 90 USDT e depois comprá-la de volta por 85 USDT, seu custo de aquisição não será mais o valor inicial de 100 USDT. Simplesmente usar o preço congelado no momento da abertura da posição para calcular o valor da moeda não refletirá a verdadeira situação de lucro e prejuízo.

A abordagem correta éExtraia o preço médio real da transação do objeto de pedido.

let openSpotPrice = (openSpotOrder && openSpotOrder.AvgPrice) ? 
  openSpotOrder.AvgPrice : record.openSpotPrice;
let closeSpotPrice = closeSpotOrder.AvgPrice || currentPair.spotPrice;

Em seguida, a taxa de retorno é calculada com base no preço real da transação:

// 正套:买现货+卖期货
if (record.direction === 'positive') {
  spotReturnRate = (closeSpotPrice - openSpotPrice) / openSpotPrice;
  deliveryReturnRate = (openDeliveryPrice - closeDeliveryPrice) / openDeliveryPrice;
} else {
  // 反套:卖现货+买期货
  spotReturnRate = (openSpotPrice - closeSpotPrice) / openSpotPrice;
  deliveryReturnRate = (closeDeliveryPrice - openDeliveryPrice) / openDeliveryPrice;
}

let totalReturnRate = spotReturnRate + deliveryReturnRate;
let requiredUSD = openSpotPrice * record.spotAmount;
let actualTotalPnl = totalReturnRate * requiredUSD;

Observe aqui a lógica de cálculo de lucros e prejuízos:

  • Conjunto regularNaquele momento, o mercado à vista estava comprado e o mercado futuro estava vendido, portanto o lucro/prejuízo para o mercado à vista = (preço de fechamento - preço de abertura) / preço de abertura, e o lucro/prejuízo para o mercado futuro = (preço de abertura - preço de fechamento) / preço de abertura.
  • reverterNaquela época, o mercado à vista envolvia a venda a descoberto, enquanto o mercado futuro envolvia a compra, em direções opostas.

Por fim, o lucro ou prejuízo real de cada transação é somado para obter o lucro ou prejuízo total:

accumulatedProfit += actualTotalPnl;
_G('accumulatedProfit', accumulatedProfit);

A terceira grande armadilha: a armadilha da liquidez.

Este é o verdadeiro problema. Por que, após 10 anos de operação, a Plataforma Quantitativa Inventor possui tão poucas estratégias de arbitragem para contratos futuros? A resposta é simples:Liquidez insuficiente no mercado de contratos de entrega.

Pergunta 1: Transação de uma única perna

A arbitragem não é um conto de fadas onde você abre posições simultaneamente. A realidade é:

  • A ordem à vista foi executada, mas a ordem futura ainda está pendente.
  • Ou a ordem futura foi executada, mas a ordem à vista foi cancelada.

Este é um exemplo clássico de “risco unilateral”. Uma perna está dentro, enquanto a outra permanece fora. Nesse ponto, qualquer flutuação de preço deixa de ser uma arbitragem e passa a ser uma posição unilateral.

A solução é se juntarMecanismo de reversão

if (!deliveryOrder) {
  Log('❌ 期货卖单失败,回滚现货');
  exchanges[0].CreateOrder(pair.spotSymbol, 'sell', -1, spotAmount);
  addCooldown(pair.deliverySymbol, pair.coin, '期货卖单失败,已回滚现货');
  return false;
}

Se alguma das operações falhar, coloque imediatamente uma ordem a mercado para encerrar a operação já executada, reduzindo a exposição ao risco dessa operação específica.

Pergunta 2: Ordens de mercado também podem ser rejeitadas.

Por mais absurdo ainda, às vezes as ordens a mercado também falham. Isso pode ser devido aos controles de risco da bolsa ou à liquidez insuficiente do mercado; em resumo, a ordem simplesmente não é executada.

Então eu fiz isso.Mecanismo duplo de ordem de mercado + ordem limitada

function createOrderWithFallback(exchange, symbol, direction, amount, limitPrice, orderType, maxRetry = 3) {
  let useMarketOrder = (limitPrice === -1);
  
  // 先尝试限价单
  if (!useMarketOrder) {
    orderId = exchange.CreateOrder(symbol, direction, limitPrice, amount);
    if (!orderId) {
      Log(`❌ 限价单提交失败,改用市价单`);
      useMarketOrder = true;
    }
  }
  
  // 限价单失败则用市价单
  if (useMarketOrder && !orderId) {
    orderId = exchange.CreateOrder(symbol, direction, -1, marketAmount);
  }
  
  // ... 检查订单状态,失败则重试
}

O sistema pode tentar novamente no máximo 3 vezes, sendo que cada tentativa utiliza uma ordem de mercado como rede de segurança.

Pergunta 3: A armadilha do montante em ordens de compra à vista

Essa armadilha está particularmente bem escondida e exige extrema cautela. A quantidade para uma ordem no mercado futuro é…Número de moedasNo entanto, a quantidade solicitada ao comprar uma ordem no mercado à vista é…Valor em USDT

Aqui, foi adicionada especificamente uma lógica de conversão:

function getActualAmount(useMarket) {
  if (isSpotBuy && useMarket) {
    // 现货市价买单:需要用USDT金额
    let currentPrice = getDepthMidPrice(exchange, symbol);
    let usdtAmount = amount * currentPrice;
    Log(`  💡 现货买单转换: ${amount.toFixed(6)} 币 → ${usdtAmount.toFixed(4)} USDT`);
    return usdtAmount;
  }
  return amount;
}

A quantidade de criptomoeda usada em uma ordem limitada é automaticamente convertida em USDT para uma ordem a mercado.

A quarta armadilha: a ilusão das oportunidades de arbitragem.

Outro problema frustrante é que um sinal de arbitragem é detectado e você está pronto para abrir uma posição, mas a oportunidade já desapareceu no momento em que você faz o pedido.

Os preços flutuam em tempo real e as condições de mercado podem ter mudado entre a detecção do sinal e a execução efetiva da posição. Os spreads de preço podem ter diminuído e as oportunidades de arbitragem podem ter desaparecido. Se, mesmo assim, você abrir uma posição nesse momento, estará apenas desperdiçando taxas de comissão.

Então foi adicionado.Mecanismo de confirmação secundário

// 开仓前重新获取实时价格并验证套利机会
Log('🔄 重新获取实时Depth盘口价格并验证套利机会...');

let realtimeSpotPrice = getDepthMidPrice(exchanges[0], pair.spotSymbol, true);
let realtimeDeliveryPrice = getDepthMidPrice(exchanges[1], pair.deliverySymbol, true);

let realtimeSpread = realtimeDeliveryPrice - realtimeSpotPrice;
let realtimeSpreadRate = realtimeSpread / realtimeSpotPrice;

// 重新计算实时Z-Score
let realtimeZScore = (realtimeSpreadRate - mu) / (sigma || 1e-6);

// 验证:实时Z-Score是否仍然满足开仓条件
if (absRealtimeZ < CONFIG.zScoreEntry) {
  Log('❌ 套利机会已消失!');
  Log('  取消开仓,避免亏损');
  return false;
}

Antes de efetivamente efetuar uma ordem, verifique novamente o preço em tempo real, recalcule o Z-Score e execute a ordem somente se tiver certeza de que a oportunidade ainda existe.

A quinta armadilha: Problemas herdados relacionados a posições em contratos futuros.

Às vezes, quando uma estratégia é reiniciada ou uma posição anterior é encerrada, podem existir posições residuais na conta de futuros. Se essas posições não forem resolvidas, novas posições se sobreporão às antigas, levando a um tamanho de posição descontrolado.

Então foi adicionado.Liquidação forçada antes da abertura de uma posiçãoA lógica:

// 检查期货现有仓位并平仓
let existingPosition = getPositionBySymbol(pair.deliverySymbol);

if (existingPosition && Math.abs(existingPosition.Amount) > 0) {
  Log('⚠️ 检测到该合约的现有仓位,执行平仓操作...');
  
  let closeDirection = existingPosition.Type === PD_LONG ? 'closebuy' : 'closesell';
  let closeAmount = Math.abs(existingPosition.Amount);
  
  let closeOrder = createOrderWithFallback(
    exchanges[1],
    pair.deliverySymbol,
    closeDirection,
    closeAmount,
    -1,
    '期货'
  );
  
  if (!closeOrder) {
    Log('❌ 平仓现有持仓失败,终止开仓');
    addCooldown(pair.deliverySymbol, pair.coin, '平仓现有持仓失败');
    return false;
  }
}

Antes de abrir uma posição, verifique-a primeiro. Se houver posições restantes, encerre-as para garantir que sua conta esteja limpa.

A sexta grande armadilha: a defasagem dos dados do Ticker.

Este é todo o processo de desenvolvimento da estratégia.Mais oculto e mais mortalUm dos problemas.

Após a estratégia entrar em execução, um fenômeno estranho foi observado:

  • Foi detectado um sinal de arbitragem e é hora de abrir uma posição.
  • O preço ideal da ordem limitada é calculado adicionando e subtraindo a diferença de preço do preço do bilhete.
  • Como resultado, o pedido permaneceu pendente, aguardando para ser atendido.
  • Após uma longa espera sem que a transação fosse concluída, o pedido foi cancelado.

Tente usar ordens a mercado. O resultado foi ainda pior:

  • A ordem de mercado foi executada com sucesso.
  • No entanto, o preço da transação foi completamente diferente do spread de arbitragem esperado.
  • A oportunidade de arbitragem planejada acabou se mostrando não lucrativa após a conclusão da transação.

O que exatamente aconteceu? Após repetidas comparações com os dados de negociação em tempo real da bolsa, o problema foi finalmente descoberto:

Ticker vs. Profundidade: A Diferença Fundamental entre Dados

Os dados do ticker refletem o preço da transação real mais recente.Isso parece ótimo, mas para mercados com baixa liquidez, como contratos de entrega, surgem problemas:

时间轴:
10:00:00 - 有人以50000成交了1张合约 → Ticker价格更新为50000
10:00:05 - 盘口挂单:买49800 / 卖50200(但没有成交)
10:00:10 - 盘口挂单:买49850 / 卖50150(但没有成交)
...
10:05:00 - Ticker价格仍然是50000(因为5分钟内没有新的成交)

Você notou o problema?O preço de 50.000 do Ticker já era história há 5 minutos.No entanto, o preço de mercado atual (preço da carteira de pedidos) pode ter se tornado 4985050150.

Se você usar o preço de cotação de 50.000 para calcular oportunidades de arbitragem e inserir ordens limitadas, então:

  1. Erro de julgamentoOs sinais de arbitragem são calculados com base em preços desatualizados.
  2. Pedido falhouO preço na ordem limite está muito distante do preço real de mercado, tornando impossível concluir a transação.
  3. Perda de mercadoUma ordem a mercado foi usada para forçar uma negociação, mas o preço real foi completamente diferente do esperado.

Por que os tickers para contratos de entrega são particularmente pouco confiáveis?

A liquidez dos contratos de entrega é muito pior do que a dos contratos à vista:

  • Mercado SpotUm grande número de transações ocorre a cada segundo, e os preços no Ticker são atualizados quase em tempo real, com muito pouco atraso.
  • Contrato de EntregaUma transação pode demorar vários minutos ou até mais para ser concluída; o preço no Ticker apresenta um atraso significativo.

Para contratos com baixa liquidez, o desvio entre o preço de mercado e o preço real da carteira de ordens pode atingir os seguintes valores:

  • Valores normais: 0,1% - 0,5%
  • Período de flutuação: 1% a 3% ou até mais

Para estratégias de arbitragem, esse desvio é fatal. A vantagem esperada na diferença de preço pode ser de apenas 0,5%, mas o preço real da transação acaba sendo completamente diferente.

Solução: Substitua Ticker pelos dados de profundidade do disco.

Já que o Ticker não é confiável, vamos usar…Dados de profundidade (profundidade do livro de ordens)

function getDepthMidPrice(exchange, symbol, logDetail = false) {
    let depth = exchange.GetDepth(symbol);
    if (!depth || !depth.Bids || depth.Bids.length === 0 || 
        !depth.Asks || depth.Asks.length === 0) {
        Log(`❌ 获取${symbol}盘口失败`);
        return null;
    }
    
    let bestBid = depth.Bids[0].Price;  // 最优买价
    let bestAsk = depth.Asks[0].Price;  // 最优卖价
    let midPrice = (bestBid + bestAsk) / 2;  // 中间价
    
    if (logDetail) {
        let spread = bestAsk - bestBid;
        let spreadRate = spread / midPrice * 100;
        Log(`📊 ${symbol} 盘口: Bid=${bestBid.toFixed(2)}, Ask=${bestAsk.toFixed(2)}, Mid=${midPrice.toFixed(2)}, Spread=${spread.toFixed(2)} (${spreadRate.toFixed(3)}%)`);
    }
    
    return midPrice;
}

Vantagens dos dados de profundidade:

  • Em tempo realReflete o estado real atual da carteira de ordens, sem qualquer atraso.
  • precisãoSeu pedido será comparado com esses livros de pedidos, e esse é o preço real de mercado.
  • OperacionalidadeOrdens limitadas calculadas com base nos preços do livro de ofertas têm maior probabilidade de serem executadas.

Sistema de precificação dupla de estratégia

Finalmente, foi adotado.Solução híbrida de Ticker + Depth

1. Utilize o Ticker para manter sequências de dados históricos.

// 用Ticker更新历史价差序列(保持连续性)
let spotTicker = exchanges[0].GetTicker(pair.spotSymbol);
let deliveryTicker = exchanges[1].GetTicker(pair.deliverySymbol);

pair.spotPrice = spotTicker.Last;
pair.deliveryPrice = deliveryTicker.Last;
pair.spread = pair.deliveryPrice - pair.spotPrice;

// 历史序列用于ADF检验、Z-Score计算
priceHistory[pair.deliverySymbol].push({
    time: Date.now(),
    spreadRate: pair.spread / pair.spotPrice,
    spread: pair.spread,
    spotPrice: pair.spotPrice,
    deliveryPrice: pair.deliveryPrice
});

Por que o Ticker ainda é usado para dados históricos? Porque é necessário.Continuidade de dadosSe os dados históricos também forem representados usando a Profundidade, as flutuações nos preços da carteira de pedidos causarão descontinuidades na sequência histórica, afetando a precisão da análise estatística.

2. Utilize a profundidade para avaliação em tempo real e verificação de abertura de posição.

// 开仓前用Depth重新验证套利机会
let realtimeSpotPrice = getDepthMidPrice(exchanges[0], pair.spotSymbol, true);
let realtimeDeliveryPrice = getDepthMidPrice(exchanges[1], pair.deliverySymbol, true);

// 基于Depth价格重新计算Z-Score
let realtimeSpread = realtimeDeliveryPrice - realtimeSpotPrice;
let realtimeSpreadRate = realtimeSpread / realtimeSpotPrice;
let realtimeZScore = (realtimeSpreadRate - mu) / (sigma || 1e-6);

// 二次验证:套利机会是否仍然存在
if (Math.abs(realtimeZScore) < CONFIG.zScoreEntry) {
    Log('❌ 套利机会已消失(基于Depth实时价格)');
    return false;
}

3. Calcule o preço da ordem limite usando a profundidade.

// 基于Depth价格和平均价差计算限价单价格
let spreadDeviation = realtimeSpread - avgSpread;
let adjustmentRatio = Math.min(
    Math.abs(spreadDeviation) * CONFIG.limitOrderSpreadRatio,
    spreadStd * 0.5
);

if (direction === 'positive') {
    spotLimitPrice = realtimeSpotPrice + adjustmentRatio;
    deliveryLimitPrice = realtimeDeliveryPrice - adjustmentRatio;
} else {
    spotLimitPrice = realtimeSpotPrice - adjustmentRatio;
    deliveryLimitPrice = realtimeDeliveryPrice + adjustmentRatio;
}

O preço da ordem limite calculado desta forma baseia-se no livro de ordens real, o que aumenta consideravelmente a probabilidade de execução.

4. Calcule o lucro e a perda em tempo real usando a Profundidade.

function calculateUnrealizedPnL(record, currentPair) {
    // 优先用Depth价格计算实时盈亏
    let currentSpotPrice = getDepthMidPrice(exchanges[0], currentPair.spotSymbol);
    let currentDeliveryPrice = getDepthMidPrice(exchanges[1], currentPair.deliverySymbol);
    
    // Depth获取失败才回退到Ticker
    if (!currentSpotPrice || !currentDeliveryPrice) {
        currentSpotPrice = currentPair.spotPrice;
        currentDeliveryPrice = currentPair.deliveryPrice;
    }
    
    // 计算盈亏...
}

Comparação dos efeitos reais de combate

Problemas com o uso do Ticker:

检测到套利信号(基于Ticker)
→ 计算限价单价格
→ 下单等待
→ 长时间不成交(价格已经不对了)
→ 改用市价单
→ 成交价格和预期差很多
→ 套利失败或微利

Melhorias após o uso do Depth:

检测到套利信号(基于Ticker历史)
→ 用Depth重新验证(机会仍在)
→ 基于Depth计算限价单价格
→ 下单,价格贴近盘口
→ 较快成交
→ 成交价格符合预期
→ 套利成功

Otimização da precificação de ordens com limite de preço

Se formos usar ordens limitadas, como definimos o preço? Se o definirmos de forma muito agressiva, a transação não será concluída; se o definirmos de forma muito conservadora, não conseguiremos um bom preço.

Com base no preço da profundidade, a abordagem aqui é:Ajuste dinâmico com base no desvio entre o spread de preço atual e o spread de preço médio.

let spreadDeviation = realtimeSpread - avgSpread;
let adjustmentRatio = Math.min(
  Math.abs(spreadDeviation) * CONFIG.limitOrderSpreadRatio,
  spreadStd * 0.5
);

// 限制调整幅度在合理区间
let minAdjustment = realtimeSpotPrice * 0.0005;
let maxAdjustment = realtimeSpotPrice * 0.005;
adjustmentRatio = Math.max(minAdjustment, Math.min(maxAdjustment, adjustmentRatio));

Se for um conjunto completo (com uma grande diferença de preço):

  • Preço de compra à vista = Ponto médio da profundidade + intervalo de ajuste
  • Preço de venda de contratos futuros = Ponto médio da profundidade - Faixa de ajuste

Isso permite que as transações sejam concluídas com uma diferença de preço favorável, evitando ficar muito distante do livro de ofertas e, assim, não resultar em uma transação perdida.

Mecanismo de período de arrefecimento

Qualquer tentativa frustrada de abrir uma posição indica um problema no mercado, que pode ser devido à liquidez insuficiente ou à volatilidade excessiva. Nesses casos, não se deve tentar novamente imediatamente, mas sim manter a calma.

Portanto, uma penalidade foi adicionada a cada par de negociação com falha.Resfriamento de 10 minutos

function addCooldown(deliverySymbol, coin, reason) {
  pairCooldowns[deliverySymbol] = Date.now() + CONFIG.cooldownDuration;
  Log(`⏸️ ${deliverySymbol} 进入10分钟冷却期`);
  Log(`   原因: ${reason}`);
  _G('pairCooldowns', pairCooldowns);
}

Durante o período de suspensão, nenhuma posição será aberta para este par de negociação para evitar falhas repetidas e desperdício de taxas de transação.

Deficiências atuais e áreas para melhoria

Essa estratégia ainda está em desenvolvimento e há muitas áreas que podem ser otimizadas:

1. Problema de atraso Atualmente, os preços são obtidos por meio de um método de polling, o que resulta em uma latência significativa. A mudança para o WebSocket para atualizações de preços em tempo real melhoraria consideravelmente a velocidade de resposta.

2. Otimização do controle de riscos O método atual de stop-loss é relativamente simples e direto, e você pode considerar o seguinte:

  • Stop loss dinâmico (ajustado com base na volatilidade)
  • Stop-loss baseado em tempo (liquidação forçada devido a tempo de retenção excessivo)
  • Controle de retirada máxima

3. Gestão de Deslizamentos A estratégia de precificação para ordens limitadas pode ser aprimorada, por exemplo, ajustando-se dinamicamente com base em fatores como a profundidade do livro de ofertas e o volume recente de transações.

4. Outras aplicações dos dados de profundidade Ela pode analisar o desequilíbrio da carteira de ordens, prever tendências de preços e melhorar a taxa de sucesso da arbitragem.

Resumir

Estratégias de arbitragem parecem atraentes, mas, na prática, é evidente que inúmeras armadilhas separam o ideal da realidade.

  • Armadilhas dos testes de estacionariedade
  • Armadilhas nas Estatísticas de Lucros e Perdas
  • A armadilha da liquidez insuficiente
  • Os perigos das transações de uma só perna
  • Armadilhas da falha de ordem de mercado
  • Armadilhas no valor da compra à vista
  • A armadilha das oportunidades de arbitragem que desaparecem
  • O poço das posições residuais
  • A falha mais grave é a defasagem no mecanismo do Ticker.

Em particular, a questão dos dados defasados ​​do Ticker é um problema em todo o processo de desenvolvimento da estratégia.O mais facilmente ignorado, mas com o maior impacto.As armadilhas. Para mercados de contratos de entrega com baixa liquidez:

Princípio fundamental: Use o Ticker para manter a continuidade histórica e use a Profundidade para aproveitar as oportunidades em tempo real.

  • O Ticker é adequado para análise de dados históricos (teste ADF, cálculo do escore Z).
  • A profundidade de processamento é adequada para julgamento em tempo real e execução de negociações (verificação de abertura de posição, precificação de ordens limitadas, cálculo de lucros e perdas).

Este artigo registra os problemas encontrados e as soluções encontradas durante o processo de exploração, e espera-se que possa servir de referência para todos.Para reiterar, este artigo tem fins exclusivamente educativos e de discussão. O código ainda está em desenvolvimento e não deve ser usado diretamente em negociações reais.

Se você utiliza uma estratégia semelhante, fique à vontade para discuti-la comigo. O mercado é complexo, e é justamente essa complexidade que torna a negociação quantitativa tão desafiadora.

Código fonte da estratégia: https://www.fmz.com/strategy/519280