2.7 Sử dụng các chỉ số

Tác giả:Giấc mơ nhỏ, Tạo: 2016-11-10 16:19:36, Cập nhật: 2019-08-01 09:25:06

Sử dụng các chỉ số


  • TA - Tối ưu hóa phần viết lại của thư viện các chỉ số phổ biến

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 chỉ số MACD, trước khi chúng ta mở thẻ MACD trên tài liệu API để xem mô tả cụ thể.

img

Nếu bạn quan tâm đến DIF, DEA, các thuật toán chỉ số, bạn có thể tìm kiếm trên Baidu về thuật toán MACD, có rất nhiều tài nguyên, các giao diện được đóng gói tốt và chúng tôi đưa ra ngay lập tức.

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 đĩa giả:

img

Như bạn có thể thấy, tất cả các chỉ số được tính toán đề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 các tham số chỉ số, không thể tính toán chỉ số trước khi khối 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ố, bạn nên hiểu mô tả của chỉ số. Và trong chương trình, hãy quyết định chiều dài của dữ liệu đường K được sử dụng để tính chỉ số.

Dưới đây, chúng tôi sẽ sử dụng giao diện biểu đồ để các chỉ số được tính toán được hiển thị trên biểu đồ và so sánh với biểu đồ thực tế của sàn giao dịch (chọn OKCoin thực tế).

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ỳ đường K trên giao diện robot được đặt là 1 phút, vì phải chạy một thời gian để thấy hiệu ứng, nên chọn chu kỳ nhỏ hơn một chút.

img img

DIF được tính toán khoảng 2.729, DEA khoảng 2.646 Cột lượng MACD khoảng 0.0831 Biểu đồ giao dịch thực tế OKCoin cho thấy DIF là 2.73 và DEA là 2.65 Cột MACD là 0.17 Bạn có thể thấy rằng hai DIF, DEA đầu tiên có sự khác biệt rất nhỏ, OKCoin đã làm 4/5 và MACD gần gấp đôi bởi OKCoin tính như sau: (DIF - DEA) * 2, thường là DIF - DEA = 2.729 - 2.646 = 0.083, nếu bạn nhân lại bằng 2 thì 0.166 tương đương khoảng 0.17.

Các phương pháp sử dụng các chỉ số khác cũng tương tự.

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

    Ngoài các chỉ số thường được sử dụng trong TA, còn có nhiều chỉ số khác trong Talib. Ví dụ, chúng ta thử sử dụng chỉ số talib.STOCHRSI và xem mô tả 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)]

Như bạn có thể thấy, cài đặt tham số là talib.STOCHRSI ((records, 14, 14, 3, 3); về cơ bản vẫn là mã tương tự như MACD trên cùng, có một số thay đổi, 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);
    }
}

Tôi không hiển thị hình ảnh, nhưng có sự khác biệt với số liệu chính thức của OKCoin, và BOSS nói rằng các thuật toán thực hiện của Talib có thể khác với OKCoin.STOCHRSI chỉ số hiểuBạn có thể thấy các chỉ số được viết như thế nào, tôi đã viết điều này không được tối ưu hóa, hiệu quả thấp, chạy khá chậm, bạn nên học.


Thêm nữa

hokshelatoBạn nói rằng K cuối cùng cần phải được cập nhật và thêm vào trước vì K cuối cùng luôn thay đổi, và K trước đó chỉ được xác định khi K mới được tạo ra. Tôi không hiểu rõ, dữ liệu đường K được lấy từ `GetRecords (); ` không xác định sao? `records (length -1) ` đại diện cho dữ liệu đường K trong giờ hiện tại, vẽ trực tiếp vào biểu đồ, chờ dữ liệu đường K với giờ mới, và thêm vào phần tử cuối cùng của biểu đồ, phải không?

ShandianliyuXin vui lòng cho tôi biết có thông tin chi tiết hơn về TA.ATR ((records, 14)), mà tôi không thể tìm thấy trong tài liệu, video và hướng dẫn sử dụng đầy đủ của BotVS. Khi tôi gọi TA.ATR ((records, 14) ((chỉ số là 30 phút k), tôi sẽ trả về một chuỗi dài 177. Xin vui lòng cho tôi biết nghĩa của chuỗi này là gì?

FangBeiPhiên bản python https://dn-filebox.qbox.me/b5d2b0ecc1e196a6bfc68eb45cd818c50d279915.png https://dn-filebox.qbox.me/157db5e2659fd13bcf552cd82fe456ba469939f8.png

FangBeiPhiên bản python def main (: while true: records = _C ((exchange.GetRecords); # lấy dữ liệu đường K, mặc định là các chu kỳ đường K được đặt bởi giao diện chính sách, _C là một hàm tích hợp cho phép lỗi. macd = TA.MACD ((records); # Nếu không thêm tham số, sử dụng các tham số mặc định 12, 26, 9 Log (("macd[0]", macd[0]); # DIF Log (("macd[1]", macd[1]); # DEA Log (("macd[2]", macd[2]); # MACD Log (("macd[0] độ dài", len ((macd[0])); # DIF độ dài Log (("macd[1] dài", len ((macd[1])); # DEA dài Log (("macd[2] dài", len ((macd[2])); # MACD dài Log (("records Length:", len ((records)); # hiển thị độ dài của records. Sleep ((1000 * 60 * 5);

Giấc mơ nhỏThời gian bắt đầu của Bar trên đường K là thời gian bắt đầu của Bar, không phải thời gian thực, thời gian bắt đầu của Bar không thay đổi.

hokshelatoVâng, trước đây tôi đã hiểu sai về thời gian của dòng K. Sau khi chỉnh sửa, tôi thấy cơ chế của BotVS là như sau: Nếu tôi muốn lấy dữ liệu đường K của ngày 1 tháng 3, gọi `GetRecords ((D1) ` sẽ trả về nhiều bản ghi, nhưng chúng đều có cùng một thời gian, là `2018-03-01 00:00:00 `. Điều đó có nghĩa là ngay cả khi tôi gọi `GetRecords ((D1) ` vào lúc 10 giờ ngày 1 tháng 3, thì thời gian của K-line vẫn là 2018-03-01 **00**:00:00. Vì vậy, cuối cùng mà bạn nói sẽ không chắc chắn cho đến khi có thời gian mới, đó là 2018-03-**02** 00:00:00, thì thời gian của ngày 1 tháng 3 sẽ không chắc chắn. Tôi đã hiểu sai trước đó là tôi nghĩ rằng tôi đã quay lại sau khi gọi vào lúc 1h, 2h và 3h ngày 1 tháng 3 là một thời gian khác, đó là 2018-03-01 **01**:00:00, 2018-03-01 **02**:00:00, 2018-03-01 **03**:00:00.

Giấc mơ nhỏGetRecords () thu được dữ liệu về đường K ngoại trừ số lần đầu tiên, phần còn lại là xác định (vì chu kỳ đã kết thúc), số lần đầu tiên là không chắc chắn vì chu kỳ chưa kết thúc, Close luôn thay đổi. Ví dụ, đường K ngày, cột đường K ngày hiện tại, khi ngày không kết thúc, không ai biết giá cuối cùng của ngày hôm nay sẽ đóng cửa.

Giấc mơ nhỏKhông lịch sự ^^

ShandianliyuĐược rồi, cảm ơn rất nhiều!

Giấc mơ nhỏĐúng vậy, tương ứng với số phần tử đầu tiên của dòng K Bar.

ShandianliyuVâng, cảm ơn bạn rất nhiều vì câu trả lời của bạn. Cuối cùng, hãy xác nhận, var a = TA.ATR ((records, 14), a[a.length-1]

Giấc mơ nhỏVâng, cụ thể, số tiền được trả lại theo sàn giao dịch, không thể chỉ định. Vì vậy, sàn giao dịch thường cung cấp dữ liệu hạn chế.

ShandianliyuTôi hiểu rằng, TA.ATR ((() thực sự là một phép tính toán toán học đối với các bản ghi được truyền. Tôi đã không thể hiện rõ trước đây, tôi muốn hỏi là khi lấy dữ liệu k-thread bằng hàm exchange.GetRecords (()) thì chiều dài trả lại có được quyết định bởi sàn giao dịch không?

Giấc mơ nhỏChỉ số này sẽ trả về số lượng dữ liệu tương ứng với dữ liệu K, nghĩa là records, và bạn sẽ nhập một mảng records có độ dài bao nhiêu, và tính ra độ dài bao nhiêu.

ShandianliyuTôi xin lỗi, tôi vẫn chưa hiểu, ý tôi là, nếu gọi hàm này, thì liệu chiều dài của dữ liệu được trả về là được trao đổi không? Tôi thấy rằng khi gọi hàm này vào những thời điểm khác nhau, thậm chí nếu các tham số giống nhau, chiều dài của dữ liệu sẽ khác nhau.

Giấc mơ nhỏNó được xác định bởi chiều dài của K.

ShandianliyuCảm ơn câu trả lời của bạn, điều này đã rõ ràng, và tôi muốn hỏi, điều gì quyết định chiều dài của 117?

Giấc mơ nhỏVí dụ, các record được truyền là đường K ngày, và ATR được tính là một tập hợp, và phần tử đầu tiên của số âm của tập hợp này là chỉ số ATR của ngày đó (ngày cuối cùng của đường K ngày).

Giấc mơ nhỏĐưa một quả dẻo lên. Nếu bây giờ dữ liệu đường K chỉ có 10 Bar, tôi yêu cầu MA ((15) hay đường trung bình 15 chu kỳ, thì chắc chắn không thể tìm ra, bởi vì chỉ có 10 chu kỳ, không thể tính trung bình của 15 chu kỳ.

FangBeiNgoài ra, tôi đã sử dụng một tick thực để kiểm tra lại, và không có dữ liệu nào được trả về.

FangBeiTại sao dữ liệu trước đây lại không đáp ứng được yêu cầu chu kỳ?

Giấc mơ nhỏĐây là một ví dụ khá tốt, chỉ trong việc sử dụng thực tế, dữ liệu chỉ số mới nhất là ở cuối mảng, đó là các phần tử chỉ số -1. Sau đây là một số dữ liệu hữu ích, ví dụ như: https://dn-filebox.qbox.me/b7837ea30e5d8396ffa91c48204f2fbc9a7f4504.png