Sử dụng chỉ số
TA 指标库
MACD 指数平滑异同平均线
KDJ 随机指标
RSI 强弱指标
ATR 平均真实波幅
OBV 能量潮
MA 移动平均线
EMA 指数平均数指标
BOLL 布林带
Alligator Alligator Indicator
CMF 蔡金货币流量指标
Highest 周期最高价
Lowest 周期最低价
Hãy thử viết một bài kiểm tra với MACD, trước khi chúng ta mở các thẻ MACD trên tài liệu API để xem các mô tả cụ thể.
Nếu bạn đang quan tâm đến DIF, DEA, thuật toán chỉ số, bạn có thể tìm kiếm thuật toán MACD tại Baidu, có rất nhiều tài nguyên, giao diện được đóng gói tốt và chúng tôi đã sử dụng.
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);
}
}
Kết quả thử nghiệm của đĩa analog:
Có thể thấy rằng tất cả các chỉ số được tính ra đều là null khi bắt đầu, và dữ liệu sau đó bắt đầu có giá trị cụ thể, bởi vì chu kỳ tính toán được quy định bởi tham số chỉ số, không thể tính chỉ số trước khi số lượng dữ liệu (records dữ liệu) không đáp ứng chu kỳ này.
Vì vậy, trước khi sử dụng chỉ số, hãy hiểu mô tả của chỉ số. Và trong chương trình, hãy đánh giá chiều dài của dữ liệu K-line được sử dụng để tính toán chỉ số. Để tránh tính toán giá trị không hợp lệ trong trường hợp không đủ chiều dài và sử dụng giá trị không hợp lệ sẽ gây ra lỗi chương trình.
Dưới đây là các chỉ số chúng tôi đã tính toán bằng cách sử dụng giao diện biểu đồ để hiển thị trên biểu đồ và so sánh với biểu đồ thực của sàn giao dịch ((thực chọn OKCoin), trước khi xem mã:
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);
}
}
Các tham số chu kỳ K-line trên giao diện robot được thiết lập là 1 phút, vì phải chạy một thời gian để thấy hiệu quả, nên chọn chu kỳ nhỏ hơn một chút.
DIF được tính là khoảng 2.729 , DEA là khoảng 2.646 MACD số cột khoảng 0.0831
Biểu đồ hoạt động của sàn giao dịch OKCoin thực tế cho thấy DIF là 2.73, DEA là 2.65, và cột MACD là 0.17
Bạn có thể thấy rằng DIF và DEA khác nhau rất nhỏ, OKCoin đã làm một vòng tròn, MACD là hai lần, bởi vì OKCoin được tính như sau:
(DIF - DEA) * 2 , thường là DIF - DEA = 2.729 - 2.646 = 0.083, nếu nhân 2 là 0.166 thì khoảng bằng 0.17.
Các chỉ số khác được sử dụng tương tự.
-
talib - http://ta-lib.org/
Ngoài các chỉ số thường được sử dụng trong thư viện TA, có rất nhiều chỉ số khác trong thư viện talib.
Ví dụ, chúng ta có thể sử dụng talib.STOCHRSI, và hãy nhìn vào tài liệu 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)]
Bạn có thể thấy rằng các tham số được thiết lập là talib.STOCHRSI ((records, 14, 14, 3, 3); cơ bản là một mã giống như MACD trên cùng, đã thay đổi một số, hãy chạy để xem.
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 nói rằng thuật toán thực hiện của thư viện talib có thể khác với OKCoin. Tôi đã lướt qua mạng và chỉ tìm thấy một chút thông tin, vì vậy có một bài viết khác:
Hiểu được chỉ số STOCHRSI
Các bạn có thể xem các chỉ số được viết ra như thế nào, cái tôi viết không được tối ưu hóa, hiệu quả thấp, chạy chậm, nên hãy học.
您说“最后一根 K 线需要先更新再添加,因为最后一根 K 线是一直在变动的,只有当新的 K 线生成以后,前一根 K 线才是确定的。”
我不是很理解,通过 GetRecords() 获得的 K 线数据难道不是确定的吗?records[length -1] 代表的是当前时间戳下的 K 线数据,直接画到图表中即可,等有了新的时间戳的 K 线数据,再添加到图表的最后一个元素即可,不是吗?望不吝赐教。
GetRecords() 获取的 K线数据 除了 倒数第一根 ,其余是确定的(因为周期已经完成),倒数第一根 不确定是因为 周期没有走完,Close 一直在变动。比如 日K 线, 当前的日K 线柱,在今天没有过完的时候, 谁也不知道 今天最终会多少价格 收盘。
嗯,我之前理解的误区在于 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。
请问有没有关于 TA.ATR(records, 14) 更详细的说明,我在BotVS的API文档,视频以及完全使用手册中都没有找到。在我调用 TA.ATR(records, 14) 时(参数为30分钟k线),返回的是一个长度为 177 的数组。请问这个数组的含义是什么?
举例 传入的records 为 日K线, 计算出的 ATR 就是 一个 数组, 这个数组的 倒数第一个元素 就是 当天的(日K线 最后一根的日期)ATR 指标。 依次类推 30分钟 K线 , 15分钟K线。 您算出的 177 的数组 就是 177 个K线周期 ,对应每个 K线Bar 的 ATR指标。
不好意思,我还是不太明白,我的意思是,如果调用这个函数,那么返回数据的长度是交易所给定的吗?我发现不同时刻调用这个函数,即使参数相同,返回数据的长度也可能不同。
这个 指标函数 返回多少 数据 是和 K线数据 也就是 records 对应的, 你传入的 records 数组 长度是多少 , 算出来的 长度 就是多少。
这个我明白,TA.ATR()实质就是对传入的records进行了一个数学运算。是我之前没有表达清楚,我想问的是用函数exchange.GetRecords() 获取k线数据时,返回的长度是由交易所决定的吗?
好的,非常感谢您的回答。最后再确认一下,var a = TA.ATR(records, 14), a[a.length-1] 这个表示的是最近k线数据的ATR吧?
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);
- 1







