Umwandlung beliebiger K-Linienzyklen

Schriftsteller:Kleine Träume, Datum: 16.02.2017
Tags:Extent-API

Beispiele für Strategien

  • Konvertiert Basis-K-Linien in beliebige K-Linienzyklen
  • Momentan nicht unterstützt Sekundenebene Testversionen, Fehler, Probleme, Kommentare sind herzlich eingeladen.

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

Verwandt

Mehr

BamsmenWenn die 18-Stunden-Linie mit der 3-Stunden-K-Linie zusammengesetzt wird, dann ist das ein Problem.

BamsmenDie Logik in getDHM scheint ein wenig gestört zu sein, die Gesamtfehlermeldung: Ziel- und Basis-Zyklen passen nicht zusammen!

Er ist ein guter Mann.Hallo, warum haben Sie nicht die integrierte Linie in der API?

JiaozhengHallo, kann ich das lösen? Meine Strategie ist nicht mehr zurückzuverfolgen.

JiaozhengWarum wählt man bei der OKEX-Daten-Rückgabe 1 Minute für die K-Reihen-Zyklen, aber es gibt keine Fehlermeldung für das Ziel?

Super 888Der Code ist eine 4-stündige K-Linie, die mit 30 Minuten normal (die K-Linie ist mit 4 kleinen Zeitabschnitten) und mit 5 Minuten abnormal (sie wird nach 12.00 Uhr zu einer 1-stündigen K-Linie) wiederholt.

Kleine TräumeJa, diese Synthese wurde früher geschrieben, sieh dir das an: https://www.fmz.com/digest-topic/4154.

BamsmenDanke, ich benutze diese Synthese nicht, weil ich keine k-Zeilen-Zyklen benötige, die die Börse anbietet, sondern weil die Strategie sowohl die Stunden- als auch die Tageszeiten-Zyklen gleichzeitig benötigt, so dass, wenn zwei GetRecords-Funktionen aufgerufen werden, die jeweils 3 Stunden- und Tageszeiten erhalten, wird die fmz-Unterseite nicht zwei Netzwerkanfragen senden?

Kleine TräumeJetzt unterstützt die Plattform direkt die benutzerdefinierten K-Line-Zyklen und kann die Funktionen der Plattform direkt verwenden.

Kleine TräumeEinige Börsen unterstützen Kreislinie-Daten, andere nicht. Im Allgemeinen werden einheitliche Zyklen verpackt. Andere Zyklen können mit kleinen Zyklen zusammengefasst werden.

Kleine TräumeIch habe K-Linien mit einem 1-Minuten-Zyklus getestet, und die untere Parameter, die 1000*60*4 bedeutet, dass es 4 Minuten sind, können K-Linien zusammengesetzt werden.

JiaozhengSie können versuchen, die Daten zu überprüfen, die OKEX-Futures auszuwählen und dann die Basis-K-Linie auf 1 Minute zu setzen, und dann auf 4 Minuten, und Sie bekommen einen Fehler wie meinen. 240000 Tonnen Zyklusfenol sind nicht die Basiszyklen, sondern ganze Multiplikatoren von 180000 Tonnen Zyklusfenol, die nicht synthetisiert werden können!

JiaozhengDas ist mein Code while ((true)) { records = Call ((exchange.GetRecords, PERIOD_M1)); //Log (("K-Liniendaten: Länge", records.length, "Daten:", records); records = AssembleRecords ((records, Num_UI_NewCycleForMS); // Der erste Parameter ist die Basis-K-Linie, der zweite Parameter ist die Anzahl der Millisekunden der Periode, die umgewandelt werden soll, 1000 * 60 * 20 oder umgewandelt in 20 Minuten // Log (("K-Liniendaten nach der Umwandlung: Länge", records.length, "Daten:" records); Das ist eine sehr schwierige Sache. - Was ist das? Schlaf ((1000); Wir sind hier. Das ist die Parameter-Einstellung https://dn-filebox.qbox.me/e0f51cd46827d68f42cbeffadba1c7a842fb0fb1.jpg Es ist klar, dass es eine Minute dauert, aber es gibt einen Hinweis, dass die Basis-K-Linien-Zyklen 3 Minuten sind, was vorher nicht der Fall war.

Kleine TräumeDie Parameter, die Sie bei der Rückprüfung eingestellt haben, sehen Sie im Screenshot oder direkt in der Gruppe QQ Kleiner Traum.

Kleine TräumeJetzt ist es aktualisiert, und es wurde ein Prozess gemacht, der die Basiszyklen erfordert, um mit den Zielzyklen übereinzustimmen, z. B. die Zielzyklen sollen 6 Stunden synthetisiert werden, die Basiszyklen sollen 1 Stunde verwendet werden, mit weniger Aufwand, und es müssen viele Talente gesammelt werden.

Kleine TräumeDanke für die Frage, ich überprüfe den Code.