리소스 로딩... 로딩...

임의의 K선 주기를 변환합니다

저자:발명가들의 수량화 - 작은 꿈, 2017-02-16 18:35:13
태그:Extent-API

예제 전략

  • 기본 K선을 임의의 K선 주기로 변환합니다.
  • 일시적으로 지원되지 않습니다 테스트 버전, 버그, 문제 등에 대한 의견은 환영합니다.

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

관련

더 많은

만약 3시간 k선을 합쳐서 18시간 라인을 합쳐서 문제가 없다면, 일선을 합쳐서 오류가 발생합니다.

getDHM의 논리 작성에는 약간의 문제가 있고 전체 오류가 있습니다. 목표 주기는 기본 주기와 일치하지 않습니다!

qunxiang_wang안녕하세요, 왜 api에 둥지를 통합하지 않는거죠?

시아오키아올루안녕하세요, 해결해 줄 수 있나요?

시아오키아올루왜 OKEX 데이터 재검토를 할 때 K 라인 주기가 1 분을 선택하지만 목표값을 반환하지 않는가? 주기는 240000 톤이 아닙니다. 기본 주기는 180000 톤의 의 정수 배수가 아닙니다. 합성할 수 없습니다.

슈퍼888코드에는 4시간 K줄이 있고, 30분 동안 정상으로 반복된다 (그라프의 K줄은 4분의 시간 간격이다), 5분 동안 비정상적으로 반복된다 (반복시간이 12시 이후 1시간 K줄이 된다)

발명가들의 수량화 - 작은 꿈네, 이 합성 코드는 좀 더 오래 전에 쓰여졌는데, 이걸 보세요: https://www.fmz.com/digest-topic/4154

감사합니다, 저는 이 합성 함수를 사용해서 거래소가 제공하지 않는 k 라인 주기를 사용해야 하기 때문이 아니라, 이 정책은 시간선과 일선 주기를 동시에 사용해야 하기 때문에, 두 번 GetRecords 함수를 호출하면 각각 3 시간선과 일선을 얻을 수 있고, fmz 하층은 두 번의 네트워크 요청을 보내지 않을까요?

발명가들의 수량화 - 작은 꿈이제 플랫폼은 직접 사용자 정의 K 라인 사이클을 지원하여 플랫폼 기능을 직접 사용할 수 있습니다.

발명가들의 수량화 - 작은 꿈일부 거래소에서는 회전선 데이터를 지원하고, 일부는 그렇지 않으며, 일반적으로 통일 주기에 포장을 하고 있다. 다른 주기는 소주기로 합성할 수 있다.

발명가들의 수량화 - 작은 꿈K줄을 1분 주기로 설정하는 것을 테스트했습니다. 아래쪽의 매개변수는 1000*60*4를 설정하면 4분이라는 것을 의미합니다.

시아오키아올루OKEX를 선택하고 기본 K 라인을 1분으로 설정하면 4분으로 더하면 이런 오류가 발생합니다. 주파수 240000톤은 기본 주파수 180000톤의 정수 배가 아닙니다. 합성할 수 없습니다.

시아오키아올루이건 제 while (true) 코드입니다 records = Call ((exchange.GetRecords,PERIOD_M1)); //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); ♪ ♪ 이 것은 파리그램 설정입니다 https://dn-filebox.qbox.me/e0f51cd46827d68f42cbeffadba1c7a842fb0fb1.jpg 1분으로 정해져 있지만 기본 K선 주기가 3분이라는 것을 암시합니다.

발명가들의 수량화 - 작은 꿈당신이 재검토할 때 설정한 매개 변수 스크린샷을 보거나 직접 그룹에 QQ 작은 꿈.

발명가들의 수량화 - 작은 꿈이제 업데이트를 통해 기본 주기가 목표 주기와 일치하도록 처리하도록 요구합니다. 예를 들어 목표 주기는 6시간을 합쳐야하며 기본 주기는 1시간을 사용해야하며 더 적은 번거로움을 사용해야하며 많은 재능을 수집해야 합니다. 테스트 할 수 있습니다. 또는 사용에 문제가있는 버그가 있습니다.

발명가들의 수량화 - 작은 꿈질문 주셔서 감사합니다. 저는 코드를 확인했습니다.