Konvertieren von beliebigen K-Line-Zyklus-Management-Templates (zuletzt aktualisiert 20180627)

Schriftsteller:In der Mitte, Datum: 22.05.2017
Tags:Extent-API

Aktualisiert auf 20171114 a. Lösung des Problems, dass Open nicht gefunden werden kann, der durch den Zugriff auf die Grenze der Record-Array verursacht wurde, der durch den Zugriff auf die Grenze verursacht wurde, der durch ein Problem mit der vorherigen K-Leitung verursacht wurde. Aktualisiert auf 20171113 a. Filtern Sie falsche K-Strangkombinationen ab b. Filtern Sie falsche K-Strangkombinationen aus den Zeitintervallen aus Aktualisiert auf 20170622 a. RecordsManager fügt Name-Parameter hinzu, um unterschiedliche K-Linien zu unterscheiden b. Fix Problem, dass Time nicht korrekt berechnet wird, wenn die Anzahl der festen K-Streams eine neue K-Stream-Periode nicht erfüllt

Aktualisiert auf 20170531 a. Fehler bei der Berechnung des Volumens

  1. Modifizierung der Template "Konvertieren von beliebigen K-Linienzyklen" von Little Dream

Das Prinzip:

  • Wir erhalten eine Periode von festen K-Linien, und dann synthetisieren wir eine neue Periode von beliebigen festen K-Linien, die ein ganzes Vielfaches der festen K-Linien sind.

Funktionen:

  • Konvertiert Basis-K-Linien in beliebige K-Linienzyklen
  • Momentan nicht unterstützt Sekundenebene

Beschränkung:

  • 新K线周期必须是固定K线周期的整数倍.
  • Die festen K-Linienzyklen sind 1min, 3min, 5min, 15min, 30min, die neuen K-Linienzyklen müssen ebenfalls Minuten und <60 sein.
  • Die feste K-Linien-Zyklus ist 1 Stunde, die neue K-Linien-Zyklus muss auch Stunden und < 24 sein.
  • Die feste K-Linien-Zyklus ist 1 day, die neue K-Linien-Zyklus muss auch Tag sein.
  • Die Anzahl der Perioden der festen K-Linien, die jedes Mal erhalten werden, muss > = 2 sein. Testversionen, Fehler, Probleme, Kommentare sind herzlich eingeladen.

Ausgabe: $.RecordsManager (NewCycleMS, Name) erstellt einen neuen Zyklusmanager NewCycleMS für neue K-Linien-Zyklen.6060*2) 2 Stunden. Name: Geben Sie einen Namen für die K-Leitung an Zurück zum K-Line-Manager Es gibt auch eine Reihe von anderen Programmen, die von den Benutzern unterstützt werden. Records: Die ursprünglichen aufgezeichneten BaseCycleMS für feste K-Linienzyklen in Millisekunden, die standardmäßig mit Fixedrecords berechnet werden Wiederherstellen von Rekords für neue K-Linien-Zyklen $.GetRecordsTable(n) Erhält die neuesten N Einträge in der neuen K-Zeile, führt alle Einträge standardmäßig aus, wird als Table-Typ ausgeführt, um LogStatus-Ausfuhren zu erleichtern Ein paar grundlegende Informationen erhalten.


/*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);
    }
}


Verwandt

Mehr

ZerozakiIch habe die falsche K-Zeit. Das ist nicht wahr. Die Daten, die wir erhielten, zeigten: Ich weiß nicht. 2018-07-30 19:00:00.000+08:00 8162.42 8187.69 8200 8156.84 681.53875929 2018-07-30 12:00:00.000+08:00 8192.91 8185.3 8209.35 8151 902.81758958 Die Zahl der Menschen, die in der Welt leben, ist sehr hoch. 2018-07-30 08:00:00.000+08:00 8213.11 8154.49 8225.18 8051 899.96507317 2018-07-30 04:00:00.000 +08:00 8214.25 8191.52 8229.08 8190.03 879.26269857 2018-07-30 00:00:00.000+08:00 8234.88 8185.32 8247.36 8170.04 817.78392428 Das ist ein sehr gutes Beispiel für eine gute Beziehung. Ich weiß nicht. Die Daten, die bislang für den 7-Tage-Zyklus eingetroffen wurden, sind: Ich weiß nicht. 2018-08-05 08:00:00.000+08:00 8213.11 8186.16 8278.23 8051 7869.96734215 2018-07-29 08:00:00.000+08:00 8235.84 8213.63 8301.2 8116.8 20943.43495 2018-07-28 08:00:00.000+08:00 8187.47 8236.39 8245.23 8070 21465.51463651 2018-07-27 08:00:00.000+08:00 7930.92 8188.83 8278 7800.44 22985.16836742 Einige von ihnen sind in der Nähe des Hauses. 2018-07-26 08:00:00.000+08:00 8171.44 7936.88 8316.49 7850.88 22644.64610719 2018-07-25 08:00:00.000+08:00 8404.91 8171.44 8485 8050 22036.92873654 2018-07-24 08:00:00.000+08:00 7715.53 8404.95 8498.04 7695.05 23595.19928712 2018-07-23 08:00:00.000+08:00 7395.57 7716.12 7813 7370.26 27205.92883481 2018-07-22 08:00:00.000+08:00 7402.1 7395.14 7585.15 7330.64 26186.61248972 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 Ich weiß nicht. Der Code: Ich weiß nicht. Funktion main (() { Wir haben 5 Minuten. const period_M5 = 1000 mal 60 mal 5 Das ist 4 Stunden. const period_H4 = 1000 mal 60 mal 60 mal 4 // Umkreis Das ist die konstante Periode_D7 = 1000 mal 60 mal 60 mal 24 mal 7 Das ist nicht der Fall. Zeit_M5 Zeit_H4 Period_D7 Ich bin nicht. Während (true) { Das ist ein sehr schwieriges Problem. Let records = null Wenn (Periode>Periode_D1) { records = exchange.GetRecords ((PERIOD_D1)) Log (("Tagesspiegel", records.length) } else if (Periode>Periode_H1) { records = exchange.GetRecords ((PERIOD_H1)) ist eine Website, die sich mit der Veröffentlichung von Dokumenten beschäftigt. Log (("Stundenlinie-Level", records.length) } else { records = exchange.GetRecords ((PERIOD_M1)) ist eine von zwei Webseiten, die sich in einem Netzwerk befinden. Log (("Minutenlinie-Level", records.length) Wir sind hier. const recordManager = $.RecordsManager ((period)) const newRecords = recordManager.AssembleRecords ((records, period) ist ein System, welches die Daten von einem anderen System erfasst. const table = recordManager.GetRecordsTable (siehe unten) Rückkehrtabelle Wir sind hier. LogStatus ((`\`) ${JSON.stringify ((tables) } (\``) Schlaf ((60*1000) Wir sind hier. Wir sind hier. Ich weiß nicht.

GUIGUI17FDie andere Seite kann entfernt werden, wenn man die isFirstFind-Deklaration innerhalb der Funktion erklärt, da jede isFirstFind-Deklaration wahr ist und jeder Eintritt der erste Zweig ist.

JiaozhengTypeError: kann die Eigenschaft 'Time' von undefined at main (__FILE__:525) nicht lesen Grundsätzlich ist es so, dass ein Fehlermeldungs-Stopp an einem laufenden Tag auftritt und die generierten K-Linien manchmal nicht Time finden.

In der Mitteconst newRecords = recordManager.AssembleRecords ((records, period) ist ein System, welches die Daten von einem anderen System erfasst. Es sollte nicht Period sein, es sollte nicht geschrieben werden, oder es sollte die Anzahl der Millisekunden in der Zeitspanne in der Zeile K in der Zeitspanne in der Zeitspanne in der Zeitspanne in der Zeitspanne in der Zeitspanne sein.

In der Mitteconst newRecords = recordManager.AssembleRecords ((records, period) ist ein System, welches die Daten von einem anderen System erfasst. Es sollte nicht Period sein, es sollte nicht geschrieben werden, oder es sollte die Anzahl der Millisekunden in der Zeitspanne in der K-Zeile in den Records schreiben.

ZrcahyxIch habe persönlich festgestellt, dass die Rückmessung zu früh anfängt, und ich schlage vor, dass man sich in den Code einloggt.

GUIGUI17FSollte es sein, um eine Wiederholung der Berechnung zu vermeiden?

In der MitteKannst du mir sagen, was die Parameter im RecordsManager und in AssemblerRecords sind, die ich debuggen kann?

In der MitteEs ist wahr, wie du sagst, ich habe die Logik von Little Dream damals immer noch nicht verstanden, also habe ich mich weiter mit meiner Forschung beschäftigt.

Zrcahyxmain:98:14 - TypeError: Kann die Eigenschaft 'length' von null / main:242:57 nicht lesen Das ist auch ein Problem.

In der MitteOh, gut, ich habe Zeit, um die Code-Änderungen zu überprüfen, und wenn es wieder Probleme gibt, sagen wir, die ursprüngliche K-Leitung und die neue K-Leitung, dann sehe ich, ob ich es wiederholen kann.

JiaozhengEs ist nicht klar, dass die meisten Codes nicht wissen, wo das Problem ist, aber die Original-Synthetik-Vorlage von Dreamcatcher funktioniert.

In der MitteWas ist das für ein eigenes K-Funk und ein neues K-Funk?