Commodity Futures High Frequency Trading Strategy escrito em C++

Autora:Bem-estar, Criado: 2020-05-22 15:28:11, Atualizado: 2023-11-02 19:54:28

img

Penny Jump Commodity Futures High Frequency Trading Strategy escrito em C++

Resumo

O mercado é o campo de batalha, o comprador e o vendedor estão sempre no jogo, que também é o tema eterno do negócio de negociação.

Classificação da estratégia de alta frequência

Na negociação de alta frequência, existem dois tipos principais de estratégias. A estratégia do lado do comprador e a estratégia do lado do vendedor. A estratégia do lado do vendedor é geralmente uma estratégia de criação de mercado, e os dois lados dessas estratégias são adversários. Por exemplo, a estratégia do comprador de arbitragem de alta frequência de suavizar todos os fenômenos irracionais no mercado na velocidade mais rápida, tomando a iniciativa de atacar o preço rapidamente ou comer o preço errado de outros criadores de mercado.

Há também uma maneira de analisar os dados históricos ou as regras de ordens do mercado, enviar as ordens pendentes a um preço razoável com antecedência e enviar as ordens de retirada com a rápida mudança do preço de mercado. Tais estratégias são comuns na criação de mercado passivo, uma vez que as ordens pendentes são executadas, e após um certo lucro ou após atingir a condição de stop-loss, a posição será fechada.

Qual é a estratégia do Penny Jump?

Penny Jump traduzido para o inglês é o significado de aumento de micro-preço. O princípio é rastrear o preço de compra e o preço de venda do mercado. Então, de acordo com o preço do mercado, mais ou menos o aumento de micro-preço do preço de rastreamento, é óbvio que esta é uma estratégia de negociação passiva, pertence ao lado do vendedor estratégia de criação de mercado. Seu modelo de negócios e lógica é conduzir transações bilaterais em ordens de limite listadas em bolsa para fornecer liquidez.

A estratégia de criação de mercado requer uma certa quantidade de estoque na mão e, em seguida, negocia tanto no lado do comprador quanto do vendedor. A principal renda desta estratégia é o retorno da taxa de comissão fornecida pela bolsa, bem como a diferença de preço ganha comprando baixo e vendendo alto.

Princípio da estratégia Penny Jump

Sabemos que há muitos investidores de varejo no mercado de negociação, e também há muitos grandes investidores, como: hot money, fundos públicos, fundos privados, e assim por diante. investidores de varejo geralmente têm menos fundos, suas ordens têm um impacto muito pequeno no mercado, eles podem facilmente comprar e vender um alvo de negociação a qualquer momento.

Se um grande investidor quer comprar 500 lotes de petróleo bruto, não há tantas ordens no preço atual para venda, e o investidor não quer comprá-los no preço mais alto. Se eles insistem em enviar a ordem de compra no preço atual, o custo dos pontos de deslizamento será muito grande. portanto, ele tem que enviar uma ordem pendente no preço desejado. Todos os participantes do mercado verão uma ordem de compra hugh mostrando no determinado preço.

Por causa desta ordem enorme, parece desajeitado no mercado, às vezes chamamos de "ordens de elefante".

Selling Price 400.3, Order volume 50; buying price 400.1, Order volume 10. 

De repente, este elefante engorroso salta para o mercado, e o preço da oferta foi enviado ao preço de 400.1.

Selling Price 400.3, Order volume 50; Buying price 400.1, Order volume 510.

Todos os traders sabem que se houver uma grande quantidade de ordens pendentes a um determinado preço, então esse preço formará um forte suporte ou resistência.

Selling Price 400.3, Order volume 50; Buying price 400.2, Order volume 1,

O preço 400.1 torna-se Compra 2 preço na profundidade da carteira de ordens.

Mesmo que o preço não suba, na posição de comprar 2, ainda há um elefante segurando o preço, e ele pode ser rapidamente vendido de volta ao elefante no preço de 400.1. Esta é a idéia geral da estratégia Penny Jump. Sua lógica é tão simples quanto isso, monitorando o estado da ordem do mercado, especular as intenções do oponente, e depois tomar a liderança na construção de uma posição favorável, e finalmente lucrar com um pequeno spread em um curto período de tempo.

Implementação da estratégia Penny Jump

Primeiro, observe as oportunidades de negociação com uma probabilidade muito baixa do mercado e faça estratégias correspondentes de acordo com a lógica de negociação. Se a lógica for complexa, você precisa usar o conhecimento matemático existente, usar o modelo para descrever a natureza do fenômeno irracional tanto quanto possível e minimizar o sobreajuste. Além disso, ele deve ser verificado por um mecanismo de backtest que possa atender ao princípio Price first then Volume first. Felizmente, temos a plataforma FMZ Quant que atualmente suporta esses modos de backtesting.

Qual é o significado de suportar o mecanismo de backtest Price first then Volume first? Você pode entendê-lo como: você envia uma ordem pendente em 400.1 para comprar, apenas quando o preço de venda na profundidade do livro de ordens é 400.1 ou inferior, sua ordem pendente pode ser fechada. Ele apenas calcula os dados de preço das ordens pendentes e não calcula os dados de volume das ordens pendentes, que apenas atende à prioridade de preço ((preço primeiro) nas regras de correspondência de ordens de troca.

O Volume first é uma versão atualizada do price first. É prioritário em termos de preço e de tempo. Pode-se dizer que este modo de correspondência é exatamente o mesmo que o modelo de troca. Ao calcular o valor da ordem pendente, é julgado se a ordem pendente atual atinge a condição de transação passiva para realizar a transação de volume, a fim de alcançar uma simulação real do ambiente real do mercado.

Além disso, alguns leitores podem achar que a estratégia Penny Jump requer oportunidades de negociação de mercado, ou seja, a necessidade do mercado tem pelo menos duas lacunas de preço hop. Sob circunstâncias normais, o principal contrato de negociação de futuros de commodities é relativamente busy. A diferença entre Buying 1 e Selling 1 hop é que quase não há chance de negociação. Portanto, colocamos nossa energia no contrato sub-primário onde a negociação não é muito ativa. Este tipo de contrato de negociação ocasionalmente tem duas ou até três oportunidades de hop. Por exemplo, no contrato MA (código Metanol em futuros de commodities chineses) 1909, a seguinte situação ocorre:

img

Vender 1 preço 2225 com volume 551, Comprar 1 preço 2223 com volume 565, olhar para baixo por alguns segundos. Depois que isso acontece, ele desaparecerá após vários tiques. Neste caso, consideramos o mercado como autocorreção. O que temos que fazer é recuperar. Antes que o mercado o corrija ativamente. se fizermos manualmente, seria impossível, com a ajuda da negociação automática, podemos torná-lo possível.

A situação de aparição de duas diferenças de preço ocorre com muita frequência, mas os três saltos são os mais seguros, mas os três saltos raramente ocorrem, resultando na frequência de negociação é muito baixa.

Em seguida, observamos a diferença entre o anterior Vender 1 Comprar 1 e o Comprar 1 Vender 1 agora. A fim de preencher a lacuna de preço entre o mercado, se a velocidade for rápida o suficiente, pode ser colocada na vanguarda de outras ordens. Além disso, o tempo de detenção da posição é muito curto, com essa lógica de negociação, após a realização da estratégia, tome o MA909 como exemplo, o teste de mercado real recomenda o Esunny em vez da interface CTP, o mecanismo de mudança de posição e situação de fundo para o Esunny é por dados empurrados, muito adequado para negociação de alta frequência.

Código de estratégia

Depois de limpar a lógica de negociação, podemos usar o código para alcançá-lo. Uma vez que a plataforma FMZ Quant usa C ++ exemplos de estratégia de escrita são muito poucos, aqui usamos C ++ para escrever esta estratégia, que é conveniente para todos aprenderem, e a variedade é commodity futures.fmz.com> Login > Dashboard > biblioteca de estratégia > Nova estratégia > Clique no menu suspenso no canto superior esquerdo > Selecione C ++ para começar a escrever a estratégia, preste atenção aos comentários no código abaixo.

  • Passo 1: Primeiro, construir a estrutura da estratégia, na qual uma classe HFT e uma função principal são definidas. A primeira linha na função principal é limpar o log. O objetivo disso é limpar as informações do log executadas anteriormente toda vez que a estratégia é reiniciada. A segunda linha é filtrar algumas mensagens de erro que não são necessárias, como atraso de rede e algumas dicas aparecem, para que o log apenas registre informações importantes e pareça mais limpo; a terceira linha é imprimir a mensagem Init OK, o que significa que o programa começou a iniciar. A quarta linha é criar um objeto de acordo com a classe HFT, e o nome do objeto é hft; a quinta linha programa entra no loop enquanto, e sempre executa o loop no método hft, pode-se ver que o método Loop é a lógica deste programa.

Em seguida, vamos olhar para a classe HFT, que tem cinco métodos. O primeiro método é o método de construção; o segundo método é obter o dia atual da semana para determinar se é uma nova linha K; o terceiro método é principalmente cancelar todas as ordens não preenchidas e obter informações detalhadas da posição, porque antes de a ordem ser colocada, ela deve primeiro determinar o status da posição atual; o quarto método é usado principalmente para imprimir algumas informações, para esta estratégia, este método não é o principal; o mais importante é o quinto método, Este método é principalmente responsável pelo processamento da lógica de negociação e colocação de ordens.

/ / Define the HFT class
Class HFT {
     Public:
         HFT() {
             // Constructor
         }
        
         Int getTradingWeekDay() {
             // Get the current day of the week to determine if it is a new K line
         }
        
         State getState() {
             / / Get order data
         }

         Void stop() {
             // Print orders and positions
         }
        
         Bool Loop() {
             // Strategy logic and placing orders
         }
};

// main function
Void main() {
     LogReset(); // clear the log
     SetErrorFilter("ready|timeout"); // Filter error messages
     Log("Init OK"); // Print the log
     HFT hft; // Create HFT object
     While (hft.Loop()); // enter loop
     Log("Exit"); // Program exits, prints the log
}

Então, vamos ver como cada um dos métodos nesta classe HFT é implementado, e como o método mais básico Loop funciona. De cima para baixo, vamos implementar a implementação específica de cada método um por um, e você vai descobrir que a estratégia de alta frequência original é tão simples. Antes de falar sobre a classe HFT, nós primeiro definimos várias variáveis globais para armazenar os resultados do cálculo do objeto hft. Eles são: armazenar status de ordem, status de posição, manter posição longa, manter posição curta, preço de compra, quantidade de compra, preço de venda, quantidade de venda. Veja o código abaixo:

/ / Define the global enumeration type State
Enum State {
     STATE_NA, // store order status
     STATE_IDLE, // store position status
     STATE_HOLD_LONG, // store long position directions
     STATE_HOLD_SHORT, // store short position direction
};

/ / Define global floating point type variable
Typedef struct {
     Double bidPrice; // store the buying price
     Double bidAmount; // store the buying amount
     Double askPrice; // store the selling price
     Double askAmount; // store the selling amount
} Book;

Com as variáveis globais acima, podemos armazenar os resultados calculados pelo objeto hft separadamente, o que é conveniente para chamadas subsequentes pelo programa. Em seguida, falaremos sobre a implementação específica de cada método na classe HFT. Primeiro, o primeiro método HFT é um construtor que chama o segundo método getTradingWeekDay e imprime o resultado no log. O segundo método getTradingWeekDay obtém o dia atual da semana para determinar se é uma nova linha K. Também é muito simples de implementar, obter o carimbo horário, calcular a hora e a semana e, finalmente, retornar o número de semanas; o terceiro método getState é um pouco longo, vou apenas descrever a ideia geral, para explicação específica, você pode olhar para os comentários no seguinte bloco de codificação.

Em seguida, vamos obter todas as ordens primeiro, retornar o resultado é uma matriz normal, em seguida, atravessar esta matriz, um por um para cancelar a ordem, em seguida, obter os dados de posição, retornar uma matriz, e depois atravessar esta matriz, obter informações de posição detalhada, incluindo: direção, posição, ontem ou posição atual, etc, e finalmente retornar o resultado; o quarto método de parada é imprimir informações; o código é o seguinte:

Public:
    // Constructor
    HFT() {
        _tradingDay = getTradingWeekDay();
        Log("current trading weekday", _tradingDay);
    }
    
    // Get the current day of the week to determine if it is a new K line
    Int getTradingWeekDay() {
        Int seconds = Unix() + 28800; // get the timestamp
        Int hour = (seconds/3600)%24; // hour
        Int weekDay = (seconds/(60*60*24))%7+4; // week
        If (hour > 20) {
            weekDay += 1;
        }
        Return weekDay;
    }
    
    / / Get order data
    State getState() {
        Auto orders = exchange.GetOrders(); // Get all orders
        If (!orders.Valid || orders.size() == 2) { // If there is no order or the length of the order data is equal to 2
            Return STATE_NA;
        }
        
        Bool foundCover = false; // Temporary variable used to control the cancellation of all unexecuted orders
        // Traverse the order array and cancel all unexecuted orders
        For (auto &order : orders) {
            If (order.Id == _coverId) {
                If ((order.Type == ORDER_TYPE_BUY && order.Price < _book.bidPrice - _toleratePrice) ||
                    (order.Type == ORDER_TYPE_SELL && order.Price > _book.askPrice + _toleratePrice)) {
                    exchange.CancelOrder(order.Id, "Cancel Cover Order"); // Cancel order based on order ID
                    _countCancel++;
                    _countRetry++;
                } else {
                    foundCover = true;
                }
            } else {
                exchange.CancelOrder(order.Id); // Cancel order based on order ID
                _countCancel++;
            }
        }
        If (foundCover) {
            Return STATE_NA;
        }
        
        // Get position data
        Auto positions = exchange.GetPosition(); // Get position data
        If (!positions.Valid) { // if the position data is empty
            Return STATE_NA;
        }

        // Traverse the position array to get specific position information
        For (auto &pos : positions) {
            If (pos.ContractType == Symbol) {
                _holdPrice = pos.Price;
                _holdAmount = pos.Amount;
                _holdType = pos.Type;
                Return pos.Type == PD_LONG || pos.Type == PD_LONG_YD ? STATE_HOLD_LONG : STATE_HOLD_SHORT;
            }
        }
        Return STATE_IDLE;
    }
    
    // Print orders and positions information
    Void stop() {
        Log(exchange.GetOrders()); // print order
        Log(exchange.GetPosition()); // Print position
        Log("Stop");
    }

Finalmente, nos concentramos em como a função Loop controla a lógica da estratégia e a ordem. Se você quiser ver mais cuidadosamente, você pode consultar os comentários no código. Primeiro, determine se a transação CTP e o servidor do mercado estão conectados; então obtenha o saldo disponível da conta e obtenha o número de semanas; então defina o código de variedade a ser negociado, chamando a função oficial FMZ SetQuantContractType, e pode usar essa função para retornar os detalhes da variedade de negociação; então chame a função GetDepth para obter os dados de profundidade do mercado atual.

// Strategy logic and placing order
Bool Loop() {
    If (exchange.IO("status") == 0) { // If the CTP and the quote server are connected
        LogStatus(_D(), "Server not connect ...."); // Print information to the status bar
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    
    If (_initBalance == 0) {
        _initBalance = _C(exchange.GetAccount).Balance; // Get account balance
    }
    
    Auto day = getTradingWeekDay(); // Get the number of weeks
    If (day != _tradingDay) {
        _tradingDay = day;
        _countCancel = 0;
    }
    
    // Set the futures contract type and get the contract specific information
    If (_ct.is_null()) {
        Log(_D(), "subscribe", Symbol); // Print the log
        _ct = exchange.SetContractType(Symbol); // Set futures contract type
        If (!_ct.is_null()) {
            Auto obj = _ct["Commodity"]["CommodityTickSize"];
            Int volumeMultiple = 1;
            If (obj.is_null()) { // CTP
                Obj = _ct["PriceTick"];
                volumeMultiple = _ct["VolumeMultiple"];
                _exchangeId = _ct["ExchangeID"];
            } else { // Esunny
                volumeMultiple = _ct["Commodity"]["ContractSize"];
                _exchangeId = _ct["Commodity"]["ExchangeNo"];
            }
            If (obj.is_null() || obj <= 0) {
                Panic("PriceTick not found");
            }
            If (_priceTick < 1) {
                exchange.SetPrecision(1, 0); // Set the decimal precision of the price and the quantity of the order.
            }
            _priceTick = double(obj);
            _toleratePrice = _priceTick * TolerateTick;
            _ins = _ct["InstrumentID"];
            Log(_ins, _exchangeId, "PriceTick:", _priceTick, "VolumeMultiple:", volumeMultiple); // print the log
        }
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    
    // Check orders and positions to set status
    Auto depth = exchange.GetDepth(); // Get depth data
    If (!depth.Valid) { // if no depth data is obtained
        LogStatus(_D(), "Market not ready"); // Print status information
        Sleep(1000); // Sleep 1 second
        Return true;
    }
    _countTick++;
    _preBook = _book;
    _book.bidPrice = depth.Bids[0].Price; // "Buying 1" price
    _book.bidAmount = depth.Bids[0].Amount; // "Buying 1" amount
    _book.askPrice = depth.Asks[0].Price; // "Selling 1" price
    _book.askAmount = depth.Asks[0].Amount; // "Selling 1" amount
    // Determine the state of the port data assignment
    If (_preBook.bidAmount == 0) {
        Return true;
    }
    Auto st = getState(); // get the order data
    
    // Print the port data to the status bar
    LogStatus(_D(), _ins, "State:", st,
                "Ask:", depth.Asks[0].Price, depth.Asks[0].Amount,
                "Bid:", depth.Bids[0].Price, depth.Bids[0].Amount,
                "Cancel:", _countCancel,
                "Tick:", _countTick);
}

Depois de fazer tanto, podemos finalmente colocar ordens. Antes da negociação, primeiro julgamos o status atual da posição de detenção do programa (nenhuma posição de detenção, ordens de posição longa, ordens de posição curta), aqui usamos o controle de lógica if...else if...else if. Eles são muito simples, Se não houver posição de detenção, a posição será aberta de acordo com a condição lógica. Se houver posição de detenção, a posição será fechada de acordo com a condição lógica. A fim de facilitar a compreensão de todos, usamos três parágrafos para explicar a lógica, Para a parte de posição de abertura:

Primeiro declarar uma variável booleana, usá-lo para controlar a posição de fechamento; em seguida, precisamos obter as informações da conta corrente, e registrar o valor do lucro, em seguida, determinar o status da ordem de retirada, se o número de retirada excede o máximo definido, imprimir as informações relacionadas no log; em seguida, calcular o valor absoluto da oferta atual e oferta diferença de preço para determinar se há mais de 2 saltos entre o preço de oferta atual e o preço de compra.

Em seguida, obtemos o Preço de compra 1 e o Preço de venda 1, se o preço de compra anterior for maior que o preço de compra atual e o volume de venda atual for menor que o volume de compra, isso significa que o preço de compra 1 desapareceu. o preço de abertura da posição longa e a quantidade de ordem são definidos; caso contrário, se o preço de venda anterior for menor que o preço de venda atual e o volume de compra atual for menor que O volume de venda prova que o preço de venda 1 desapareceu, o preço de abertura da posição curta e a quantidade de ordem são definidos; no final, a posição longa e as ordens de posição curta entram no mercado ao mesmo tempo. O código específico é o seguinte:

Bool forceCover = _countRetry >= _retryMax; // Boolean value used to control the number of closings
If (st == STATE_IDLE) { // if there is no holding position
    If (_holdAmount > 0) {
        If (_countRetry > 0) {
            _countLoss++; // failure count
        } else {
            _countWin++; // success count
        }
        Auto account = exchange.GetAccount(); // Get account information
        If (account.Valid) { // If get account information
            LogProfit(_N(account.Balance+account.FrozenBalance-_initBalance, 2), "Win:", _countWin, "Loss:", _countLoss); // Record profit value
        }
    }
    _countRetry = 0;
    _holdAmount = 0;
    
    // Judging the status of withdrawal
    If (_countCancel > _cancelMax) {
        Log("Cancel Exceed", _countCancel); // Print the log
        Return false;
    }

    Bool canDo = false; // temporary variable
    If (abs(_book.bidPrice - _book.askPrice) > _priceTick * 1) { // If there is more than 2 hops between the current bid and ask price
        canDo = true;
    }
    If (!canDo) {
        Return true;
    }
    
    Auto bidPrice = depth.Bids[0].Price; // Buying 1 price
    Auto askPrice = depth.Asks[0].Price; // Selling 1 price
    Auto bidAmount = 1.0;
    Auto askAmount = 1.0;
    
    If (_preBook.bidPrice > _book.bidPrice && _book.askAmount < _book.bidAmount) { // If the previous buying price is greater than the current buying price and the current selling volume is less than the buying volume
        bidPrice += _priceTick; // Set the opening long position price
        bidAmount = 2; // set the opening long position volume
    } else if (_preBook.askPrice < _book.askPrice && _book.bidAmount < _book.askAmount) { // If the previous selling price is less than the current selling price and the current buying volume is less than the selling volume
        askPrice -= _priceTick; // set the opening short position volume
        askAmount = 2; // set the opening short position volume
    } else {
        Return true;
    }
    Log(_book.bidPrice, _book.bidAmount, _book.askPrice, _book.askAmount); // Print current market data
    exchange.SetDirection("buy"); // Set the order type to buying long
    exchange.Buy(bidPrice, bidAmount); // buying long and open position
    exchange.SetDirection("sell"); // Set the order type to selling short
    exchange.Sell(askPrice, askAmount); // short sell and open position
}

Em seguida, falaremos sobre como fechar uma posição longa, primeiro definir o tipo de ordem de acordo com o status atual da posição e, em seguida, obter o preço de Venda 1 . Se o preço atual de Venda 1 for maior que o preço de abertura da compra longa, defina o preço de fechamento da posição longa. Se o preço atual de Venda 1 for menor que o preço de abertura da posição longa, então redefine a variável de quantidade de fechamento para verdade, em seguida, feche toda a posição longa.

Else if (st == STATE_HOLD_LONG) { // if holding long position
     exchange.SetDirection((_holdType == PD_LONG && _exchangeId == "SHFE") ? "closebuy_today" : "closebuy"); // Set the order type, and close position
     Auto sellPrice = depth.Asks[0].Price; // Get "Selling 1" price
     If (sellPrice > _holdPrice) { // If the current "selling 1" price is greater than the long position opening price
         Log(_holdPrice, "Hit #ff0000"); // Print long position opening price 
         sellPrice = _holdPrice + ProfitTick; // Set closing long position price
     } else if (sellPrice < _holdPrice) { // If the current "selling 1" price is less than the long position opening price
         forceCover = true;
     }
     If (forceCover) {
         Log("StopLoss");
     }
     _coverId = exchange.Sell(forceCover ? depth.Bids[0].Price : sellPrice, _holdAmount); // close long position
     If (!_coverId.Valid) {
         Return false;
     }
}

Finalmente, vamos ver como fechar a posição curta. O princípio é o oposto da posição longa de fechamento acima mencionada. Primeiro, de acordo com o status da posição atual, defina o tipo de ordem e, em seguida, obtenha o preço de compra 1, se o preço atual de compra 1 for menor que o preço de abertura da posição curta, o preço da posição curta de fechamento será definido. Se o preço atual de compra 1 for maior que o preço da posição curta de abertura, redefine a variável de quantidade de fechamento para verdade, em seguida, feche todas as posições curtas.

Else if (st == STATE_HOLD_SHORT) { // if holding short position
     exchange.SetDirection((_holdType == PD_SHORT && _exchangeId == "SHFE") ? "closesell_today" : "closesell"); // Set the order type, and close position
     Auto buyPrice = depth.Bids[0].Price; // Get "buying 1" price
     If (buyPrice < _holdPrice) { // If the current "buying 1" price is less than the opening short position price
         Log(_holdPrice, "Hit #ff0000"); // Print the log
         buyPrice = _holdPrice - ProfitTick; // Set the close short position price
     } else if (buyPrice > _holdPrice) { // If the current "buying 1" price is greater than the opening short position price
         forceCover = true;
     }
     If (forceCover) {
         Log("StopLoss");
     }
     _coverId = exchange.Buy(forceCover ? depth.Asks[0].Price : buyPrice, _holdAmount); // close short position
     If (!_coverId.Valid) {
         Return false;
     }
}

O texto acima apresenta uma análise completa desta estratégia.https://www.fmz.com/strategy/163427) para copiar o código fonte da estratégia completa sem configurar o ambiente de backtest no FMZ Quant.

Resultados dos testes de regresso

img

Lógica comercial

img

Declaração de estratégia

Para satisfazer a curiosidade da negociação de alta frequência e ver os resultados mais claramente, esta taxa de transação do ambiente de backtest estratégia é definida em 0, o que leva a uma lógica de velocidade rápida simples. se você quiser cobrir a taxa de transação para alcançar lucratividade no mercado real. Mais otimização é necessária. Como usar o fluxo de pedidos para realizar previsões de curto prazo para melhorar a taxa de ganho, além do reembolso da taxa de câmbio, A fim de alcançar uma estratégia rentável sustentável, existem muitos livros sobre negociação de alta frequência. Espero que todos possam pensar mais e ir ao mercado real em vez de apenas ficar no princípio.

Sobre nós

FMZ Quant é uma equipe puramente orientada para a tecnologia que fornece um mecanismo de backtest disponível altamente eficiente para os entusiastas de negociação quantitativa.


Relacionados

Mais.