Type/to search
8
Follow
1363
Followers
Uma breve discussão sobre o processamento de dados da linha K em negociação programada
Discussions
Created 2019-08-13 11:11:38  Updated 2023-10-20 20:06:13
 8
 4967

img

Uma breve discussão sobre o processamento de dados da linha K em negociação programada

Ao escrever estratégias de negociação programáticas, usando dados da linha K, geralmente é necessário usar alguns dados da linha K de período não padrão, como dados da linha K de período de 12 minutos, dados da linha K de período de 4 horas, geralmente esse tipo de não padrão O período não pode ser obtido diretamente. Então, como respondemos a essas demandas?
A resposta é que definitivamente há um jeito.
Ciclos não padronizados podem ser obtidos pela fusão e síntese de dados de ciclos menores. Você pode imaginar que o preço mais alto em vários ciclos é contado como o preço mais alto após a síntese, e o preço mais baixo é contado como o preço mais baixo após a síntese. A abertura o preço não mudará. , o primeiro preço de abertura dos dados da matéria-prima da linha K sintetizada é usado, o preço de fechamento corresponde ao último preço de fechamento dos dados da matéria-prima da linha K sintetizada, o tempo é o tempo do preço de abertura e o volume de negociação é calculado pela soma dos volumes de transação dos dados da matéria-prima.
Conforme mostrado na imagem:

  • Ideias

    Tomamos o mercado de ativos de blockchain BTC_USDT como exemplo e sintetizamos 1 hora em 4 horas.

    img

    img

    img

    img

    HoraMáximaAberturaMínimaFechamento
    2019.8.12 00:0011447.0711382.5711367.211406.92
    2019.8.12 01:001142011405.6511366.611373.83
    2019.8.12 02:0011419.2411374.6811365.5111398.19
    2019.8.12 03:0011407.8811398.5911369.711384.71

    Os dados desses quatro ciclos de 1 hora são combinados em dados de ciclo de 4 horas. O preço de abertura é o preço de abertura do primeiro tempo 00:00: 11382,57
    O preço de fechamento é o último, ou seja, o preço de fechamento às 03:00: 11384,71
    O preço mais alto é o preço mais alto aqui: 11447,07
    O menor preço está aqui: 11365.51
    O horário de início do ciclo de 4 horas é 00:00, o horário de início da linha K de 1 hora, ou seja, 2019.8.12 00:00
    O volume de negociação pode ser somado a cada 1 hora (principalmente para observar como o preço é sintetizado, o que não é mostrado nos dados de volume de negociação). Não entrarei em detalhes aqui.

    A linha K sintetizada de 4 horas é:
    Máxima: 11447,07
    Aberto: 11382.57
    Baixo: 11365,51
    Recebido: 11384.71
    Hora: 2019.8.12 00:00

    img

    Você pode ver que os dados são consistentes.

  • Escreva código para implementar

    Depois de verificar as ideias preliminares, você pode começar a escrever algum código para implementar preliminarmente esse requisito.

    Libere o código diretamente, 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 K-line, duas coisas são necessárias. A primeira são dados de matéria-prima, ou seja, dados K-line de um pequeno período.var r = exchange.GetRecords()
    Dados obtidos da linha K de pequeno período. A segunda é definir claramente o período de síntese, ou seja, o período-alvo para a síntese de dados da linha K.
    Então, por meio do algoritmo da função GetNewCycleRecords, os dados de uma estrutura de matriz K-line sintetizada podem ser finalmente retornados.
    Deve-se notar que:

      1. O ciclo de destino não pode ser menor que o ciclo da linha K que você passa para a função GetNewCycleRecords como matéria-prima de dados.
        Isso ocorre porque é impossível usar um ciclo pequeno para sintetizar dados de um ciclo menor.
      1. O período alvo definido deve ser um período fechado.
        O que é fechamento de ciclo?
        Simplificando, dentro de uma hora ou um dia, os intervalos de tempo do ciclo alvo são combinados para formar um ciclo fechado.
        Exemplo:
        Por exemplo, a linha K de um ciclo de 12 minutos começa em 0:00 de cada hora (tome 0:00 como exemplo), e o primeiro ciclo é00:00:00 ~ 00:12:00, 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 , o que perfaz 1 hora completa.

      Se for um ciclo de 13 minutos, é um ciclo aberto, e os dados calculados em tal ciclo não são únicos, porque os dados sintetizados serão diferentes dependendo do ponto de partida dos dados sintetizados.

    O disco real foi executado:
    img

    Comparar gráficos de câmbio
    img

  • Use dados da linha K para construir a estrutura de dados necessária

    Os membros do grupo costumam fazer perguntas: Quero calcular a média móvel do preço mais alto de cada linha K, o que devo fazer?

    Normalmente, calculamos a média móvel calculando a média dos preços de fechamento para formar a média móvel, mas às vezes é necessário calcular o preço mais alto, o preço mais baixo, o preço de abertura, etc.
    Neste momento, você não pode simplesmenteexchange.GetRecords() Os dados da linha K retornados pela função são passados ​​diretamente para a função de cálculo do indicador.

    Por exemplo:
    A função de cálculo do indicador de média móvel talib.MA tem dois parâmetros. O primeiro parâmetro são os dados que precisam ser passados, e o segundo parâmetro é o parâmetro do período do indicador.
    Por exemplo, queremos calcular os seguintes indicadores
    img

    O ciclo da linha K é de 4 horas.
    No gráfico de câmbio, uma média móvel foi definida com um parâmetro de período de média móvel de 9.
    E a fonte de dados para cálculo é definida como o preço mais alto de cada barra.
    img
    Ou seja, essa média móvel é a média dos preços mais altos de 9 barras da linha K de 4 horas, que constituem a média móvel do indicador.

    Vamos construir alguns dados nós mesmos e ver se eles são os mesmos que os calculados pelo gráfico da bolsa.

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

    Precisamos calcular a média dos preços mais altos de cada barra para derivar o indicador de média móvel.
    Então você precisa primeiro construir uma matriz, na qual cada elemento de dados corresponde ao preço mais alto de cada barra.
    Você pode ver que a variável highs é inicialmente uma matriz vazia, e então percorremos a variável de dados do candlestick r2 (não se lembra do r2? Veja o código na função principal de sintetizar o candlestick de 4 horas acima).
    Leia o preço mais alto de cada barra de r2 (ou seja, r2[i].High , i varia de 0 a r2.length - 1 ), e então o empurra para highs . Dessa forma, é construída uma estrutura de dados que corresponde um a um com a barra de dados da linha K.

    Neste ponto, os máximos podem ser passados ​​para a função talib.MA 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") // 画出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) } }

    Execução de backtest:

    img

    Você pode ver que os valores do indicador de média móvel na posição do mouse na figura são11466.9289

    O código acima pode ser copiado para a estratégia para executar o teste. Lembre-se de verificar "Line Drawing Library" e salvá-lo!

  • Como obter dados K-line no mercado de moeda digital

    A plataforma de negociação quantitativa Inventor já possui uma interface empacotada, a função exchange.GetRecords, que pode obter dados da linha K.
    O seguinte se concentra no acesso direto à interface de dados K-line do Exchange para obter dados, porque às vezes você precisa especificar parâmetros para obter mais K-lines, interface GetRecords encapsulada
    Geralmente 100 são retornados. Se a estratégia exigir inicialmente mais de 100 K-lines, você precisará coletar e esperar.
    Para fazer a estratégia ser executada o mais rápido possível, você pode encapsular uma função, acessar diretamente a interface K-line da exchange e especificar parâmetros para obter mais dados K-line.

    Tomando o par de negociação BTC_USDT da Huobi como exemplo, implementamos este requisito:

    Encontre a documentação da API da exchange e veja a descrição da interface K-line:
    img

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

    parâmetro:

    Nome do parâmetroTipoObrigatórioDescriçãoValor
    símbolostringverdadeiroPar de negociaçãobtcusdt, ethbtc...
    períodostringverdadeiroRetorna a granularidade de tempo dos dados, ou seja, o intervalo de tempo de cada vela1min, 5min, 15min, 30min, 60min, 1dia, 1mês, 1semana, 1ano
    tamanhointeirofalsoRetorna o número de dados da linha 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") }

    Versão Python, exemplo de acesso à interface de troca Huobi:

#!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画线类库

Versão Python, um exemplo de acesso à interface K-line da Binance 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

Podemos ver no log que records.length é 300, o que significa que há 300 barras de dados de registros K-line.
img

Related Recommendations
Comment
All comments (8)

    贴主能修复一下问题么?无法用3小时或6小时k合成日k

    6 years ago

    好的,抽时间改改。

    6 years ago

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

    这一句有问题,无法用3小时或6小时k合成日k,只能用1小时,2小时,4小时的k线合成日k

    6 years ago

    如果要爬某品种全部的历史数据也能爬么?

    6 years ago

    这是访问交易所接口数据的,交易所给你多少数据就是多少。也就是最近的几百根吧一般来说。

    6 years ago

    感谢回复

    7 years ago

    请问,如果想要超过300根,怎么处理比较好呢?比如1000根K线数据。交易所单次好像支持每次300根。多谢

    7 years ago

    如果 超过交易所接口支持的最大返回数量,这样只能收集数据,等足够K线数据量。

    7 years ago
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)