O recurso está a ser carregado... Carregamento...

Converter qualquer ciclo de linha K

Autora:Inventor quantificado - sonho pequeno, Data: 16 de fevereiro de 2017
Tags:Extent-API

Exemplos de estratégias

  • Converte a linha K básica para qualquer ciclo de linha K
  • Temporariamente não suportado Nível de segundos A versão de teste, se houver bugs e problemas, é bem-vinda para comentários.

// K线周期合成  扩展为 根据基础K线 合成 为任意周期。
var cloneObj = function(obj) {                             // 深拷贝 对象函数
    var str, newobj = obj.constructor === Array ? [] : {};
    if (typeof obj !== 'object') {
        return;
    } else if (JSON) {
        str = JSON.stringify(obj);                         //系列化对象
            newobj = JSON.parse(str);                      //还原
    } else {
        for (var i in obj) {
            newobj[i] = typeof obj[i] === 'object' ?
                cloneObj(obj[i]) : obj[i];
        }
    }
    return newobj;
};

var DAY = 0;
var HOURS = 1;
var MINUTES = 2;
var isFirstFind = true;
var FirstStamp = null;

function GetDHM(objTime, BaseCycle, NewCycleForMS){
    var ret = [];
    if(BaseCycle % (1000 * 60 * 60 * 24) === 0){
        ret[0] = objTime.getDate();
        ret[1] = DAY;
    }else if(BaseCycle % (1000 * 60 * 60) === 0){
        ret[0] = objTime.getHours();
        ret[1] = HOURS;
    }else if(BaseCycle % (1000 * 60) === 0){
        ret[0] = objTime.getMinutes();
        ret[1] = MINUTES;
    }
    if(NewCycleForMS % (1000 * 60 * 60 * 24) === 0){
        ret[2] = DAY;
    }else if(NewCycleForMS % (1000 * 60 * 60) === 0){
        ret[2] = HOURS;
    }else if(NewCycleForMS % (1000 * 60) === 0){
        ret[2] = MINUTES;
    }
    return ret;
}

function SearchFirstTime(ret, BaseCycle, NewCycleForMS){
    if(ret[1] === DAY && ret[2] === DAY){ 
        var array_day = [];
        for(var i = 1 ; i < 29; i += (NewCycleForMS / BaseCycle)){
            array_day.push(i);
        }
        for(var j = 0 ; j < array_day.length; j++ ){
            if(ret[0] === array_day[j]){
                return true;
            }
        }
    }else if(ret[1] === HOURS && ret[2] === HOURS){
        var array_hours = [];
        for(var i = 0 ; i < 24; i += (NewCycleForMS / BaseCycle)){
            array_hours.push(i);
        }
        for(var j = 0 ; j < array_hours.length ; j++){
            if(ret[0] === array_hours[j]){
                return true;
            }
        }
    }else if(ret[1] === MINUTES && ret[2] === MINUTES){
        var array_minutes = [];
        for(var i = 0; i < 60; i += (NewCycleForMS / BaseCycle)){
            array_minutes.push(i);
        }
        for(var j = 0; j < array_minutes.length; j++){
            if(ret[0] === array_minutes[j]){
                return true;
            }
        }
    }else{
        throw "目标周期与基础周期不匹配!目标周期毫秒数:" + NewCycleForMS + " 基础周期毫秒数: " + BaseCycle;
    }
}

function Calc_High(AssRecords, n, BaseCycle, NewCycleForMS){
    var max = AssRecords[n].High;
    for(var i = 1 ; i < NewCycleForMS / BaseCycle; i++){
        max = Math.max(AssRecords[n + i].High, max);
    }
    return max;
}

function Calc_Low(AssRecords, n, BaseCycle, NewCycleForMS){
    var min = AssRecords[n].Low;
    for(var i = 1 ; i < NewCycleForMS / BaseCycle; i++){
        min = Math.min(AssRecords[n + i].Low, min);
    }
    return min;
}

function AssembleRecords(records, NewCycleForMS) {
    var AssRecords = records.slice(0); // 深拷贝
    var AfterAssRecords = [];
    
    if(!records || records.length < 2){
        throw (!records) ? "传入的records参数为 错误" + records : "基础K线长度小于2";
    }
    var BaseCycle = records[records.length - 1].Time - records[records.length - 2].Time;
    if(NewCycleForMS % BaseCycle !== 0){
        throw "目标周期‘" + NewCycleForMS + "’不是 基础周期 ‘" + BaseCycle + "’ 的整倍数,无法合成!";
    }
    if(NewCycleForMS / BaseCycle > records.length){
        throw "基础K线数量不足,请检查是否基础K线周期过小!";
    }

    // 判断时间戳, 找到 基础K线  相对于 目标K线的起始时间。
    var objTime = new Date();
    for (var i = 0; i < AssRecords.length; i++) {
        objTime.setTime(AssRecords[i].Time);
        var ret = GetDHM(objTime, BaseCycle, NewCycleForMS); 
        
        if (isFirstFind === true && SearchFirstTime(ret, BaseCycle, NewCycleForMS) === true) {
            FirstStamp = AssRecords[i].Time;
            for (j = 0; j < i; j++) {
                AssRecords.shift();        // 把目标K线周期前不满足合成的数据排除。
            }
            isFirstFind = false;
            break;                         // 排除后跳出
        }else if(isFirstFind === false){
            if((AssRecords[i].Time - FirstStamp) % NewCycleForMS === 0){
                for (j = 0; j < i; j++) {
                    AssRecords.shift();    // 把目标K线周期前不满足合成的数据排除。
                }
                break;
            }
        }
    }
    var BarObj = {                         // 定义一个 K线柱结构
        Time: 0,
        Open: 0,
        High: 0,
        Low: 0,
        Close: 0,
        Volume: 0,
    };
    var n = 0;
    for (n = 0; n < AssRecords.length - (NewCycleForMS / BaseCycle); n += (NewCycleForMS / BaseCycle)) {     // 合成
        /*
        {
        Time    :一个时间戳, 精确到毫秒,与Javascript的 new Date().getTime() 得到的结果格式一样
        Open    :开盘价
        High    :最高价
        Low :最低价
        Close   :收盘价
        Volume  :交易量
        }
        */
        BarObj.Time = AssRecords[n].Time;
        BarObj.Open = AssRecords[n].Open;
        BarObj.High = Calc_High(AssRecords, n, BaseCycle, NewCycleForMS); 
        BarObj.Low =  Calc_Low(AssRecords, n, BaseCycle, NewCycleForMS); 
        BarObj.Close = AssRecords[n + (NewCycleForMS / BaseCycle) - 1].Close;
        BarObj.Volume = AssRecords[n + (NewCycleForMS / BaseCycle) - 1].Volume;
        AfterAssRecords.push(cloneObj(BarObj));
    }
    
    BarObj.Time = AssRecords[n - (NewCycleForMS / BaseCycle)].Time + NewCycleForMS;  // 最后一根时间不能变,
    BarObj.Open = AssRecords[n].Open;
    BarObj.Close = AssRecords[AssRecords.length - 1].Close;
    BarObj.Volume = AssRecords[AssRecords.length - 1].Volume;
    var max = AssRecords[n].High;
    var min = AssRecords[n].Low;
    for(var index_n = n + 1 ;index_n < AssRecords.length; index_n++){
        max = Math.max(max, AssRecords[index_n].High);
        min = Math.min(min, AssRecords[index_n].Low);
    }
    BarObj.High = max;
    BarObj.Low = min;
    AfterAssRecords.push(cloneObj(BarObj));

    return AfterAssRecords;
}

function main() {                                                    // 测试代码
    var records = exchange.GetRecords();
    while (!records || records.length < 24) {
        records = exchange.GetRecords();
    }
    
    // 处理界面参数,  如果写到自己的策略里面 可以参考下
    var Num_UI_NewCycleForMS = 1;
    var arrayNum = UI_NewCycleForMS.split("*");
    for(var indexNum = 0 ; indexNum < arrayNum.length ; indexNum++){
        Num_UI_NewCycleForMS = Num_UI_NewCycleForMS * Number(arrayNum[indexNum]);
    }
    Log("自定义周期毫秒时间为:", Num_UI_NewCycleForMS);
    

    while(true){
        records = _C(exchange.GetRecords);
        // Log("原始K线数据:长度", records.length, "数据:", records);
        records = AssembleRecords(records, Num_UI_NewCycleForMS);        // 第一个参数是 基础K线, 第二个参数是 要转换的周期的 毫秒数, 1000 * 60 * 20 就是 转换为 20分钟
        // Log("转换后K线数据:长度", records.length, "数据:", records);
        $.PlotRecords(records, 'BTC');
        // throw "stop"; // ceshi
        Sleep(1000);
    }
}

Relacionados

Mais.

BamsmenSe a síntese da linha de 18 horas não é um problema, a síntese da linha de dia é um erro.

BamsmenA lógica do getDHM parece ter um pouco de problemas, com um total de erros: os ciclos de destino não correspondem aos ciclos de base!

qunxiang_wangOlá, por que você não está integrando um circuito no API?

XiaoxiaoluOlá, você pode resolver isso? Minha estratégia porque isso já não pode ser rastreado

XiaoxiaoluPor que o ciclo da linha K foi selecionado em 1 minuto quando o teste foi feito com o OKEX, mas não retornou o objetivo? O ciclo é de 240000 toneladas, não é o ciclo base. O ciclo é de 180000 toneladas, não é possível sintetizar!

super888O código é uma linha K de 4 horas, que se repete normal em 30 minutos (a linha K do gráfico é de 4 minutos de intervalo) e não normal em 5 minutos (de 12 horas de tempo de repetição para 1 hora de linha K)

Inventor quantificado - sonho pequenoSim, esse código sintético foi escrito muito antes, você pode ler este: https://www.fmz.com/digest-topic/4154.

BamsmenObrigado, eu estou usando esta função de síntese não porque eu preciso usar o k-line cycle que não é fornecido pela bolsa, mas porque a política precisa usar o ciclo de horas e dia ao mesmo tempo, então, se você chamar duas vezes a função GetRecords para obter 3 horas e dias, respectivamente, será que o fundo do fmz vai enviar duas solicitações de rede?

Inventor quantificado - sonho pequenoAgora, a plataforma suporta diretamente os ciclos de linha K personalizados e você pode usar diretamente as funcionalidades da plataforma.

Inventor quantificado - sonho pequenoAlgumas trocas suportam dados de circunferência, algumas não, geralmente são feitas em pacotes para ciclos unificados. Outros ciclos podem ser sintetizados com ciclos menores.

Inventor quantificado - sonho pequenoEu testei a linha K para definir um ciclo de 1 minuto, e o parâmetro inferior para definir 1000 * 60 * 4 é 4 minutos, o que significa que é possível sintetizar a linha K.

XiaoxiaoluVocê pode experimentar o teste de dados, selecionar o OKEX e definir a linha K básica para 1 minuto, e depois para 4 minutos, e você receberá um erro como o meu. O ciclo de potássio de 240000 toneladas não é o ciclo de base. O ciclo de potássio de 180000 toneladas é um múltiplo inteiro, não pode ser sintetizado!

XiaoxiaoluEste é o meu código while (true) { registros = Call ((exchange.GetRecords, PERIOD_M1); //Log (("Dados de linha K primários: comprimento", records.length, "Dados:", records); records = AssembleRecords ((records, Num_UI_NewCycleForMS); // O primeiro parâmetro é a linha base K, o segundo parâmetro é o milissegundo de ciclo a ser convertido, 1000 * 60 * 20 ou a conversão para 20 minutos // Log (("após a conversão de dados da linha K: comprimento", records.length, "data:", records); O site oficial da empresa é o.plotRecords. // throw "stop"; // ceshi Sleep ((1000); Não. Esta é a configuração do parâmetro https://dn-filebox.qbox.me/e0f51cd46827d68f42cbeffadba1c7a842fb0fb1.jpg A definição é de um minuto, mas sugere que o ciclo da linha K básica é de três minutos, o que não aconteceu antes.

Inventor quantificado - sonho pequenoO que você pode fazer para rever os parâmetros definidos no screenshot abaixo ou diretamente no grupo QQ.

Inventor quantificado - sonho pequenoAgora é atualizado, fazendo um processamento que requer um ciclo básico para ser consistente com o ciclo objetivo, por exemplo, o ciclo objetivo é para ser sintetizado em 6 horas, o ciclo básico é para ser usado em 1 hora, usando menos problemas, mas também para coletar muitos talentos. Você pode testar, ou se houver algum problema com o uso, sugiro que me deixe uma mensagem, ou pode me fazer um QQ.

Inventor quantificado - sonho pequenoObrigado pela pergunta, eu verifiquei o código.