Type/to search
8
Follow
1386
Followers
2.7 指標の使用
Tutorials
Created 2016-11-10 16:19:36  Updated 2019-08-01 09:25:06
 22
 6536

指数の使用


  • TA - 常用指数関数庫の一部を最適化して書き換え

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

MACDのテストをMACDで書きます.まずはAPIのドキュメントにMACDのタグを広げて,詳細を説明します.

img

DIF,DEA,指数アルゴリズムなどに興味のある同級生なら百度でMACDアルゴリズムを検索してみてください.たくさんのリソースがあり,パッケージ化されたインターフェースを用意しました.テストコードは以下の通りです.

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

試聴した結果:

img

計算された指標は,すべての値がnullで始まり,その後のデータが特定の値を持つようになったことがわかります.これは,指標パラメータが規定する計算周期が,データ量 (recordsデータ) がこの周期を満たさないまで指標を計算できないからです.
したがって,指標を使用する前に,指標の記述を理解し,指標を計算するために使用されるK線データの長さをプログラムで判断してください.長さが不足した場合は,無効値が計算され,無効値を使用すると,プログラムエラーが発生しないようにしてください.

以下は,グラフインターフェースを使用して計算した指標をグラフに表示し,取引所のリアルタイムグラフと比較します (リアルタイムで 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); } }

ロボットインタフェースのK線周期パラメータは1分と設定されている.効果を見るにはしばらく実行する必要があるため,少し小さい周期を選択する.図のように:

img
img

図から見える Inventor 量化 ロボット動作 計算されたDIFは約2.729で,DEAは約2.646 MACD量柱 約0.0831
実際のOKCoin取引所の動向図は,DIFが2.73で,DEAが2.65で,MACDの量柱は0.17を示しています.
OKCoinはDIFとDEAの差は小さいので OKCoinはMACDの2倍で OKCoinは2倍で OKCoinは2倍で OKCoinは2倍で
(DIF-DEA) * 2は,通常はDIF-DEA=2.729 - 2.646=0.083で,もし2を掛けると,0.166は約0.17に等しくなります.

他の指標の使い方は基本的には同じです.

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

    タリブのデータベースには,TAの標準的な指標以外にも多くの指標があります.
    例えば,talib.STOCHRSIという指標を使ってみよう.

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)]

参数設定は talib.STOCHRSI ((records,14,14,3,3)) となっているのがわかります. 基本的には上側のMACDのようなコードですが,少し変更して,見てみましょう。

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

BOSSは,talibのライブラリがOKCoinのライブラリとは異なる可能性のあるアルゴリズムで実装されていることを指摘しました. ネットで調べてみると,少しだけ情報しか見つかりませんでしたが,別の投稿がありました.
STOCHRSI指標を理解する
この指標は,私が書いたもので,最適化されていないので,効率が悪く,動作が遅いので,勉強してみてください.

Related Recommendations
Comment
All comments (22)

    您说“最后一根 K 线需要先更新再添加,因为最后一根 K 线是一直在变动的,只有当新的 K 线生成以后,前一根 K 线才是确定的。”

    我不是很理解,通过 GetRecords() 获得的 K 线数据难道不是确定的吗?records[length -1] 代表的是当前时间戳下的 K 线数据,直接画到图表中即可,等有了新的时间戳的 K 线数据,再添加到图表的最后一个元素即可,不是吗?望不吝赐教。

    9 years ago

    GetRecords() 获取的 K线数据 除了 倒数第一根 ,其余是确定的(因为周期已经完成),倒数第一根 不确定是因为 周期没有走完,Close 一直在变动。比如 日K 线, 当前的日K 线柱,在今天没有过完的时候, 谁也不知道 今天最终会多少价格 收盘。

    9 years ago

    嗯,我之前理解的误区在于 K 线的时间戳上。调试下来后发现 BotVS 的机制是这样的,以您说的日 K 线为例:

    如果我要获取 3月1日 这一天的 K 线数据,调用 GetRecords(D1) 会返回很多条记录,但它们的时间戳都是一样的,都是2018-03-01 00:00:00。

    也就是说,即使我在 3月1日 10点 调用了 GetRecords(D1),获取到的 K 线时间戳,依然是 2018-03-01 00:00:00。所以才有了您说的最后一根是会不确定的,直到有了新的时间戳,即 2018-03-02 00:00:00,则 3月1日这一天的时间戳便确定了。

    我此前理解的误区在于,我以为我在 3月1日 1点、2点、3点调用后返回的时间是不同的,即 2018-03-01 01:00:00、2018-03-01 02:00:00、2018-03-01 03:00:00。

    9 years ago

    K线Bar 的时间戳是 这个Bar 的起始时间, 并不是 实时 时间, Bar 的起始时间是不会变动的。

    9 years ago

    请问有没有关于 TA.ATR(records, 14) 更详细的说明,我在BotVS的API文档,视频以及完全使用手册中都没有找到。在我调用 TA.ATR(records, 14) 时(参数为30分钟k线),返回的是一个长度为 177 的数组。请问这个数组的含义是什么?

    9 years ago

    举例 传入的records 为 日K线, 计算出的 ATR 就是 一个 数组, 这个数组的 倒数第一个元素 就是 当天的(日K线 最后一根的日期)ATR 指标。 依次类推 30分钟 K线 , 15分钟K线。 您算出的 177 的数组 就是 177 个K线周期 ,对应每个 K线Bar 的 ATR指标。

    9 years ago

    感谢您的回答,这下清楚了,另外想问一下,这个117的长度是由什么决定的?

    9 years ago

    是由 K线长度 决定的 ^^

    9 years ago

    不好意思,我还是不太明白,我的意思是,如果调用这个函数,那么返回数据的长度是交易所给定的吗?我发现不同时刻调用这个函数,即使参数相同,返回数据的长度也可能不同。

    9 years ago

    这个 指标函数 返回多少 数据 是和 K线数据 也就是 records 对应的, 你传入的 records 数组 长度是多少 , 算出来的 长度 就是多少。

    9 years ago

    这个我明白,TA.ATR()实质就是对传入的records进行了一个数学运算。是我之前没有表达清楚,我想问的是用函数exchange.GetRecords() 获取k线数据时,返回的长度是由交易所决定的吗?

    9 years ago

    是的 具体 返回多少是 看交易所 的,并不能 指定。所以 交易所 一般 提供的都是 有限 数据。

    9 years ago

    好的,非常感谢您的回答。最后再确认一下,var a = TA.ATR(records, 14), a[a.length-1] 这个表示的是最近k线数据的ATR吧?

    9 years ago

    是的 对应 倒数第一根 K线 Bar。

    9 years ago

    明白了,非常感谢!

    9 years ago

    python版本

    img img

    9 years ago

    python版本
    def main():
    while true:
    records = _C(exchange.GetRecords); # 获取K线数据 ,默认为策略界面设置的K线周期, _C 是一个容错的内置函数。
    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]长度", len(macd[0])); # DIF 长度
    Log("macd[1]长度", len(macd[1])); # DEA 长度
    Log("macd[2]长度", len(macd[2])); # MACD 长度
    Log("records 长度:", len(records)); # 显示一下 records 的长度。
    Sleep(1000 * 60 * 5);

    9 years ago

    这个例子挺好, 就是在实际使用中 ,最新的指标数据都是在数组 最后的, 就是 索引 -1 的元素。前边不满足周期要求 计算出的数据都是 None,
    后面才有 有效数据,如图:
    img

    9 years ago

    另外,我用实盘级tick回测,没有数据返回

    9 years ago

    前面的数据为什么会不满足周期要求呢?

    9 years ago

    举个栗子~
    如果 现在K线数据只有10个Bar 的时候,我要求 MA(15) 即 15周期均线, 那么 肯定是求不出来的,因为只有10个周期,无法计算15个周期的平均值。

    9 years ago
  • 1
Forums
PINE Language
Get the app
iPhone Download
© 2015 - ∞ INVENTOR PTE LTD (SG)