Processamento de dados de linha K na negociação quantitativa

Autora:Bem-estar, Criado: 2019-09-03 11:15:30, Atualizado: 2023-11-07 20:43:41

img

Como o processamento de dados da K Line no comércio quantitativo?

Quando se escreve uma estratégia de negociação quantitativa, usando os dados da linha K, muitas vezes há casos em que são necessários dados de linha K não padrão. por exemplo, são necessários dados de linha K de ciclo de 12 minutos e dados de ciclo de linha K de 4 horas. Normalmente, esses ciclos não padrão não estão diretamente disponíveis. Então, como lidar com tais necessidades?

Os dados da linha K do ciclo não padrão podem ser obtidos combinando os dados do ciclo menor. Imagine isso, o preço mais alto em vários ciclos é contado como o preço mais alto após a síntese da linha K do ciclo múltiplo, e o preço mais baixo é calculado como o preço mais baixo após a síntese, e o preço de abertura não muda. O primeiro preço de abertura dos dados da matéria-prima da linha K é sintetizado. O preço de fechamento corresponde ao preço de fechamento dos últimos dados da matéria-prima da linha K. O tempo usa o tempo da linha de preço de abertura k. O volume da transação usa os dados da matéria-prima somados e calculados.

Tal como mostra a figura:

  • Pensamento

Vamos tomar o ativo blockchain BTC_USDT como exemplo e sintetizar 1 hora em 4 horas.

img img img img

Tempo Maior Aberto Baixo Fechado
2019.8.12 00:00 11447.07 11382.57 11367.2 11406.92
2019.8.12 01:00 11420 11405.65 11366.6 11373.83
2019.8.12 02:00 11419.24 11374.68 11365.51 11398.19
2019.8.12 03:00 11407.88 11398.59 11369.7 11384.71

Os dados de quatro ciclos de uma hora são combinados num único dado de um ciclo de quatro horas.

O preço de abertura é o primeiro preço de abertura da linha K às 00:00 horas: 11382.57 O preço de fechamento é o último preço de fechamento da linha k às 03:00: 11384.71 O preço mais alto é encontrar o preço mais alto entre eles: 11447,07 O preço mais baixo é encontrar o preço mais baixo entre eles: 11365,51

Nota: O mercado de futuros de commodities da China fechou às 15:00 em um dia de negociação normal

A hora de início do ciclo de 4 horas é a hora de início da primeira linha K de 1 hora, ou seja, 2019.8.12 00:00

A soma do volume de todas as linhas k de 1 hora é utilizada como volume da linha k de 4 horas.

Uma linha K de 4 horas é sintetizada:

High: 11447.07
Open: 11382.57
Low: 11365.51
Close: 11384.71
Time: 209.8.12 00:00

img

Podem ver que os dados são consistentes.

  • Implementação do código

Depois de compreender as ideias iniciais, pode escrever manualmente o código para realizar os requisitos.

Estes códigos são apenas para referência:

function GetNewCycleRecords (sourceRecords, targetCycle) { // K line synthesis function
      var ret = []
      
      // First get the source K line data cycle
      if (!sourceRecords || sourceRecords.length < 2) {
          Return null
      }
      var sourceLen = sourceRecords.length
      var sourceCycle = sourceRecords[sourceLen - 1].Time - sourceRecords[sourceLen - 2].Time

      if (targetCycle % sourceCycle != 0) {
          Log("targetCycle:", targetCycle)
          Log("sourceCycle:", sourceCycle)
          throw "targetCycle is not an integral multiple of sourceCycle."
      }

      if ((1000 * 60 * 60) % targetCycle != 0 && (1000 * 60 * 60 * 24) % targetCycle != 0) {
          Log("targetCycle:", targetCycle)
          Log("sourceCycle:", sourceCycle)
          Log((1000 * 60 * 60) % targetCycle, (1000 * 60 * 60 * 24) % targetCycle)
          throw "targetCycle cannot complete the cycle."
      }

      var multiple = targetCycle / sourceCycle


      var isBegin = false
      var count = 0
      var high = 0
      var low = 0
      var open = 0
      var close = 0
      var time = 0
      var vol = 0
      for (var i = 0 ; i < sourceLen ; i++) {
          // Get the time zone offset value
          var d = new Date()
          var n = d.getTimezoneOffset()

          if ((1000 * 60 * 60 * 24) - sourceRecords[i].Time % (1000 * 60 * 60 * 24) + (n * 1000 * 60)) % targetCycle == 0) {
              isBegin = true
          }

          if (isBegin) {
              if (count == 0) {
                  High = sourceRecords[i].High
                  Low = sourceRecords[i].Low
                  Open = sourceRecords[i].Open
                  Close = sourceRecords[i].Close
                  Time = sourceRecords[i].Time
                  Vol = sourceRecords[i].Volume

                  count++
              } else if (count < multiple) {
                  High = Math.max(high, sourceRecords[i].High)
                  Low = Math.min(low, sourceRecords[i].Low)
                  Close = sourceRecords[i].Close
                  Vol += sourceRecords[i].Volume

                  count++
              }

              if (count == multiple || i == sourceLen - 1) {
                  Ret.push({
                      High : high,
                      Low : low,
                      Open : open,
                      Close : close,
                      Time : time,
                      Volume : vol,
                  })
                  count = 0
              }
          }
      }

      Return ret
  }

  // test
  function main () {
      while (true) {
          var r = exchange.GetRecords() // Raw data, as the basic K-line data of the synthesize K line. for example, to synthesize a 4-hour K-line, you can use the 1-hour K-line as the raw data.
          var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4) // Pass the original K-line data r through the GetNewCycleRecords function, and the target cycles, 1000 * 60 * 60 * 4, ie the target synthesis cycle is 4 hours K-line data .

          $.PlotRecords(r2, "r2") // The strategy class library bar can be selected by check the line class library, and calling the $.PlotRecords line drawing class library to export the function drawing.
          Sleep(1000) // Each cycle is separated by 1000 milliseconds, preventing access to the K-line interface too much, resulting in transaction restrictions.
      }
  }

Na verdade, para sintetizar a linha K, você precisa de duas coisas. O primeiro são os dados da matéria-prima, ou seja, os dados da linha K de um ciclo menor.var r = exchange.GetRecords()para obter os dados da linha de ciclo K menor.

O segundo é descobrir o tamanho do ciclo de síntese, nós usamos o algoritmo função GetNewCycleRecords para fazer isso, então você pode finalmente retornar os dados de uma estrutura de matriz K-line sintetizada.

Tenha em conta:

  1. O ciclo de destino não pode ser menor do que o ciclo da linha K que você passou na função GetNewCycleRecords como matéria-prima para os dados.

  2. O ciclo alvo deve ser definido como ciclo fechado. O que é um ciclo fechado?

Por exemplo:

A linha K do ciclo de 12 minutos começa a partir de 0:0 a cada hora, o primeiro ciclo é 00:00:00 ~ 00:12:00, e o segundo ciclo é 00:12: 00 ~ 00: 24:00, o terceiro ciclo é 00:24:00 ~ 00:36:00, o quarto ciclo é 00:36:00 ~ 00:48:00, o quinto ciclo é 00:48 :00 ~ 01:00:00, que são exatamente uma hora completa.

Se for um ciclo de 13 minutos, será um ciclo que não está fechado. Os dados calculados por tal ciclo não são únicos porque os dados sintetizados diferem dependendo do ponto de partida dos dados sintetizados.

Faça isso no mercado real:

img

Gráfico de troca de contraste

img

  • Construir a estrutura de dados necessária usando dados de linha K

Quero calcular a média móvel do preço mais alto para todas as linhas K. O que devo fazer?

Normalmente, nós calcular as médias móveis usando a média dos preços de fechamento, mas às vezes há demanda para usar o preço mais alto, o preço mais baixo, o preço de abertura e assim por diante.

Para estas demandas extras, os dados de linha K devolvidos pela função exchange.GetRecords ((() não podem ser transmitidos diretamente para a função de cálculo do indicador.

Por exemplo: Otalib.MAA função de cálculo do indicador da média móvel tem dois parâmetros, o primeiro dos quais são os dados a transmitir e o segundo o parâmetro do ciclo do indicador.

Por exemplo, precisamos calcular os indicadores como mostrado abaixo.

img

O ciclo da linha K é de 4 horas.

No gráfico das cotações de câmbio, foi fixada uma linha média com o parâmetro do ciclo de 9.

A fonte de dados calculada utiliza o preço mais elevado por barra.

img

Ou seja, esta linha média móvel consiste na média do preço médio mais alto de nove ciclos de 4 horas K-line Bar.

Vamos construir um dado nós mesmos para ver se é o mesmo com os dados da troca.

var highs = []
for (var i = 0 ; i < r2.length ; i++) {
    highs.push(r2[i].High)
}

Como precisamos calcular o preço mais alto de cada barra para obter o valor do indicador da média móvel, precisamos construir uma matriz na qual cada elemento de dados tem o preço mais alto para cada barra.

Podem ver que ohighsA variável é inicialmente uma matriz vazia, então atravessamos a variável de dados de linha r2 k (não lembram da r2?

Leia o preço mais alto de cada Bar de r2 (ou seja, r2 [i].High, i varia de 0 a r2.longitude - 1), em seguida, empurrar parahighsDesta forma, nós apenas construímos uma estrutura de dados que corresponde um a um com a barra de dados da linha K.

Neste momento,highspode passar otalib.MAFunção para calcular a média móvel.

Exemplo completo:

function main () {
     while (true) {
         var r = exchange.GetRecords()
         var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4)
         if (!r2) {
             Continue
         }
        
         $.PlotRecords(r2, "r2") // Draw the K line
        
         var highs = []
         for (var i = 0 ; i < r2.length ; i++) {
             Highs.push(r2[i].High)
         }
        
         var ma = talib.MA(highs, 9) // use the moving average function "talib.MA" to calculate the moving average indicator
         $.PlotLine("high_MA9", ma[ma.length - 2], r2[r2.length - 2].Time) // Use the line drawing library to draw the moving average indicator on the chart
        
         Sleep(1000)
     }
}

Teste de retrocesso:

img

Você pode ver que o valor médio do indicador da posição do ponto do mouse na figura é 11466.9289

O código acima pode ser copiado para a estratégia para executar o teste, lembre-se de verificar a Draw Line Library e salvá-lo!

  • Método de aquisição de dados K-line para o mercado de criptomoedas

A plataforma FMZ Quant já dispõe de uma interfaceexchange.GetRecordsfunção, para obter dados da linha K.

O seguinte foca no acesso direto à interface de dados de linha K do exchanges para obter dados, porque às vezes você precisa especificar parâmetros para obter mais linhas K, o pacoteGetRecordsinterface geralmente retorna 100 k linhas. se você encontrar uma estratégia que inicialmente requer mais de 100 K-linhas, você precisa esperar o processo de coleta.

Para fazer a estratégia funcionar o mais rápido possível, você pode encapsular uma função, acessar diretamente a interface da linha K da troca e especificar parâmetros para obter mais dados da linha K.

Usando o par de negociação BTC_USDT na troca Huobi como exemplo, implementamos este requisito:

Encontre a documentação da API do exchange e veja a descrição da interface da linha K:

img

https://huobiapi.github.io/docs/spot/v1/en/#get-klines-candles

Parâmetros:

Nome Tipo É necessário? Descrição Valor
símbolo cordel verdade Pares de negociação Não, não, não, não.
período cordel verdade Retorna a granularidade temporal dos dados, que é o intervalo de tempo de cada linha k 1 minuto, 5 minutos, 15 minutos, 30 minutos, 60 minutos, 1 dia, 1 mês, 1 semana, 1 ano
tamanho Número inteiro Falso Retorna o número de linhas de dados K [1, 2000]

Código de ensaio:

function GetRecords_Huobi (period, size, symbol) {
    var url = "https://api.huobi.pro/market/history/kline?" + "period=" + period + "&size=" + size + "&symbol=" + symbol
    var ret = HttpQuery(url)
    
    try {
        var jsonData = JSON.parse(ret)
        var records = []
        for (var i = jsonData.data.length - 1; i >= 0 ; i--) {
            records.push({
                Time : jsonData.data[i].id * 1000,
                High : jsonData.data[i].high,
                Open : jsonData.data[i].open,
                Low : jsonData.data[i].low,
                Close : jsonData.data[i].close,
                Volume : jsonData.data[i].vol,
            })
        }
        return records
    } catch (e) {
        Log(e)
    }
}  


function main() {
    var records = GetRecords_Huobi("1day", "300", "btcusdt")
    Log(records.length)
    $.PlotRecords(records, "K")
}

img img

Podem ver no registo, impressãorecords.lengthé 300, ou seja, o número derecordsA barra de dados da linha K é 300.img


Relacionados

Mais.