Análise da estratégia do LeeksReaper (2)

Autora:Lydia., Criado: 2022-11-07 16:38:41, Atualizado: 2023-09-15 21:07:34

img

Análise da estratégia do LeeksReaper (2)

Continuemos a explicar o conteúdo do último capítulo (https://www.fmz.com/bbs-topic/9725).

A terceira função adicionada:

    self.balanceAccount = function() {
        var account = exchange.GetAccount()
        if (!account) {
            return
        }
        self.account = account
        var now = new Date().getTime()
        if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)) {
            self.preCalc = now
            var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks))
            if (net != self.preNet) {
                self.preNet = net
                LogProfit(net)
            }
        }
        self.btc = account.Stocks
        self.cny = account.Balance
        self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)
        var balanced = false
        
        if (self.p < 0.48) {
            Log ( \"\" Start Balance \"\", self. P)
            self.cny -= 300
            if (self.orderBook.Bids.length >0) {
                exchange.Buy(self.orderBook.Bids[0].Price + 0.00, 0.01)
                exchange.Buy(self.orderBook.Bids[0].Price + 0.01, 0.01)
                exchange.Buy(self.orderBook.Bids[0].Price + 0.02, 0.01)
            }
        } else if (self.p > 0.52) {
            Log ( \"\" Start Balance \"\", self. P)
            self.btc -= 0.03
            if (self.orderBook.Asks.length >0) {
                exchange.Sell(self.orderBook.Asks[0].Price - 0.00, 0.01)
                exchange.Sell(self.orderBook.Asks[0].Price - 0.01, 0.01)
                exchange.Sell(self.orderBook.Asks[0].Price - 0.02, 0.01)
            }
        }
        Sleep(BalanceTimeout)
        var orders = exchange.GetOrders()
        if (orders) {
            for (var i = 0; i < orders.length; i++) {
                if (orders[i].Id != self.tradeOrderId) {
                    exchange.CancelOrder(orders[i].Id)
                }
            }
        }
    }

Quando o construtorLeeksReaper ()construi um objeto, obalanceAccount ()A função adicionada ao objeto atualiza as informações do ativo da conta armazenadas noself.account, ou seja, oaccountAtributo do objeto construído. Calcule o valor da receita e imprima-lo a tempo. Em seguida, de acordo com a última informação do ativo da conta, calcule a relação de saldo da moeda dos pontos (balanço da posição dos pontos), ao desencadear o limiar de deslocamento, feche a posição com uma pequena ordem, para que a moeda (posição) de volta ao estado de equilíbrio. Espere um certo tempo para negociar, depois cancele todos os fabricantes, a próxima rodada de execução da função, verificará o saldo e fará o processamento correspondente novamente.

Vejamos o código desta função sentença por sentença: Primeiro, a primeira frase.var account = exchange.GetAccount ()declara uma variável localaccounte chama a função deexchange.GetAccountObter os dados mais recentes da conta corrente e atribuí-lo para a variávelaccountEntão julgue a variável.accountSe a variável for:null(por exemplo, timeout, rede, interfaces de troca exceção, etc.), ele irá retornar (correspondente aif (!account) {...}) directamente.

self.account = accounté atribuir a variável localaccountpara oaccountAtributo do objeto construído para registar as últimas informações da conta no objeto construído.

Var now = new Date().getTime ()declara uma variável localnowe chama ogetTime()atribui um valor à variávelnow.

if (self.orderBook.Bids.length > 0 && now - self.preCalc > (CalcNetInterval * 1000)){...}Determina que se a diferença entre o carimbo horário atual e o carimbo horário registrado da última vez excede o parâmetroCalcNet Interval * 1000, significa que foi atualizado desde a última vez.CalcNetInterval * 1000milissegundos (CalcNetIntervalO preço de compra de um exemplar é utilizado para calcular o rendimento, a condição deself.orderBook.Bids.length > 0Quando a condição de instrução if é acionada, a instrução de nível de dados de profundidade é executada.self.PreCalc = nowé executado para atualizar a variável de carimbo horário da declaração impressa mais recenteself.preCalcpara o carimbo de hora correntenowO método de cálculo do valor líquido é utilizado nas estatísticas de retorno.var net = _N(account.Balance + account.FrozenBalance + self.orderBook.Bids[0].Price * (account.Stocks + account.FrozenStocks)), ou seja, converter a moeda em dinheiro (moeda denominada) de acordo com o preço de compra atual, e depois adicioná-lo ao montante de dinheiro na conta e atribuí-lo à variável local declaradanetJulgar se o valor líquido total actual é consistente com o valor líquido total registado na última vez:

            if (net != self.preNet) {
                self.preNet = net
                LogProfit(net)
            }

Se não for consistente, isto é,net! = self.preNeté verdade, atualizar o atributo deself.preNetutilizado para registar o valor líquido com a variávelnetEm seguida, imprima o total líquido denetdados para o gráfico da curva de rendimento do robô da plataforma de negociação FMZ Quant (oLogProfitFunção pode ser consultada no documento FMZ API).

Se a impressão regular dos ganhos não for desencadeada, prossiga com o seguinte processo para registar oaccount.Stocks(moeda disponível na conta corrente) eaccount.Balance(moeda disponível na conta corrente) noself.BTCeself.CNY. Calcular a escala de deslocamento e registar a atribuição noself.p.

self.p = self.btc * self.prices[self.prices.length-1] / (self.btc * self.prices[self.prices.length-1] + self.cny)

O algoritmo também é muito simples, que é calcular a percentagem do valor corrente da moeda para o valor líquido total da conta.

E quanto a julgar quando acionar o saldo de dinheiro (posição)? Aqui, eu tomo 50% mais ou menos 2 pontos percentuais como o buffer, e executa o saldo além do buffer, ou seja, se oself.p < 0.48Se o dinheiro for menor, o preço aumentará 0,01 cada vez a partir da posição de compra na abertura do mercado, e três pequenas ordens serão organizadas.self.p > 0.52, se a moeda é mais, vender um e liberar pequenos pedidos.Sleep(BalanceTimeout)durante um determinado período de tempo, de acordo com as definições dos parâmetros.

        Var orders = exchange. Get Orders () # Get all current makers, with orders variable
        If (orders) { # If the variable orders used to obtain the current order data is not null
            for (var i = 0; i < orders.length; I + +) { # Loop through orders and cancel orders one by one
                if (orders[i].Id != self.tradeOrderId) {
                    Exchange. CancelOrder (orders [I]. Id) # Call exchange. CancelOrder to cancel orders based on orders [I]. Id
                }
            }
        }

A quarta função adicionada:

Na parte central da estratégia, aqui vem a jogada principal.self.poll = function(){...}A estratégia de desenvolvimento sustentável é a lógica principal de toda a estratégia, tal como dissemos no artigo anterior, antes damain()função começa a executar e entra no infinitowhileLoop, nós usamosvar reaper = LeeksReaper()para construir o objeto leeksreaper, e, em seguida, executar a chamada de loop dereaper.poll()emmain() function.

Oself.pollA função começa a executar, fazendo algum trabalho preparatório antes de cada loop.self.numTick++A redução da taxa de mortalidadeself.updateTrades()O sistema de gestão de dados de mercado é um sistema de gestão de dados de mercado que atualiza os registos recentes de negociação de mercado e calcula os dados de utilização relevantes.self.updateOrderBook()O sistema de gestão dos pedidos de serviços de informação e de informação é um sistema de gestão de dados.self.balanceAccount()verificar o saldo da posição monetária.

        Var burstPrice = self. Prices [self. Prices. Length-1] * BurstThresholdPct # Calculate Burst Price
        Var bull = false                   # Declare a bull-marked variable, initially false
        Var bear = false                  # Declare a bear marked variable, initially false
        Var tradeAmount = 0         # Declare the transaction amount variable, initially 0

O próximo passo é julgar se o mercado de curto prazo atual é um touro ou um urso.

        if (self.numTick > 2 && (
            self.prices[self.prices.length-1] - _.max(self.prices.slice(-6, -1)) > burstPrice ||
            self.prices[self.prices.length-1] - _.max(self.prices.slice(-6, -2)) > burstPrice && self.prices[self.prices.length-1] > self.prices[self.prices.length-2]
            )) {
            bull = true
            tradeAmount = self.cny / self.bidPrice * 0.99
        } else if (self.numTick > 2 && (
            self.prices[self.prices.length-1] - _.min(self.prices.slice(-6, -1)) < -burstPrice ||
            self.prices[self.prices.length-1] - _.min(self.prices.slice(-6, -2)) < -burstPrice && self.prices[self.prices.length-1] < self.prices[self.prices.length-2]
            )) {
            bear = true
            tradeAmount = self.btc
        }

Lembras-te doself.updateOrderBook()função do artigo anterior onde usamos um algoritmo média ponderada para construir um tempo ordenadopricesTrês novas funções:_.min, _.max, eslicesão utilizadas no código e são fáceis de compreender.

· _. min: A função é encontrar o valor mínimo na matriz de parâmetros.

· _.max: A função é encontrar o valor máximo na matriz de parâmetros.

· sliceA função é uma função membro daJavaScriptÉ usado para retornar uma parte da matriz de acordo com o índice. Por exemplo:

function main() {
    // index     .. -8 -7 -6 -5 -4 -3 -2 -1
    var arr = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
    Log (arr. Slice (-5, -1))   // it will intercept the elements from 4 to 1 and return a new array: [4,3,2,1]
}

img

As condições para julgar um mercado de baixa ou alta são:

· Oself.numTick > 2Deve ser verdadeiro, ou seja, quando uma nova rodada de preço de detecção ocorre, deve ser desencadeada após pelo menos três rodadas de detecção, de modo a evitar desencadear no início. · A diferença entre os últimos dados doself.pricesA sequência de preços, isto é, os dados mais recentes, e o preço máximo ou mínimo no intervalo anterior no intervalo de preços de mercado.self.pricesArray deve exceder o preço de ruptura deburstPrice.

Se todas as condições forem verdadeiras, marquebulloubearcomo verdadeiro, e atribuir um valor para a variáveltradeAmountpara planear a transacção do Stud.

Em seguida, de acordo com oself.volA taxa de crescimento da populaçãoself.updateTrades()Função, oBurstThresholdVolO parâmetro determina se a intensidade da transacção deve ser reduzida (reduzir o volume de transacções planeado).

        if (self.vol < BurstThresholdVol) {
            TradeAmount * = self. Vol/BurstThresholdVol      //Reduce the planned volume by self. Vol/BurstThresholdVol times of the previous volume
        }
        
        if (self.numTick < 5) {
            TradeAmount * = 0.8      // reduced to 80% of the plan
        }
        
        If (self. NumTick < 10) {       // reduce to 80% of the plan
            tradeAmount *= 0.8
        }

Em seguida, julgue se o sinal de negociação e o volume cumprem os requisitos:

        If ( (!Bull && !Bear) | | tradeAmount &lt; MinStock) {     # If it is not a bull market and not a bear market, or the amount tradeAmount planned to trade is less than the minimum trading volume MinStock set by the parameter, the poll function returns without trading operations directly
            return
        }

Após a sentença acima, executarvar tradePrice = bull ? self.bidPrice: self.askPriceEstabelece o preço da transacção em função de se tratar de um mercado de baixa ou de alta, e atribui o valor com o preço correspondente da fatura.

Por fim, umawhileA única condição de parada do ciclo é que o volume de negociação planeado detradeAmount > = MinStockÉ inferior ao volume mínimo de negociação. No loop, a ordem é executada de acordo com o estado atual do mercado.orderId. Sleep(200)O circuito determina então se oorderIdé verdade (se a ordem falhar, o ID da ordem não será devolvido, e a condição if não será acionada).self.tradeOrderId.

Declarar uma variávelorderutilizado para armazenar dados de encomendas, com um valor inicial denull. Em seguida, os dados de ordem do ID são obtidos em um loop, e julgar se a ordem é o estado do fabricante, se assim for, a ordem do ID é cancelada, e se não, o loop de detecção é encerrado.

                Var order = null         // Declare a variable to hold the order data
                While (true) {             // a while loop
                    Order = exchange. GetOrder (orderId)          // Call GetOrder to query the order data whose order ID is orderId
                    If (order) {                                                   // If the order data is queried and the query fails and the order is null, the current if condition will not be triggered
                        If (order. Status = = ORDER _ STATE _ PENDING) {              // Judge whether the order status is maker
                            Exchange. CancelOrder (orderId)                                    // If the order is maker, cancel the order
                            Sleep(200)
                        } else {                                                                               // otherwise execute break to end the current while loop
                            break
                        }
                    }
                }

Em seguida, realiza-se o seguinte processo:

                Self. TradeOrderId = 0                         // Reset self. TradeOrderId.
                TradeAmount-= order. DealAmount    // Update tradeAmount, subtract the quantity of the order on the bill of lading that has been completed
                TradeAmount * = 0.9                          //Decrease the order amount
                If (order. Status = = ORDER _ STATE _ CANCELED) {                   // if the order is already cancelled
                    Self. UpdateOrderBook ()                                                      // Update data such as order book
                    While (bull & & self. BidPrice-tradePrice &gt; 0.1) {               // In a bull market, if the updated bill of lading price exceeds the current trading price by 0.1, the trading amount will be reduced and the trading price will be adjusted slightly
                        tradeAmount *= 0.99
                        tradePrice += 0.1
                    }
                    While (bear & & self. AskPrice-tradePrice &lt; -0.1) {             // In a bear market, if the updated bill of lading price exceeds the current trading price by 0.1, the trading amount will be reduced and the trading price will be adjusted slightly
                        tradeAmount *= 0.99
                        tradePrice -= 0.1
                    }
                }

Quando o processo do programa termina do loop dewhile (tradeAmount > = MinStock){...}, indica que a execução deste processo de transacção de rajada de preços está concluída. Executar oself.numTick = 0, isto é, redefinir oself.numTickpara 0.

OLeeksReaper()Construtor retorna oselfObjeto no final da execução, isto é, quandovar reaper = LeeksReaper(), é devolvido aoreaper.

Até agora, analisámos como oLeeksReaper()Eu acredito que você terá uma compreensão clara deste processo de algoritmo de estratégia de alta frequência depois de ler este artigo.


Relacionados

Mais.