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.
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:
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.
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.
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.
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);
Inventor quantificado - sonho pequenoA 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.
Inventor quantificado - sonho pequenoGetRecords (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.
Inventor quantificado - sonho pequenoNão é educado.
ShandianliyuPercebido, muito obrigado!
Inventor quantificado - sonho pequenoSim 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?
Inventor quantificado - sonho pequenoSim, 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.
Inventor quantificado - sonho pequenoEsta 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?
Inventor quantificado - sonho pequenoE 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?
Inventor quantificado - sonho pequenoPor 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.
Inventor quantificado - sonho pequenoLevante 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?
Inventor quantificado - sonho pequenoEste 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