Conversión de cualquier K línea de gestión de ciclos de la plantilla ((actualizada recientemente 20180627)

El autor:En el centro, fecha: 22 de mayo de 2017 21:08:57
Las etiquetas:Extent-API (en inglés)

Actualizado en 20171114 a. Resolver el problema de no encontrar Open, causado por el acceso al límite de la matriz de registros, causado por el acceso al límite causado por un problema en la línea K anterior. Actualizado en 20171113 a. Filtrar combinaciones de K-strings con una hora de inicio incorrecta b. Filtrar combinaciones incorrectas de líneas K con intervalos de tiempo Actualizado en 20170622 a. RecordsManager añade parámetros de nombre para distinguir las diferentes líneas K. b. Corrección de un problema en el que Time calcula incorrectamente cuando el número fijo de K líneas no cumple un nuevo ciclo de K líneas

Actualizado en 20170531 Error de cálculo del volumen

  1. Modificación de la plantilla "Convertir cualquier ciclo de línea K" de Dream

El principio:

  • Obtener un ciclo de K líneas fijas, y luego sintetizar un nuevo ciclo de K líneas de K líneas fijas arbitrarias de múltiples veces

Función:

  • Convierte la línea base K en cualquier ciclo de línea K.
  • No está soportado por el momento

Restricciones:

  • 新K线周期必须是固定K线周期的整数倍.
  • Los ciclos fijos de K son 1min, 3min, 5min, 15min, 30min, y los nuevos ciclos de K también deben ser minutos y <60
  • El ciclo de la línea K fija es de 1 hora, el nuevo ciclo de la línea K también debe ser de horas y < 24
  • El ciclo de la línea K fija es de 1 día, y el nuevo ciclo de la línea K también debe ser de 1 día.
  • El número de ciclos fijos de la línea K que se obtiene cada vez debe ser > = 2. Las versiones de prueba, si hay algún error, si hay algún problema, bienvenidas a los comentarios.

La función de salida es: $.RecordsManager (NewCycleMS, Name) crea un nuevo administrador de ciclos NewCycleMS cuenta milisegundos para los nuevos ciclos de la línea K. Por defecto ((1000)6060*2) 2 horas. Name: Especifique un nombre para administrar la línea K Regresar al administrador de la línea K $.AssembleRecords (records, BaseCycleMS) es una aplicación de base de datos de base de datos de base de datos. Records: Los registros originales obtenidos BaseCycleMS para milisegundos de ciclos fijos de K líneas, calculado por defecto con registros fijos Regresar registros de los nuevos ciclos de la línea K $.GetRecordsTable ((n) obtiene los últimos N registros de la nueva línea K. Por defecto, se exportan todos los registros. Los usuarios de los sitios web de las redes sociales pueden obtener información básica de los sitios web de las redes sociales.


/*backtest
  period: 60
 */
/*
20180627
    修改了天无法整合的bug
20180118
    屏蔽掉一些log输出
更新于20171114
    a. 解决Open找不到问题,是record数组访问越界造成的,访问越界是之前的K线有问题导致的。
更新于20171113
    a. 过滤掉起始时间不正确的k线组合
    b. 过滤掉时间间隔不正确的k线组合
更新于20170622
     a. RecordsManager 增加Name参数,便于区分不同的K线
     b. Fix 当固定K线数目不满一根新K线周期时,Time计算不正确的问题

更新于20170531
    a. fix Volume计算错误

1. 修改自小小梦的"转换任意K线周期" 模板

原理:
  - 获得固定K线的周期,然后合成任意固定K线整数倍的新K线周期

功能:
  - 转换基础K线为任意K线周期
  - 暂时不支持 秒级别

限制:
   - 新K线周期必须是固定K线周期的整数倍.
   - 固定K线周期为1min, 3min, 5min, 15min, 30min, 新K线周期也必须是分钟且<60
   - 固定K线周期为1hour, 新K线周期也必须是小时且<24
   - 固定K线周期为1day, 新K线周期也必须是天
   - 每次获得的固定K线周期数目必须>=2
测试版本,如有BUG ,问题 欢迎留言。

输出函数:
    $.RecordsManager(NewCycleMS, Name) 生成新周期管理器
        NewCycleMS 为新K线周期毫秒数. 默认(1000*60*60*2) 2hour.
        Name: 为该K线管理指定名字
        返回K线管理器
    $.AssembleRecords(records, BaseCycleMS) 
        records: 拿到的原始records
        BaseCycleMS 为固定K线周期毫秒,默认用固定records进行计算
        返回新K线周期的records 
    $.GetRecordsTable(n) 得到新K线最新的N个条目, 默认输出所有条目, 输出为table类型,便于LogStatus输出
    $.Get***** 获得一些基本信息
*/
function EasyReadTime(millseconds) {
    if (typeof millseconds == 'undefined' ||
        !millseconds) {
        millseconds = new Date().getTime();
    }
    var newDate = new Date();
    newDate.setTime(millseconds);
    return newDate.toLocaleString();
}

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;

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 _RecordsManager(NewCycleForMS, Name) {
    if (typeof NewCycleForMS == 'string') {
        this._NewCycleForMS = 1;
        var arrayNum = NewCycleForMS.split("*");
        for(var indexNum = 0 ; indexNum < arrayNum.length ; indexNum++){
            this._NewCycleForMS = this._NewCycleForMS * Number(arrayNum[indexNum]);
        }
    } else {
        this._NewCycleForMS = NewCycleForMS;
    }
    this._Name = "";
    if (Name) {
        this._Name = Name;
    }
    this._Records = new Array();

    this.GetNewCycleForMS = function() {
        return this._NewCycleForMS;
    };
    
    this.GetRecords = function() {
        return this._Records;
    }

    this.AssembleRecords = function(records, BaseCycle) {
        var NewCycleForMS = this._NewCycleForMS;
        var AssRecords = records.slice(0); // 深拷贝
        var AfterAssRecords = [];
        
        if (!records || records.length == 0) {
            Log("record 为空@!");
            return records;
        }
        if(records.length < 2){
            throw (!records) ? "传入的records参数为 错误" + records : "基础K线长度小于2";
        }
        if (typeof BaseCycle === 'undefined') {
            BaseCycle = records[records.length - 1].Time - records[records.length - 2].Time;
        }
        if(NewCycleForMS % BaseCycle !== 0){
            //Log(EasyReadTime(records[records.length - 1].Time), EasyReadTime(records[records.length - 2].Time));
            //Log("目标周期‘", NewCycleForMS, "’不是 基础周期 ‘", BaseCycle, "’ 的整倍数,无法合成!");
            return null;
        }
        if(NewCycleForMS / BaseCycle > records.length){
            Log("records: ", records, "NewCycleForMS: ", NewCycleForMS, ", BaseCycle: ", BaseCycle);
            throw "基础K线数量不足,请检查是否基础K线周期过小!";
        }
    
        // 判断时间戳, 找到 基础K线  相对于 目标K线的起始时间。
        var objTime = new Date();
        var isFirstFind = true;
        var FirstStamp = null;
        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);) {     // 合成
            /*
            {
            Time    :一个时间戳, 精确到毫秒,与Javascript的 new Date().getTime() 得到的结果格式一样
            Open    :开盘价
            High    :最高价
            Low :最低价
            Close   :收盘价
            Volume  :交易量
            }
            */
            //时间判断
            var is_bad = false;
            var start_time = AssRecords[n].Time;
            var stop_time = AssRecords[n + (NewCycleForMS / BaseCycle) - 1].Time + BaseCycle;
            if (ret[2] != DAY && start_time % NewCycleForMS != 0) {
                //Log("过滤起始时间不正确的k线组合", EasyReadTime(start_time));
                is_bad = true;
            }
            if (stop_time - start_time != NewCycleForMS) {
                //Log("过滤时间间隔不正确的k线组合", EasyReadTime(start_time), EasyReadTime(stop_time));
                is_bad=true;
            }
            if (is_bad) {
                n++;
                continue;
            }
            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 = 0;
            for (var j = n; j < n + (NewCycleForMS / BaseCycle); j++) {
                BarObj.Volume += AssRecords[j].Volume;
            }
            AfterAssRecords.push(cloneObj(BarObj));
            n += (NewCycleForMS / BaseCycle)
        }
        
        if (n == 0) {
            BarObj.Time = AssRecords[0].Time;
        } else {
            BarObj.Time = AssRecords[n - (NewCycleForMS / BaseCycle)].Time + NewCycleForMS;  // 最后一根时间不能变,
        }
        BarObj.Open = AssRecords[n].Open;
        BarObj.Close = AssRecords[AssRecords.length - 1].Close;
        BarObj.Volume = AssRecords[n].Volume;
        //BarObj.Volume = 0;
        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.Volume += AssRecords[index_n].Volume;
        }
        BarObj.High = max;
        BarObj.Low = min;
        AfterAssRecords.push(cloneObj(BarObj));
    
        this._Records = AfterAssRecords;
        return AfterAssRecords;
    };

    this.GetKlineName = function () {
        return " " + this._NewCycleForMS / 60 / 1000 + " 分钟K线";
    };

    /* 获得records数据表格*/
    this.GetRecordsTable = function (n) {
        if (typeof n !== 'undefined' && n >=0 ) {
            var records = this._Records.slice(-n);
        } else {
            var records = this._Records.slice(0);
        }
        
        var record_array = new Array();
        for (var i = records.length - 1; i >= 0; i--) {
            var newDate = new Date();
            newDate.setTime(records[i].Time);
            var time_str = newDate.toLocaleString();
            record_array.push([time_str, records[i].Open, records[i].Close,
                               records[i].High, records[i].Low, records[i].Volume]);
        }
        var title = this._Name + " " + this.GetKlineName() + "(" + records.length + "根)";
        var table = {type: 'table', title: title,
                     cols: ['Time', 'Open','Close', 'High', 'Low', 'Volume'],
                     rows: record_array};
        return table;
    }
}

$.RecordsManager = function (NewCycleForMS, Name) {

    if (typeof NewCycleForMS === 'undefined') {
        NewCycleForMS = UI_NewCycleForMS;
    }
    var RecordsManager = new _RecordsManager(NewCycleForMS, Name);
    return RecordsManager;
}
    
function main() {
    var records = exchange.GetRecords();
    while (!records || records.length < 24) {
        records = exchange.GetRecords();
        Sleep(1000);
    }
    
    while (true) {
        records = _C(exchange.GetRecords);
        record_manager0 = $.RecordsManager(UI_NewCycleForMS, "Hello World");
        new_records0 = record_manager0.AssembleRecords(records);
        var table0 = record_manager0.GetRecordsTable();
        
        var BaseCycle = records[records.length - 1].Time - records[records.length - 2].Time;
        record_manager1 = $.RecordsManager(BaseCycle);
        new_records1 = record_manager1.AssembleRecords(records);
        var table1 = record_manager1.GetRecordsTable();
        LogStatus('`' + JSON.stringify([table0, table1, ""]) +'`');
        records = record_manager1.GetRecords();
        //Log(records[records.length-1]);
        Sleep(60000);
    }
}


Relacionados

Más.

No hay nada.La línea K está mal. ¿Qué es esto? Los datos obtenidos son los siguientes: ¿Por qué no lo haces? 2018-07-30 19:00:00.000+08:00 8162.42 8187.69 8200 8156.84 681.53875929 El año pasado, el gobierno de los Estados Unidos anunció que el gobierno de los Estados Unidos se había comprometido con el desarrollo de la tecnología de la información. 2018-07-30 12:00:00.000+08:00 8192.91 8185.3 8209.35 8151 902.81758958 El año pasado, el gobierno de los Estados Unidos anunció que el gobierno de los Estados Unidos aprobaría una nueva ley que prohibiría el uso de armas nucleares. 2018-07-30 08:00:00.000+08:00 8213.11 8154.49 8225.18 8051 899.96507317 El año pasado, el gobierno de los Estados Unidos anunció que el gobierno de los Estados Unidos se había comprometido con el desarrollo de la tecnología de la información. 2018-07-30 04:00:00.000 +08:00 8214.25 8191.52 8229.08 8190.03 879.26269857 El año pasado, el gobierno de los Estados Unidos anunció que el gobierno de los Estados Unidos se había comprometido con el desarrollo de la tecnología de la información. 2018-07-30 00:00:00.000 +08:00 8234.88 8185.32 8247.36 8170.04 817.78392428 El año pasado, el gobierno de los Estados Unidos anunció que el gobierno de los Estados Unidos había anunciado una nueva ley para la construcción de una nueva estación de tren en el país. ¿Por qué no lo haces? El ciclo de siete días es el siguiente: ¿Por qué no lo haces? 2018-08-05 08:00:00.000+08:00 8213.11 8186.16 8278.23 8051 7869.96734215 El año pasado, el gobierno de los Estados Unidos anunció que el gobierno de los Estados Unidos había anunciado una nueva ley para la construcción de un nuevo aeropuerto. 2018-07-29 08:00:00.000+08:00 8235.84 8213.63 8301.2 8116.8 20943.43495 El año pasado, el número de personas afectadas por el virus fue de 82.900. 2018-07-28 08:00:00.000+08:00 8187.47 8236.39 8245.23 8070 21465.51463651 El año pasado, el gobierno de los Estados Unidos anunció que el gobierno de los Estados Unidos aprobaría una nueva ley para proteger a los niños. 2018-07-27 08:00:00.000 +08:00 7930.92 8188.83 8278 7800.44 22985.16836742 El año pasado, el gobierno de la República Popular de China (RPC) anunció que el gobierno de la República Popular de China (RPC) había aprobado una nueva ley que prohibiría el uso de armas nucleares. 2018-07-26 08:00:00.000 +08:00 8171.44 7936.88 8316.49 7850.88 22644.64610719 El año pasado, el gobierno de la República Popular China (PRN) anunció que el gobierno de la República Popular China (PRN) había aprobado una nueva ley que prohibiría el uso de armas nucleares. 2018-07-25 08:00:00.000 +08:00 8404.91 8171.44 8485 8050 22036.92873654 El año pasado, el número de personas afectadas por el virus fue de 82.800. 2018-07-24 08:00:00.000+08:00 7715.53 8404.95 8498.04 7695.05 23595.19928712 El año pasado, el gobierno de los Estados Unidos aprobó el acuerdo para la construcción de una nueva estación de tren en la ciudad de San Francisco. 2018-07-23 08:00:00.000+08:00 7395.57 7716.12 7813 7370.26 27205.92883481 El año pasado, el gobierno de los Estados Unidos aprobó el acuerdo para la construcción de una nueva estación de tren. 2018-07-22 08:00:00.000 +08:00 7402.1 7395.14 7585.15 7330.64 26186.61248972 El año pasado, el gobierno de la República Popular China (PRN) anunció que el gobierno de la República Popular China (PRN) había aprobado una nueva ley que prohibiría el uso de armas nucleares. 2018-07-21 08:00:00.000 +08:00 7326.6 7404 7450 7210 28545.21532011 2018-07-20 08:00:00.000+08:00 7472.61 7326.59 7691.67 7265.14 28703.79798543 El año pasado, el número de personas que fueron asesinadas fue de más de un millón. ¿Por qué no lo haces? El código es: ¿Por qué no lo haces? La función principal (()) { ¿Qué es esto? Const period_M5 = 1000*60*5 Esto es lo que quiero decir con esto Y entonces, ¿qué? Const period_H4 = 1000*60*60*4 y entonces el período_H4 es igual al período_H4 // el perímetro const period_D7 es igual a 1000*60*60*24*7 Los períodos const = [ El período_M5 El tiempo es el tiempo El período_D7 ¿Qué es esto? mientras (verdadero) { Const tables = periodes.map ((period=>{ Let records = nulo Si (periodo>periodo_D1) { Record = exchange.GetRecords ((PERIOD_D1)) El registro de los registros de los registros de los registros de los registros de los registros Log (("nivel de luz del día", records.length) } else si (periodo>periodo_H1) { Record = exchange.GetRecords ((PERIOD_H1)) El registro de los registros de los registros de los registros de los registros de los registros de los registros Log (("nivel de línea de tiempo", records.length) ¿Por qué no? Record = exchange.GetRecords ((PERIOD_M1)) El registro de los registros de los registros de los registros de los registros de los registros Log (("nivel de línea de minutos", records.length) ¿Qué es eso? Const recordManager = $.RecordsManager ((period) es el nombre de un sistema de registro. const newRecords = recordManager.AssembleRecords ((records, period) es el nombre que se le da a los registros de un registro. Const tabla = recordManager.GetRecordsTable (en inglés) La tabla de retorno ¿Qué es eso? LogStatus ((`\`${JSON.stringify(tables) }\``) Sleep ((60 por 1000) ¿Qué es eso? ¿Qué es eso? ¿Por qué no lo haces?

Guigui17fEn la línea 211, si se declara isFirstFind dentro de la función, se puede eliminar la parte "else" después, ya que cada isFirstFind es verdadero y cada entrada es la primera rama, por lo que se puede leer en Log.

JiaozhengTipoError: no puede leer la propiedad 'Time' de indefinido en principal (__FILE__:525) Básicamente, en el día de ejecución se produce este tipo de interrupción de error, y las líneas generadas por K a veces no encuentran Time.

En el centroconst newRecords = recordManager.AssembleRecords ((records, period) es el nombre que se le da a los registros de un registro. No debería ser period, debería ser no escribir (si no, el programa calcula los intervalos de K líneas con records) o escribir los milisegundos de intervalos de tiempo de K líneas en records.

En el centroconst newRecords = recordManager.AssembleRecords ((records, period) es el nombre que se le da a los registros de un registro. No debería ser un período, debería no escribirlo, o escribir el intervalo de tiempo de K líneas de registros en milisegundos

Zrcahyx y otras sustanciasYo mismo he confirmado que el tiempo de inicio de retroceso es demasiado temprano, por lo que sugiero que se logue en el código.

Guigui17f¿Pero si lo dejamos fuera, si no se obtienen nuevos datos en el medio, ¿podría causar errores en el cálculo?

En el centro¿Puedes decirme cuáles son los parámetros que se dan en el Administrador de Registros y en los Registros de Asamblea para que pueda depurarlos?

En el centroEs cierto que, como dices, todavía no entiendo la lógica de Little Dream en ese momento, así que estudié más y mejoré la investigación.

Zrcahyx y otras sustanciasmain:98:14 - TypeError: Cannot read property 'length' of null / main:242:57 TypeError: no puede leer la propiedad 'Time' de undefined Y también hay un problema.

En el centroBueno, bueno, tengo tiempo para revisar el código, y si hay algún problema, digamos, la línea original y la nueva línea K, y ver si puedo reproducirlos.

JiaozhengNo sé, la mayoría del código no sabe dónde está el problema, pero la versión original de la plantilla sintética de Dream Dream funciona bien.

En el centro¿Cuál es la configuración de tu línea K y la nueva línea K?