Преобразование любых циклов 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);
    }
}

Связанные

Больше

БэмсменыЕсли вы соедините 18-часовую линию с 3-часовой к-линией, это не имеет значения, но если вы соедините 18-часовую линию с 3-часовой к-линией, это будет иметь значение.

БэмсменыВ getDHM есть несколько проблем с логикой, и все ошибки возвращаются. Целевые циклы не соответствуют базовым!

qunxiang_wangПривет, почему ты не включил круговую линию в API?

ЦзяочжэньЗдравствуйте, вы можете решить мою стратегию, потому что это уже не может быть отслежено

ЦзяочжэньПочему при повторном проверке данных okx K-линейный цикл выбирает 1 минуту, но возвращает ошибку цели цикл х 240000 тн не является базовым циклом х 180 000 тн, не может быть синтезирована!

супер888В коде есть 4-часовая K-линия, которая проходит нормально через 30 минут (графическая K-линия имеет 4-минутный интервал), а не нормально через 5 минут (проходит 1 час после 12-часового интервала)

Маленькие мечтыДа, этот синтетический код был написан довольно рано, посмотрите это: https://www.fmz.com/digest-topic/4154.

БэмсменыСпасибо, я использовал эту синтетическую функцию не потому, что мне нужно использовать к-линиевые циклы, которые не предоставляются биржами, а потому, что в стратегии требуется использовать одновременно часовые и дневные циклы, так что если дважды вызвать функцию GetRecords, чтобы получить 3-часовые и дневные линии, не будет ли нижний слой fmz отправлять два сетевых запроса?

Маленькие мечтыТеперь платформа прямо поддерживает настройки K-линейных циклов, которые можно использовать непосредственно с помощью платформы.

Маленькие мечтыНекоторые биржи поддерживают данные о круговой линии, некоторые нет, в целом для унифицированных циклов делают упаковку; другие циклы могут быть синтезированы с небольшими циклами.

Маленькие мечтыЯ проверил, что если настроить K-линию на 1-минутный цикл, то в нижнем параметре, если настроить 1000*60*4, то это означает 4 минуты, что можно синтезировать K-линию.

ЦзяочжэньВы можете попробовать это самостоятельно, выберите 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, "data:", records); Зарегистрированы: https://www.plotrecords.com/ // throw "stop"; // ceshi Sleep ((1000); {y:bi} Это параметры настройки https://dn-filebox.qbox.me/e0f51cd46827d68f42cbeffadba1c7a842fb0fb1.jpg Явно установлено на одну минуту, но это указывает, что базовый цикл линии K составляет 3 минуты, чего раньше не было.

Маленькие мечтыПараметры, установленные при рецензировании, см. скриншот или прямо в группе QQ.

Маленькие мечтыТеперь обновлено, что требует обработки базовых циклов, чтобы они соответствовали целевым циклам, например, целевые циклы должны быть синтезированы в течение 6 часов, базовые циклы должны использоваться в течение 1 часа, использовать меньше проблем, а также собирать много талантов.

Маленькие мечтыСпасибо за вопрос, я проверю код.