2.7 Uso de los indicadores

El autor:Un sueño pequeño., Creado: 2016-11-10 16:19:36, Actualizado: 2019-08-01 09:25:06

Uso de los indicadores


  • TA - Optimización de las partidas de reescritura de la biblioteca de indicadores de uso común

TA 指标库
MACD       指数平滑异同平均线
KDJ        随机指标
RSI        强弱指标
ATR        平均真实波幅
OBV        能量潮
MA         移动平均线
EMA        指数平均数指标
BOLL       布林带
Alligator  Alligator Indicator
CMF        蔡金货币流量指标
Highest    周期最高价
Lowest     周期最低价

Tomemos el indicador MACD para intentar escribir una prueba, antes de eso vamos a abrir la etiqueta MACD en la documentación de la API y ver la descripción.

img

Si los estudiantes están interesados en DIF, DEA, algoritmos de indicadores, etc. pueden ir a Baidu y buscar el algoritmo MACD, hay muchos recursos y interfaces bien envasadas que podemos usar.

function main(){
    var records = null;
    var macd = null;
    while(true){
        records = _C(exchange.GetRecords);  // 获取K线数据 ,默认为策略界面设置的K线周期, _C 是一个容错的内置函数。
                                            // _C 详见 https://www.fmz.com/bbs-topic/320  问题7。
        macd = TA.MACD(records);   // 不加参数的话,使用的是默认参数  12, 26, 9
        Log("macd[0]", macd[0]);   // DIF
        Log("macd[1]", macd[1]);   // DEA
        Log("macd[2]", macd[2]);   // MACD 
        Log("macd[0]长度", macd[0].length);   // DIF 长度
        Log("macd[1]长度", macd[1].length);   // DEA 长度
        Log("macd[2]长度", macd[2].length);   // MACD 长度
        Log("records 长度:", records.length);  // 显示一下 records 的长度。
        Sleep(1000 * 60 * 5);
    }
}

Los resultados de las pruebas de simulación:

img

Como se puede ver, todos los indicadores calculados al principio son nulos, y los datos posteriores comienzan con un valor específico, debido a que el ciclo de cálculo especificado por los parámetros del indicador no puede calcularse hasta que el volumen de datos (datos de registros) no satisfaga este ciclo. Por lo tanto, antes de usar el indicador, se debe conocer la descripción del indicador y determinar en el programa la longitud de los datos de la línea K que se usan para calcular el indicador. Para evitar que se calcule un valor inválido si la longitud es insuficiente, y el uso de un valor inválido puede causar errores en el programa.

A continuación, vemos el código para mostrar los indicadores calculados en el gráfico usando una interfaz gráfica y compararlos con los gráficos de plataformas reales de los intercambios (opción de plataformas reales OKCoin):

var ChartCfg = {
tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'},
    chart: { zoomType:'x',panning:true },//图表类型  
    title: { text: "K-macd"}, //标题
    rangeSelector: {
            buttons:  [{type: 'hour',count: 1, text: '1h'}, {type: 'hour',count: 3, text: '3h'}, {type: 'hour', count: 8, text: '8h'}, {type: 'all',text: 'All'}],
            selected: 0,
            inputEnabled: false
        },
    subtitle: {text: "测试macd"},//副标题
    xAxis:{type: 'datetime'},
    yAxis: [{
            title: {text: 'K线'},//标题
            style: {color: '#4572A7'},//样式 
            opposite: false  //生成右边Y轴
        },
       {
            title:{text: "macd"},
            opposite: true  //生成右边Y轴  ceshi
       }
    ],
    series: [//系列
        {type:'candlestick',yAxis:0,name:'K',id:'KLine',data:[]},
        {name:"DIF",type:'spline',yAxis:1,data:[]},
        {name:"DEA",type:'spline',yAxis:1,data:[]},
        {name:"MACD量柱",type:'spline',yAxis:1,data:[]},
        ]                  
};
function main(){
    var records = null;
    var macd = null;
    var perRecords = _C(exchange.GetRecords);
    var perRecordTime = perRecords[perRecords.length - 1].Time;
    var chart_obj = Chart(ChartCfg); // 初始化图表
    chart_obj.reset();
    while(true){
        records = _C(exchange.GetRecords);  // 获取K线数据 ,默认为策略界面设置的K线周期, _C 是一个容错的内置函数。
        if(!records && records.length < 26 ){
            continue;
        }
        macd = TA.MACD(records, 12, 26, 9);   // 不加参数的话,使用的是默认参数  12, 26, 9
        if(records[records.length - 1].Time !== perRecordTime){                                    // _C 详见 https://www.fmz.com/bbs-topic/320  问题7。
            //先更新,再添加K线
            chart_obj.add(0, [records[records.length - 2].Time, records[records.length - 2].Open, records[records.length - 2].High, records[records.length - 2].Low, records[records.length - 2].Close], -1);   // 跟新刚完成的bar。
            chart_obj.add(0, [records[records.length - 1].Time, records[records.length - 1].Open, records[records.length - 1].High, records[records.length - 1].Low, records[records.length - 1].Close]);       // 添加新出现的bar
            //先更新,添加指标线
            chart_obj.add(1, [records[records.length - 2].Time, macd[0][records.length - 2]], -1);   // 更新
            chart_obj.add(1, [records[records.length - 1].Time, macd[0][records.length - 1]]);
            
            chart_obj.add(2, [records[records.length - 2].Time, macd[1][records.length - 2]], -1);   // 更新
            chart_obj.add(2, [records[records.length - 1].Time, macd[1][records.length - 1]]);
            
            chart_obj.add(3, [records[records.length - 2].Time, macd[2][records.length - 2]], -1);   // 更新
            chart_obj.add(3, [records[records.length - 1].Time, macd[2][records.length - 1]]);
            
            perRecordTime = records[records.length - 1].Time;
        }else{
            //只更新当前的bar 和 线
            chart_obj.add(0, [records[records.length - 1].Time, records[records.length - 1].Open, records[records.length - 1].High, records[records.length - 1].Low, records[records.length - 1].Close], -1);
            chart_obj.add(1, [records[records.length - 1].Time, macd[0][records.length - 1]], -1);   // 更新
            chart_obj.add(2, [records[records.length - 1].Time, macd[1][records.length - 1]], -1);   // 更新
            chart_obj.add(3, [records[records.length - 1].Time, macd[2][records.length - 1]], -1);   // 更新
        }
        chart_obj.update(ChartCfg);
        Sleep(1000);
    }
}

Los parámetros de ciclo de la línea K en la interfaz del robot están configurados para 1 minuto, por lo que se selecciona un ciclo un poco más pequeño, ya que se necesita un tiempo para ver el efecto.

img img

Como se puede ver en el gráfico Cuantificados por el inventor Operado por un robot El DIF calculado es de aproximadamente 2.729 y el DEA es de aproximadamente 2.646 Pilas de cantidad MACD de aproximadamente 0.0831 Los gráficos de la cartera de los intercambios reales de OKCoin muestran el DIF de 2.73 y el DEA de 2.65 en el pilar de MACD de 0.17 Como se puede ver, la diferencia entre los dos primeros DIF, DEA y OKCoin es muy pequeña, OKCoin ha hecho cuatro y cinco, y el MACD es el doble, porque OKCoin se calcula así: (DIF - DEA) * 2, que normalmente es DIF - DEA = 2.729 - 2.646 = 0.083, si se multiplica de nuevo por 2 es 0.166 es aproximadamente igual a 0.17.

El uso de otros indicadores es básicamente similar.

  • - ¿ Qué quieres decir?http://ta-lib.org/

    Además de los indicadores que se utilizan habitualmente en la biblioteca TA, hay muchos otros indicadores en la biblioteca talib. Por ejemplo, intentamos usar el indicador talib.STOCHRSI y veamos la descripción de la documentación de la API:
STOCHRSI	Stochastic Relative Strength Index
STOCHRSI(Records[Close],Time Period = 14,Fast-K Period = 5,Fast-D Period = 3,Fast-D MA = 0) = [Array(outFastK),Array(outFastD)]

Como se puede ver, la configuración de parámetros es talib.STOCHRSI ((records, 14, 14, 3, 3); básicamente es un código similar al MACD superior, con algunos cambios, corra y vea.

var ChartCfg = {
tooltip: {xDateFormat: '%Y-%m-%d %H:%M:%S, %A'},
    chart: { zoomType:'x',panning:true },//图表类型  
    title: { text: "stochrsi"}, //标题
    rangeSelector: {
            buttons:  [{type: 'hour',count: 1, text: '1h'}, {type: 'hour',count: 3, text: '3h'}, {type: 'hour', count: 8, text: '8h'}, {type: 'all',text: 'All'}],
            selected: 0,
            inputEnabled: false
        },
    subtitle: {text: "测试stochrsi"},//副标题
    xAxis:{type: 'datetime'},
    yAxis: [{
            title: {text: 'K线'},//标题
            style: {color: '#4572A7'},//样式 
            opposite: false  //生成右边Y轴
        },
       {
            title:{text: "K-D"},
            opposite: true  //生成右边Y轴  ceshi
       }
    ],
    series: [//系列
        {type:'candlestick',yAxis:0,name:'K',id:'KLine',data:[]},
        {name:"K",type:'line',yAxis:1,data:[]},
        {name:"D",type:'line',yAxis:1,data:[]},
        ]                  
};
function main(){
    var records = null;
    //var macd = null;
    var stochrsi = null;
    var perRecords = _C(exchange.GetRecords);
    var perRecordTime = perRecords[perRecords.length - 1].Time;
    var chart_obj = Chart(ChartCfg); // 初始化图表
    chart_obj.reset();
    while(true){
        records = _C(exchange.GetRecords);  // 获取K线数据 ,默认为策略界面设置的K线周期, _C 是一个容错的内置函数。
        if(!records && records.length < 26 ){
            continue;
        }
        //macd = TA.MACD(records, 12, 26, 9);   // 不加参数的话,使用的是默认参数  12, 26, 9
        stochrsi = talib.STOCHRSI(records, 14, 5, 3, 0);
        if(records[records.length - 1].Time !== perRecordTime){                                    // _C 详见 https://www.fmz.com/bbs-topic/320  问题7。
            //添加K线
            chart_obj.add(0, [records[records.length - 2].Time, records[records.length - 2].Open, records[records.length - 2].High, records[records.length - 2].Low, records[records.length - 2].Close], -1);   // 跟新刚完成的bar。
            chart_obj.add(0, [records[records.length - 1].Time, records[records.length - 1].Open, records[records.length - 1].High, records[records.length - 1].Low, records[records.length - 1].Close]);       // 添加新出现的bar
            //添加指标线
            chart_obj.add(1, [records[records.length - 2].Time, stochrsi[0][records.length - 2]], -1);   // 更新
            chart_obj.add(1, [records[records.length - 1].Time, stochrsi[0][records.length - 1]]);
            
            chart_obj.add(2, [records[records.length - 2].Time, stochrsi[1][records.length - 2]], -1);   // 更新
            chart_obj.add(2, [records[records.length - 1].Time, stochrsi[1][records.length - 1]]);
            
            perRecordTime = records[records.length - 1].Time;
        }else{
            //只更新当前的bar 和 线
            chart_obj.add(0, [records[records.length - 1].Time, records[records.length - 1].Open, records[records.length - 1].High, records[records.length - 1].Low, records[records.length - 1].Close], -1);
            chart_obj.add(1, [records[records.length - 1].Time, stochrsi[0][records.length - 1]], -1);   // 更新
            chart_obj.add(2, [records[records.length - 1].Time, stochrsi[1][records.length - 1]], -1);   // 更新
        }
        chart_obj.update(ChartCfg);
        LogStatus("倒数第一组数据:", stochrsi[0][stochrsi[0].length - 1], stochrsi[1][stochrsi[1].length - 1], "    倒数第二组数据:", stochrsi[0][stochrsi[0].length - 2], stochrsi[1][stochrsi[1].length - 2]);
        Sleep(1000);
    }
}

En un artículo limitado, no mostré una captura de pantalla, pero hay diferencias con los valores oficiales de OKCoin, y BOSS dice que el algoritmo de implementación de talib puede ser diferente al de OKCoin.Comprensión del indicador STOCHRSIComo todos pueden ver cómo se escriben los indicadores, este que escribí no está optimizado, es de baja eficiencia, funciona muy lento, así que aprenda.


Más.

Hokshelato tambiénUsted dice que la última K-línea necesita ser actualizada y añadida primero, porque la última K-línea está siempre cambiando, y la primera K-línea sólo es definida cuando se genera una nueva K-línea. No entiendo muy bien, ¿no es cierto que los datos de la línea K obtenidos a través de `GetRecords (() `? `records [length -1] ` representan los datos de la línea K con el tiempo actual, que se pueden dibujar directamente en el gráfico, y luego se pueden añadir nuevos datos de la línea K con el tiempo y el último elemento del gráfico, ¿no?

Shandyanliyu¿Hay alguna explicación más detallada sobre TA.ATR ((records, 14)), que no encuentro en la documentación de la API de BotVS, ni en los videos ni en el manual de uso completo. Cuando invito TA.ATR ((records, 14) ((parámetros son k líneas de 30 minutos), devuelvo un conjunto de 177 de longitud. ¿Qué significa este conjunto?

¿ Qué haces?La versión de python En la actualidad, la mayoría de los archivos están en manos de personas que no son miembros de la comunidad.

¿ Qué haces?versión de python Def main (): Mientras que es verdad: records = _C ((exchange.GetRecords); # Obtiene datos de línea K, asumiendo por defecto el ciclo de línea K establecido por la interfaz de la política, _C es una función interna tolerante a errores. macd = TA.MACD ((records); # Si no se agregan parámetros, se utilizan los parámetros por defecto 12, 26, 9 Log (("macd[0]", macd[0]); # DIF Log (("macd[1]", macd[1]); # DEA Log (("macd[2]", macd[2]); # MACD Log (("macd[0] longitud", len ((macd[0])); # DIF longitud Log (("macd[1] longitud", len ((macd[1])); # DEA longitud Log (("macd[2] longitud", len ((macd[2])); # longitud del MACD Log (("records Length:", len ((records)); # muestra la longitud de los registros. Sleep ((1000 * 60 * 5);

Un sueño pequeño.La barra de tiempo de la línea K es la hora de inicio de esta barra, no en tiempo real, la hora de inicio de la barra no cambia.

Hokshelato tambiénBueno, lo que yo entendía antes era que el error estaba en el cronómetro de la línea K. Después de desactivarlo, descubrí que el mecanismo de BotVS es el siguiente: Si quiero obtener datos de línea K para el 1 de marzo, llamar a GetRecords (D1) devolverá muchos registros, pero todos tienen el mismo horario, es decir, 2018-03-01 00:00:00. Es decir, incluso si llamo GetRecords (D1) a las 10 horas del 1 de marzo, el horario de la línea K obtenido sigue siendo 2018-03-01 **00**:00:00. Así que la última línea que usted dice es incierta hasta que haya un nuevo horario, es decir, 2018-03-**02** 00:00:00, el día 1 de marzo es incierto. Lo que yo había entendido mal era que pensé que las horas de regreso después de las llamadas de las 1, 2 y 3 de marzo eran diferentes, es decir, 2018-03-01 **01**:00:00, 2018-03-01 **02**:00:00, 2018-03-01 **03**:00:00.

Un sueño pequeño.Los datos de la línea de K obtenidos por GetRecords exceptuando la primera línea de descenso, el resto es definido (porque el ciclo ha terminado), la primera línea de descenso es incierta porque el ciclo no ha terminado y Close está siempre cambiando. Por ejemplo, la línea de K del día, el pilar de K del día actual, no ha terminado hoy, nadie sabe cuál será el precio final del día.

Un sueño pequeño.No es muy amable.

Shandyanliyu¡Claro, muchas gracias!

Un sueño pequeño.Sí, corresponde a la primera línea de K que tiene un factor negativo Bar.

ShandyanliyuBien, muchas gracias por su respuesta. Por último, confirme que var a = TA.ATR ((records, 14), a[a.length-1] es el ATR de los últimos datos de la línea k, ¿verdad?

Un sueño pequeño.Sí. Específicamente, la cantidad de retorno se ve en el intercambio, no se puede especificar. Por lo tanto, los intercambios generalmente ofrecen datos limitados.

ShandyanliyuEsto es lo que yo entiendo, TA.ATR (() es una operación matemática para los registros que se transmiten. No lo expresé antes, lo que quiero preguntar es si la longitud de retorno es determinada por el intercambio cuando se obtienen datos de k líneas con la función exchange.GetRecords (()).

Un sueño pequeño.Esta función de indicador devuelve la cantidad de datos que corresponde a los datos de la línea K, es decir, los registros, cuál es la longitud de la matriz de registros que ingresas, cuál es la longitud calculada.

ShandyanliyuLo siento, todavía no estoy muy claro, quiero decir, si se llama a esta función, ¿la longitud de los datos de retorno es la dada por el intercambio?

Un sueño pequeño.Es la longitud de la línea K.

ShandyanliyuGracias por la respuesta, esto está claro, pero también quiero preguntar, ¿qué determina la longitud de este 117?

Un sueño pequeño.Por ejemplo, los registros transmitidos son las líneas K diarias, y el ATR calculado es un conjunto de números, cuyo primer elemento negativo es el indicador ATR del día (la fecha de la última línea de K diarias). Por lo tanto, clasifique las líneas K de 30 minutos y K de 15 minutos.

Un sueño pequeño.¿Por qué no levanta un castaño? Si ahora los datos de la línea K son sólo 10 Bar, y pido MA ((15) es decir, una línea media de 15 ciclos, entonces definitivamente no se puede obtener, porque sólo hay 10 ciclos, no se puede calcular el promedio de 15 ciclos.

¿ Qué haces?Además, he probado con ticks de disco real, y no he devuelto datos.

¿ Qué haces?¿Por qué los datos anteriores no cumplen con los requisitos del ciclo?

Un sueño pequeño.Este ejemplo es bastante bueno, pero en el uso práctico, los últimos datos de indicadores están en el último elemento de la matriz, es decir, el elemento de índice -1. En la parte posterior hay datos útiles, como: https://dn-filebox.qbox.me/b7837ea30e5d8396ffa91c48204f2fbc9a7f4504.png