Processamento de dados da linha K em transações programáticas

Autora:Sonhos pequenos, Criado: 2019-08-13 11:11:38, Atualizado: 2023-10-20 20:06:13

img

Processamento de dados da linha K em transações programáticas

Quando se escreve uma estratégia de negociação programada usando dados de linha K, muitas vezes há uma necessidade de usar alguns dados de linha K de ciclo não padrão, como dados de ciclo de linha K de 12 minutos, dados de ciclo de linha K de 4 horas, que geralmente não podem ser obtidos diretamente. Então, como lidar com essa necessidade? A resposta é que há uma solução. Os ciclos não padrão podem ser obtidos por meio de dados de ciclos menores, combinados e sintetizados. Imagine que o preço mais alto em vários ciclos seja o preço mais alto após a síntese, o preço mais baixo seja o preço mais baixo após a síntese, o preço de abertura não mude. O primeiro preço de abertura é o primeiro preço de abertura dos dados de matéria-prima da linha K, o preço de fechamento corresponde ao último preço de fechamento dos dados de matéria-prima da linha K, o tempo é o tempo do preço de abertura, o volume de transações é calculado e obtido com os dados de matéria-prima. O que é que ele está a fazer?

  • Pensamento

    O mercado de ativos da blockchain BTC_USDT, por exemplo, se tornou 4 horas em 1 hora.

    img

    img

    img

    img

    Tempo Alto Desligue Baixo Recolha
    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

    Estes quatro ciclos de uma hora, combinados com um ciclo de quatro horas, o preço de abertura é o primeiro preço de abertura 00:00:11382.57 O preço de fechamento é o último, que é o preço de fechamento às 03:00: 11384.71. Preço mais alto para encontrar o preço mais alto aqui: 11447.07 Preço mais baixo para encontrar o preço mais baixo aqui: 11365.51 O ciclo de 4 horas começa às 00:00 e a linha K de 1 hora começa em 2019.8.12 00:00 A soma de pedidos de transações por hora (a principal observação de como os preços são sintetizados não é mostrada nos dados de transações) não é descrita aqui.

    A linha K de quatro horas é composta por: Altura: 11447.07 Abre: 11382.57 Baixo: 11365.51 Coleção:11384.71 Hora: 19 de agosto de 2019

    img

    A partir de agora, o número de casos confirmados no país aumentou.

  • Implementação de código

    Depois de validar a ideia inicial, é possível escrever manualmente um código para realizar essa necessidade inicialmente.

    O código é apenas para referência:

      function GetNewCycleRecords (sourceRecords, targetCycle) {    // K线合成函数
          var ret = []
          
          // 首先获取源K线数据的周期
          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++) {
              // 获取 时区偏移数值
              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 
      }
    
      // 测试
      function main () {
          while (true) {
              var r = exchange.GetRecords()                           // 原始数据,作为合成K线的基础K线数据,例如要合成4小时K线,可以用1小时K线作为原始数据。
              var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4)      // 通过 GetNewCycleRecords 函数 传入 原始K线数据 r , 和目标周期, 1000 * 60 * 60 * 4 即 目标合成的周期 是4小时K线数据。
    
              $.PlotRecords(r2, "r2")                                 // 策略类库栏 可以勾选画线类库,调用 $.PlotRecords 画线类库 导出函数 画图。
              Sleep(1000)                                             // 每次循环间隔 1000 毫秒,防止访问K线接口获取数据过于频繁,导致交易所限制。
          }
      }
    

    Na verdade, para sintetizar linhas K, são necessárias duas coisas: primeiro, precisamos de dados de matérias-primas, ou seja, dados de linhas K de pequenos ciclos.var r = exchange.GetRecords()Os dados de linha K de pequenos ciclos obtidos. Em segundo lugar, é necessário definir o quão grande é o ciclo, ou seja, o ciclo alvo para a síntese de dados de linha K. O algoritmo da função GetNewCycleRecords é usado para retornar dados de uma estrutura de arquivos de linha K sintetizada. O que é importante lembrar:

    • 1, o ciclo de destino não pode ser menor do que o ciclo da linha K da função GetNewCycleRecords como matéria-prima de dados. A partir daí, a empresa começou a trabalhar com os seus clientes, porque não era possível sintetizar dados de períodos menores com períodos menores.

    • 2, os ciclos de alvo definidos devem ser de ciclo fechado. O que é o fechamento de ciclo? Simplificando, é uma combinação de intervalos de tempo de ciclos de objetivos dentro de uma hora ou dentro de um dia, formando um ciclo fechado. Exemplos: Por exemplo, a linha K de um ciclo de 12 minutos, que começa a partir de 0 minutos e 0 segundos de cada hora (por exemplo, 0 horas), o primeiro ciclo é00:00:00 ~ 00:12:00O segundo ciclo é:00:12:00 ~ 00:24:00O terceiro ciclo é00:24:00 ~ 00:36:00O quarto ciclo é:00:36:00 ~ 00:48:00O quinto ciclo é:00:48:00 ~ 01:00:00A partir daí, o programa foi lançado no Brasil, onde foi exibido em todo o mundo.

      Se for um ciclo de 13 minutos, ou um ciclo não fechado, os dados calculados para esse ciclo não são únicos, pois os dados sintetizados variam de acordo com o ponto de partida dos dados sintetizados.

    O disco real começou a funcionar:img

    Gráfico de trocaimg

  • Estruturas de dados necessárias para construir dados de linha K

    Muitas vezes os amigos perguntam: "Quero calcular a média do preço mais alto de cada linha K, e como?"

    Normalmente, a linha média é calculada como a média do preço de fechamento calculado, que compõe a linha média, mas às vezes é necessário calcular o preço máximo, o preço mínimo, o preço de abertura, etc. Não podemos fazer isso diretamente.exchange.GetRecords()Os dados da linha K que a função retorna são transmitidos diretamente para a função de cálculo do indicador.

    Por exemplo:talib.MAA função de cálculo de indicadores homogêneos tem dois parâmetros, o primeiro parâmetro é o parâmetro de dados a serem transmitidos e o segundo parâmetro é o parâmetro de ciclo do indicador. Por exemplo, vamos calcular o indicador do diagrama abaixo.img

    O ciclo da linha K é de 4 horas. No gráfico da bolsa, uma linha média com um parâmetro de ciclo de linha média de 9 é definida. A fonte de dados que é calculada é o preço mais alto por Bar.imgOu seja, esta linha média é a média calculada do preço máximo de 9 ciclos de 4 horas K-LineBar, que é composta por uma linha média de indicadores.

    Nós construímos um cálculo de dados para ver se ele é o mesmo que o gráfico da bolsa.

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

    Uma vez que o valor médio do preço mais alto de cada Bar deve ser calculado, obtém-se um indicador linear. Em seguida, é necessário construir uma matriz em que cada elemento de dados é o valor máximo correspondente a cada Bar. Podemos ver que as variáveis highs começam como uma matriz vazia, e então vamos percorrer a variável de dados da linha K, r2 (não se lembram de r2? Vejam o código na função principal acima para a síntese da linha K de 4 horas). Leia o valor máximo de r2 por Bar (ou seja, r2[i].High, i vale o intervalo de 0 a r2.length - 1), e empurre para highs.

    Neste momento, os highs podem ser transmitidos para o talib.

    Exemplo completo:

    function main () {
        while (true) {
            var r = exchange.GetRecords()
            var r2 = GetNewCycleRecords(r, 1000 * 60 * 60 * 4)
            if (!r2) {
                continue
            }
            
            $.PlotRecords(r2, "r2")                                               // 画出K线
            
            var highs = []
            for (var i = 0 ; i < r2.length ; i++) {
                highs.push(r2[i].High)
            }
            
            var ma = talib.MA(highs, 9)                                           // 用均线指标函数 talib.MA 计算 均线指标
            $.PlotLine("high_MA9", ma[ma.length - 2], r2[r2.length - 2].Time)     // 使用画线类库把均线指标画在图表上
            
            Sleep(1000)
        }
    }
    

    Re-teste em execução:

    img

    Como você pode ver no gráfico, o valor do indicador da linha média da posição do rato é11466.9289

    O código acima pode ser copiado para executar testes na política, e lembre-se de salvar depois de selecionar "Draw Line Library"!

  • Como obter dados da linha K do mercado de moeda digital

    Os inventores da plataforma de negociação quantitativa já possuem uma interface embalada, a função exchange.GetRecords, para obter dados de linha K. A seguir, o foco é o acesso direto à interface de dados da linha K do exchange para obter dados, pois às vezes é necessário especificar parâmetros para obter mais linhas K, com a interface GetRecords embalada. Normalmente, o retorno é de 100 bits. Se a estratégia inicialmente requer mais de 100 K-strings, é necessário coletar e esperar. Para que a política funcione o mais rápido possível, é possível envelopar uma função por conta própria, acessar diretamente a interface da linha K da bolsa e especificar parâmetros para obter mais dados da linha K.

    Com o BTC_USDT como exemplo de par de transações, nós realizamos esta necessidade:

    Para encontrar a documentação da API da bolsa, veja a descrição da interface da linha K:img

    https://api.huobi.pro/market/history/kline?period=1day&size=200&symbol=btcusdt
    

    Parâmetros:

    Nome do parâmetro Tipo É necessário? Descrição Valorização
    símbolo cordel verdade Negociação Não, não, não, não.
    período cordel verdade Retorna o tempo dos grânulos de dados, ou seja, o intervalo de tempo de cada linha. 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 teste:

    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")
    }
    

    A versão em Python, exemplo de como acessar a interface do exchange:

#!python3
import json
import urllib2

def GetRecords_Huobi(period, size, symbol):
    headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
    url = "https://api.huobi.pro/market/history/kline?" + "period=" + period + "&size=" + size + "&symbol=" + symbol
    request = urllib2.Request(url)  
    request.add_header('User-Agent','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6')  
    opener = urllib2.build_opener()  
    f= opener.open(request)  
    ret = f.read().decode('utf-8')  
    
    try :
        jsonData = json.loads(ret)
        
        records = []
        for i in range(len(jsonData["data"]) - 1, -1, -1):
            records.append({
                "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
    except Exception as e:
        Log(e)
        
def main():
    r = GetRecords_Huobi("1day", "300", "btcusdt")
    Log(len(r))
    ext.PlotRecords(r, "K")   # 需要引用Python画线类库


A versão em Python, exemplo de interface K-line para acessar o Bitcoin Exchange:

#!python3
import json
import urllib2

def GetRecords_Huobi(period, size, symbol):
    headers = {'User-Agent':'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6'}
    url = "https://api.binance.com/api/v3/klines?symbol=" + symbol + "&interval=" + period
    request = urllib2.Request(url)  
    request.add_header('User-Agent','Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.1.6) Gecko/20091201 Firefox/3.5.6')  
    opener = urllib2.build_opener()  
    f= opener.open(request)  
    ret = f.read().decode('utf-8')  
    try :
        jsonData = json.loads(ret)
        
        records = []
        for i in range(len(jsonData)):
            records.append({
                "Time" : float(jsonData[i][0]),
                "High" : float(jsonData[i][2]), 
                "Open" : float(jsonData[i][1]), 
                "Low" : float(jsonData[i][3]), 
                "Close" : float(jsonData[i][4]), 
                "Volume" : float(jsonData[i][5]), 
            })
        return records
    except Exception as e:
        Log(e)
        
def main():
    r = GetRecords_Huobi("1m", "300", "BTCUSDT")
    Log(len(r))
    ext.PlotRecords(r, "K")   # 需要引用Python画线类库


img

img

Como pode ver no log, imprima records.length para 300, ou seja, registros K linha de barras de dados com 300 caracteres.img


Relacionados

Mais.

BamsmenNão é possível sintetizar k dias em 3 horas ou 6 horas.

Bamsmenif (((1000 * 60 * 60 * 24) - sourceRecords[i].Time % (1000 * 60 * 60 * 24) + (n * 1000 * 60)) % targetCycle == 0) { isBegin = verdadeiro Não. A frase tem um problema, não é possível sintetizar k dias em 3 horas ou 6 horas, só é possível sintetizar k dias em linha de 1 hora, 2 horas e 4 horas.

xis2004Se você quiser escalar toda a história de uma espécie, você pode escalar?

WillzhangObrigado pela resposta.

WillzhangPor favor, como é melhor se você quiser mais de 300 bits? Por exemplo, 1000 K-lines de dados.

Sonhos pequenosO que você está fazendo aqui é muito ruim.

Sonhos pequenosÉ o número de dados que você recebe para acessar a interface da bolsa.

Sonhos pequenosSe exceder o número máximo de retornos suportados pela interface da bolsa, só será possível coletar dados, por exemplo, uma quantidade suficiente de dados da linha K.