2.7 Utilização de indicadores

Autora:Sonhos pequenos, Criado: 2016-11-10 16:19:36, Atualizado: 2019-08-01 09:25:06

Utilização de indicadores


  • TA - Optimizar a reescrever parte da biblioteca de funções de indicadores comuns

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

Tente escrever um teste com o indicador MACD, antes de abrirmos o rótulo MACD na documentação da API e vermos a descrição.

img

Se os alunos estão interessados em DIF, DEA, algoritmos de indicadores, etc. podem pesquisar o MACD em Baidu, há muitos recursos, interface bem embalada e temos o código de teste:

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

Os resultados dos testes de disco:

img

Como pode ser visto, todos os indicadores calculados são nulos quando começam, e os dados posteriores começam com valores específicos, porque o ciclo de cálculo especificado pelos parâmetros do indicador não pode ser calculado até que o volume de dados (records de dados) não atenda a esse ciclo. Portanto, antes de usar um indicador, é importante entender a descrição do indicador e determinar o comprimento dos dados da linha K para o cálculo do indicador no programa. Para não calcular um valor inválido se o comprimento for insuficiente e usar um valor inválido pode causar erros no programa.

Abaixo, vemos o código usando a interface gráfica para mostrar os indicadores calculados no gráfico e compará-los com os gráficos em disco real das bolsas de câmbio.

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

O parâmetro do ciclo da linha K na interface do robô é definido como 1 minuto, e como é preciso um tempo para ver o efeito, selecione um ciclo um pouco menor.

img img

Como pode ser visto no gráfico Quantificação do inventor Operação robótica O DIF calculado é de cerca de 2.729 e a DEA é de cerca de 2.646 colunas de quantidade do MACD são de cerca de 0.0831 O gráfico de comportamento da troca real OKCoin mostra o DIF de 2.73 e o DEA de 2.65 e a coluna de quantidade MACD de 0.17 Como pode ver, a diferença entre os dois primeiros DIF, DEA e OKCoin é pequena, OKCoin fez quatro e cinco e o MACD é quase o dobro, porque OKCoin é calculado assim: (DIF - DEA) * 2, geralmente DIF - DEA = 2.729 - 2.646 = 0.083, se multiplicado novamente por 2 é 0.166 é aproximadamente igual a 0.17.

O uso de outros indicadores é basicamente semelhante.

  • Talib -http://ta-lib.org/

    Além dos indicadores usados na biblioteca TA, há muitos outros indicadores na biblioteca talib. Por exemplo, vamos tentar usar o indicador talib.STOCHRSI, e veja a descrição do documento da 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 você pode ver, a configuração do parâmetro é talib.STOCHRSI ((records, 14, 14, 3, 3); basicamente é um código semelhante ao MACD superior, com algumas alterações, corra e veja.

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

A BOSS diz que o algoritmo de implementação do talib pode ser diferente do do OKCoin. Pesquisei na internet e encontrei apenas um pouco de informação, então tenho outra postagem:Compreensão do indicador STOCHRSIComo vocês podem ver, o que eu escrevi não é otimizado, é muito baixo, funciona muito devagar, então é melhor aprender.


Mais.

HokshelatoVocê diz que a última linha K precisa ser atualizada e adicionada primeiro, porque a última linha K está sempre em mudança e só será definida quando uma nova linha K for gerada. Eu não entendo muito bem, os dados da linha K obtidos através de `GetRecords (), não são definitivos? `records [length -1] ` representam os dados da linha K do cronograma atual, que podem ser pintados diretamente no gráfico, e depois, com os dados da linha K do cronograma novo, adicionados ao último elemento do gráfico, certo?

ShandianliyuPor favor, há alguma explicação mais detalhada sobre TA.ATR ((records, 14)), que eu não encontrei na documentação da API do BotVS, nem nos vídeos, nem no manual de uso completo. Quando eu invoco TA.ATR ((records, 14) ((parâmetros são k linhas de 30 minutos), retorna um conjunto de 177 de comprimento. Por favor, o que significa este conjunto?

FangBeiA versão Python https://dn-filebox.qbox.me/b5d2b0ecc1e196a6bfc68eb45cd818c50d279915.png https://dn-filebox.qbox.me/157db5e2659fd13bcf552cd82fe456ba469939f8.png

FangBeiversão python def main (: enquanto verdadeiro: records = _C ((exchange.GetRecords); # obtém dados de linha K, assumindo por padrão o ciclo de linha K definido pela interface da política, _C é uma função inbuilt tolerante a erros. macd = TA.MACD ((records); # Para não adicionar parâmetros, usamos os parâmetros padrão 12, 26, 9 Log (("macd[0]", macd[0]); # DIF Log (("macd[1]", macd[1]); # DEA Log (("macd[2]", macd[2]); # MACD Log (("macd[0] comprimento", len ((macd[0])); # DIF comprimento Log (("macd[1] longo", len ((macd[1])); # DEA longo Log (("macd[2] comprimento", len ((macd[2])); # MACD comprimento Log (("records Duração:", len ((records)); # mostre o comprimento dos records. Sleep ((1000 * 60 * 5);

Sonhos pequenosA barra de tempo da linha K Bar é a hora de início da barra, não o tempo real, e a hora de início da barra não muda.

HokshelatoO que eu percebi antes era que o erro estava no cronograma da linha K. Depois de fazer o debugging, descobri que o mecanismo do BotVS era assim: Se eu quiser obter dados da linha K para o dia 1 de março, chamar GetRecords ((D1) ∞ retornará muitos registros, mas todos têm o mesmo cronograma, que é `2018-03-01 00:00:00 `. Ou seja, mesmo que eu tenha chamado GetRecords (D1) às 10h do dia 1o de março, a linha de tempo obtida ainda é 2018-03-01 **00**:00:00. Assim, a última linha que você disse que seria incerta até que houvesse uma nova linha de tempo, ou seja, 2018-03-**02** 00:00:00, então o dia 1o de março não seria determinado. O erro que eu percebi antes foi que eu pensei que eu voltava no dia 1o de março, às 1h, 2h e 3h, em um horário diferente, ou seja, 2018-03-01 **01**:00:00, 2018-03-01 **02**:00:00, 2018-03-01 **03**:00:00.

Sonhos pequenosGetRecords (http://www.getrecords.com/) obtém dados da linha K. Além da primeira linha do decréscimo, o restante é definido (como o ciclo terminou), a primeira linha do decréscimo é incerta porque o ciclo não terminou, e o Close está sempre em movimento. Por exemplo, a linha K do dia, a coluna K do dia atual, não terminou hoje, e ninguém sabe qual será o preço final do dia.

Sonhos pequenosNão é educado.

ShandianliyuPercebido, muito obrigado!

Sonhos pequenosSim Correspondência Negativa da primeira linha K Bar.

ShandianliyuMuito bem, muito obrigado pela sua resposta. Finalmente, confirme que var a = TA.ATR ((records, 14), a[a.length-1] é o ATR dos dados da linha k mais recente, certo?

Sonhos pequenosSim, especificamente, o quanto é devolvido é de acordo com a bolsa, não pode ser especificado. Portanto, as bolsas geralmente oferecem dados limitados.

ShandianliyuO que eu entendo é que o TA.ATR ((() é basicamente uma operação matemática feita com os registros que são transmitidos. Eu não disse isso antes, mas eu queria perguntar se o comprimento de retorno é determinado pela troca quando a função exchange.GetRecords ((() é usada para obter dados da linha k.

Sonhos pequenosEsta função de indicador retorna o quanto de dados é correspondente aos dados da linha K, ou seja, os registros, o que é o comprimento da matriz de registros que você está inserindo, o que é o comprimento calculado.

ShandianliyuDesculpe, eu ainda não entendi bem, quero dizer, se a função for chamada, o comprimento dos dados de retorno será o dado pela bolsa?

Sonhos pequenosE isso é determinado pelo comprimento da linha K ^^

ShandianliyuObrigado pela sua resposta, está claro, mas gostaria de perguntar, o que determina a extensão do número 117?

Sonhos pequenosPor exemplo, os registros transmitidos são linhas K diárias, e o ATR calculado é um conjunto de números, cujo primeiro elemento negativo é o indicador ATR do dia (data da última linha K diária). Assim, classifique linhas K de 30 minutos, linhas K de 15 minutos.

Sonhos pequenosLevante um castanho. Se agora os dados da linha K são apenas 10 Bar, eu peço MA ((15) ou linha média de 15 ciclos, então certamente não é possível, porque apenas 10 ciclos, não é possível calcular a média de 15 ciclos.

FangBeiAlém disso, eu fiz um teste de tick real e não retornei nenhum dado.

FangBeiPor que os dados anteriores não atendem aos requisitos do ciclo?

Sonhos pequenosEste exemplo é muito bom, mas na prática, os dados de indicador mais recentes estão no final da matriz, ou seja, o elemento com índice -1. A partir de agora, o número de pessoas que estão usando a tecnologia está aumentando, e o número de pessoas que estão usando a tecnologia está aumentando. https://dn-filebox.qbox.me/b7837ea30e5d8396ffa91c48204f2fbc9a7f4504.png