Les ressources ont été chargées... Je charge...

2.7 Utilisation des indicateurs

Auteur:L'inventeur de la quantification - un petit rêve, Créé: 2016-11-10 16:19:36, mis à jour: 2019-08-01 09:25:06

Utilisation des indicateurs


  • TA - Optimisation de la réécriture de la bibliothèque d'indicateurs couramment utilisée

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

Prenons l'indicateur MACD et essayons d'écrire un test, avant de commencer, nous allons déployer la balise MACD dans la documentation de l'API pour voir la description.

img

Si vous êtes intéressé par les algorithmes DIF, DEA, indicateur, etc., vous pouvez aller sur Baudite pour trouver l'algorithme MACD, il y a beaucoup de ressources, des interfaces bien emballées et nous avons des codes de test:

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

Les résultats des tests sur le disque:

img

Comme vous pouvez le voir, tous les indicateurs calculés sont nuls au début, et les données suivantes commencent à avoir des valeurs spécifiques, ce qui est dû au cycle de calcul spécifié par les paramètres de l'indicateur. Par conséquent, il est important de connaître la description de l'indicateur avant d'utiliser l'indicateur; et de déterminer dans le programme la longueur des données de la ligne K utilisées pour le calcul de l'indicateur.

Ci-dessous, nous utilisons une interface graphique pour afficher les indicateurs calculés sur le graphique et comparer les graphiques en direct des échanges (en choisissant OKCoin en direct).

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

Le paramètre de cycle de ligne K sur l'interface du robot est défini à 1 minute, car il faut courir un certain temps pour voir l'effet.

img img

Comme le montre le graphique, le DIF calculé est d'environ 2.729 et la DEA est d'environ 2.646 et la colonne MACD est d'environ 0.0831 Le graphique de comportement de l'échange réel OKCoin affiche un DIF de 2.73 et un DEA de 2.65 et une colonne MACD de 0.17 Comme vous pouvez le voir, la différence entre les deux premiers DIF et DEA est très faible, OKCoin a fait quatre et cinq, le MACD est presque deux fois plus faible, parce que OKCoin est calculé comme ceci: (DIF - DEA) * 2, qui est généralement DIF - DEA = 2.729 - 2.646 = 0.083, si on le multiplie encore par 2 c'est 0.166 qui est à peu près égal à 0.17.

Les autres indicateurs sont utilisés de manière similaire.

  • - Je ne sais pas.http://ta-lib.org/

    En plus des indicateurs couramment utilisés par TA, il existe de nombreux autres indicateurs dans la bibliothèque talib. Par exemple, nous avons essayé d'utiliser l'indicateur talib.STOCHRSI et nous avons vu la description de la documentation de l'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)]

Comme vous pouvez le voir, le paramètre est talib.STOCHRSI ((records, 14, 14, 3, 3); c'est essentiellement un code similaire au MACD ci-dessus, avec quelques modifications.

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

Je n'ai pas montré de capture d'écran, mais il y a une différence avec les chiffres officiels d'OKCoin, et BOSS dit que l'algorithme d'implémentation de la bibliothèque talib peut être différent de celui d'OKCoin.Comprendre les indicateurs STOCHRSIVous pouvez voir comment les indicateurs sont écrits, je l'ai écrit sans optimisation, faible efficacité, fonctionne très lentement, alors apprenez-le.


Plus de

hokshelatoVous dites que la dernière ligne K a besoin d'être mise à jour et ajoutée en premier, parce que la dernière ligne K est en constante évolution et que la première ligne K n'est définie que lorsque la nouvelle ligne K est générée. Je ne comprends pas très bien, les données de la ligne K obtenues par `GetRecords (() ` ne sont-elles pas exactes? `records [length -1] ` représentent les données de la ligne K sous le chronomètre actuel, et peuvent être directement dessinées dans le graphique, et les données de la ligne K avec le nouveau chronomètre peuvent être ajoutées au dernier élément du graphique, n'est-ce pas?

Je vous en prie.S'il vous plaît, avez-vous des instructions plus détaillées sur TA.ATR ((records, 14)), que je n'ai pas trouvées dans la documentation de l'API de BotVS, les vidéos et le manuel d'utilisation complet.

FangBei est là.La version python Il est également possible de télécharger des fichiers de fichiers de fichiers de fichiers de fichiers de fichiers.

FangBei est là.version python Définition principale: alors que vrai: records = _C ((exchange.GetRecords); # Obtient les données de ligne K, en supposant par défaut que la ligne K est une période de la stratégie de l'interface, _C est une fonction intégrée tolérante des erreurs. macd = TA.MACD ((records); # sans paramètres, les paramètres par défaut sont 12, 26, 9 Log (("macd[0]", macd[0]); # DIF Log (("macd[1]", macd[1]); # DEA Log (("macd[2]", macd[2]); # MACD Log (("macd[0] longueur", len ((macd[0])); # DIF longueur Log (("macd[1] longueur", len ((macd[1])); # DEA longueur Log (("macd[2] longueur", len ((macd[2])); # longueur MACD Log (("records Longueur:", len ((records)); # affiche la longueur des records. Sleep ((1000 * 60 * 5);

L'inventeur de la quantification - un petit rêveLa barre de temps de la ligne KBar est l'heure de début de cette barre, et non pas l'heure réelle, l'heure de début de la barre ne change pas.

hokshelatoBonjour, j'ai compris que c'était une erreur dans la chronologie de la ligne K. Après le débogage, j'ai découvert que le mécanisme de BotVS ressemblait à ceci: Si je veux obtenir les données de la ligne K du 1er mars pour ce jour, appeler GetRecords (D1) renvoie beaucoup d'enregistrements, mais ils ont tous la même date, c'est-à-dire 2018-03-01 00:00:00. C'est-à-dire que même si j'ai appelé GetRecords le 1er mars à 10 heures, le timestamp K obtenu est toujours 2018-03-01 **00**:00:00. Donc, la dernière ligne que vous avez mentionnée est incertaine jusqu'à ce qu'il y ait un nouveau timestamp, c'est-à-dire 2018-03-**02** 00:00:00, alors le 1er mars est un timestamp. Ce que j'ai compris comme une erreur, c'est que j'ai pensé que j'étais revenu à une heure différente après avoir appelé le 1er mars à 1h, 2h et 3h, c'est-à-dire 2018-03-01 **01**:00:00, 2018-03-01 **02**:00:00, 2018-03-01 **03**:00:00.

L'inventeur de la quantification - un petit rêveGetRecords (()) obtient des données sur la ligne K. À l'exception de la première ligne de décompte, le reste est déterminé (parce que le cycle est terminé), la première ligne de décompte est incertaine parce que le cycle n'est pas terminé et que Close est en constante évolution. Par exemple, la ligne K quotidienne, le pilier K quotidien actuel, n'est pas terminé aujourd'hui, et personne ne sait quel sera le prix final de la clôture de la journée.

L'inventeur de la quantification - un petit rêveC'était impoli.

Je vous en prie.C'est clair, merci beaucoup!

L'inventeur de la quantification - un petit rêveOui, correspondant à la première ligne de la série K bar.

Je vous en prie.Bon, merci beaucoup pour votre réponse. Enfin, confirmez que var a = TA.ATR ((records, 14), a[a.length-1] est l'ATR des données de la ligne k la plus récente.

L'inventeur de la quantification - un petit rêveOui, c'est précis. Le montant du rendement dépend de l'échange et ne peut pas être spécifié.

Je vous en prie.Ce que je comprends, c'est que TA.ATR ((() est essentiellement une opération mathématique sur les enregistrements transmis. Je ne l'ai pas expliqué plus tôt, mais je voulais vous demander si la longueur de retour est déterminée par l'échange lors de l'obtention de données de ligne k avec la fonction exchange.GetRecords (()).

L'inventeur de la quantification - un petit rêveCette fonction indique combien de données retourne correspond à la ligne de données K, c'est-à-dire aux records, à la longueur de l'array de records que vous avez entré, et à la longueur de l'array calculé.

Je vous en prie.Je suis désolé, je ne comprends toujours pas, je veux dire, si vous appelez cette fonction, la longueur des données retournées est-elle donnée par l'échange?

L'inventeur de la quantification - un petit rêveC'est déterminé par la longueur de la ligne K ^^

Je vous en prie.Merci pour votre réponse, c'est clair, mais je voudrais aussi savoir ce qui détermine la longueur de ce 117.

L'inventeur de la quantification - un petit rêvePar exemple, les enregistrements transmis sont des lignes de jour K, et l'ATR calculé est un ensemble d'éléments dont le premier élément négatif est l'indicateur ATR du jour (la date de la dernière ligne de jour K). On classe ensuite les lignes K de 30 minutes et les lignes K de 15 minutes.

L'inventeur de la quantification - un petit rêveJe ne peux pas le faire. Si maintenant les données de la ligne K ne sont que de 10 Bar, je demande MA ((15) qui est une ligne moyenne de 15 cycles, alors c'est certainement impossible, car il n'y a que 10 cycles, il est impossible de calculer la moyenne de 15 cycles.

FangBei est là.En plus, j'ai testé avec un tic-tac à disque réel, et je n'ai pas de données.

FangBei est là.Pourquoi les données précédentes ne répondent-elles pas aux exigences cycliques?

L'inventeur de la quantification - un petit rêveL'exemple est plutôt bon, mais dans l'usage pratique, les données d'indicateur les plus récentes se trouvent à la fin de l'arrayé, c'est-à-dire l'élément dont l'index est −1. Les données suivantes sont utiles: Il est également possible de télécharger des fichiers sur le serveur de téléchargement.