예제 전략
// 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); } }
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 라인 사이클을 지원하여 플랫폼 기능을 직접 사용할 수 있습니다.
발명가들의 수량화 - 작은 꿈일부 거래소에서는 회전선 데이터를 지원하고, 일부는 그렇지 않으며, 일반적으로 통일 주기에 포장을 하고 있다. 다른 주기는 소주기로 합성할 수 있다.
발명가들의 수량화 - 작은 꿈K줄을 1분 주기로 설정하는 것을 테스트했습니다. 아래쪽의 매개변수는 1000*60*4를 설정하면 4분이라는 것을 의미합니다.
시아오키아올루OKEX를 선택하고 기본 K 라인을 1분으로 설정하면 4분으로 더하면 이런 오류가 발생합니다.
주파수
시아오키아올루이건 제 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시간을 사용해야하며 더 적은 번거로움을 사용해야하며 많은 재능을 수집해야 합니다. 테스트 할 수 있습니다. 또는 사용에 문제가있는 버그가 있습니다.
발명가들의 수량화 - 작은 꿈질문 주셔서 감사합니다. 저는 코드를 확인했습니다.