Ejemplo de estrategia
// 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); } }
los guardias de seguridadSi la síntesis de la línea de 18 horas con la línea de 3 horas k no es un problema, la síntesis de la línea de día es un error.
los guardias de seguridad¡La escritura lógica de getDHM parece tener un poco de problemas, un total de errores, el ciclo objetivo no coincide con el ciclo base!
- ¿Qué quieres decir?Hola, ¿por qué no hay un círculo integrado en el API?
- ¿ Qué es eso?Hola, ¿puedes resolver mi estrategia ya que esto ya no se puede volver a probar?
- ¿ Qué es eso?¿Por qué el ciclo de la línea K se elige 1 minuto cuando se vuelve a analizar los datos de OKEX, pero no devuelve el objetivo? el ciclo de 240000 toneladas no es el ciclo de base. el ciclo de 180000 toneladas es un múltiplo entero, no se puede sintetizar.
super888En el código hay una línea K de 4 horas, que se repite normal con 30 minutos (la línea K del gráfico es de 4 intervalos de tiempo), y una línea K anormal con 5 minutos (después de 12 horas de repetición se convierte en una línea K de 1 hora)
Los inventores cuantifican - sueños pequeñosSí, este código sintético fue escrito mucho antes, puedes leer esto: https://www.fmz.com/digest-topic/4154.
los guardias de seguridadGracias, uso esta función de síntesis no porque necesite usar un ciclo de k líneas que no ofrece el intercambio, sino porque la política requiere usar un ciclo de horas y un ciclo de días al mismo tiempo, así que si se llama dos veces a la función GetRecords y se obtiene una línea de 3 horas y una línea de día respectivamente, ¿el fondo de fmz enviará dos solicitudes de red?
Los inventores cuantifican - sueños pequeñosAhora, la plataforma soporta directamente el ciclo de línea K personalizado, lo que permite usar directamente las funciones de la plataforma.
Los inventores cuantifican - sueños pequeñosAlgunas bolsas de intercambio soportan datos de circunferencia, algunas no, generalmente se envuelven en ciclos unificados. Otros ciclos se pueden sintetizar en ciclos pequeños.
Los inventores cuantifican - sueños pequeñosHe probado la función de K-line para establecer ciclos de 1 minuto, y el parámetro inferior para establecer 1000*60*4 es 4 minutos, es posible sintetizar K-lines.
- ¿ Qué es eso?Puedes intentarlo tú mismo, elige los futuros OKEX, y si la línea K básica es de 1 minuto y se suma a 4 minutos, entonces se produce un error como el mío. El ciclo de potasio 240000 toneladas no es el ciclo base. ¡El ciclo de potasio 180000 toneladas es un múltiplo entero, no se puede sintetizar!
- ¿ Qué es eso?Este es mi código while (true) { Los registros = Call (exchange.GetRecords, PERIOD_M1); y //Log (("Datos de línea K primarios: longitud", "Datos", "Datos", "Datos", "Datos")); records = AssembleRecords ((records, Num_UI_NewCycleForMS); // El primer parámetro es la línea base K, el segundo parámetro es el milisegundo de ciclo a convertir, 1000 * 60 * 20 es la conversión a 20 minutos // Log (("convertido después de K línea de datos: longitud", records.length, "datos:", records); Los registros de Bitcoin están en línea con los registros de Bitcoin. // lanzar "stop"; // ceshi Sleep ((1000)); ¿Por qué no? Este es el parámetro de configuración https://dn-filebox.qbox.me/e0f51cd46827d68f42cbeffadba1c7a842fb0fb1.jpg Es claro que se establece en un minuto, pero sugiere que el ciclo de la línea K básica es de 3 minutos, lo que no ha sucedido antes.
Los inventores cuantifican - sueños pequeñosSi usted está en la lista de opciones para la revisión de los parámetros, vea la imagen de abajo, o directamente en el grupo QQ.
Los inventores cuantifican - sueños pequeñosAhora se ha actualizado y se ha hecho un tratamiento que requiere ciclos básicos para que coincidan con los ciclos objetivos, por ejemplo, los ciclos objetivos deben ser de 6 horas, los ciclos básicos deben usarse por 1 hora, usar menos molestias, y recolectar muchos talentos. Puedes probar, o si hay algún problema con el uso de BUG, sugiero que puedas dejarme un mensaje, también puedes QQ me.
Los inventores cuantifican - sueños pequeñosGracias por la pregunta, revisé el código.