Skip to content

Latest commit

 

History

History
174 lines (153 loc) · 5 KB

DMI指标.md

File metadata and controls

174 lines (153 loc) · 5 KB

策略名称

DMI指标

策略作者

独舞

策略描述

最近用到了DMI指标,TV上超级简单一行代码搞定的事,我找了又找就是找不到JS版的 没办法自己写吧,对于我这种非专业人士,就这一个指标连写代改用了一天,烦死了。

TraingView 上的DMI指标,只包含DI+ DI-和ADX三条线 完全按照TV上的DMI算法计算,误差非常非常小,数组第一个元素就是当前K线的DMI值

源码 (javascript)

//当前值与前值的差异,x[0] - x[length],symbol参数值只能是1或-1
function change(records, length, symbol) {
    if (!records || !length || !Math.abs(symbol) == 1) {
        return;
    }
    //反转数组让最新的数据在数组最开端
    records = records.slice().reverse();
    //将records中的最高价最低价单独录入不同的数组
    var srcHigh = [];
    var srcLow = [];
    for (var i = 0; i < records.length; i++) {
        srcHigh.push(records[i].High);
        srcLow.push(records[i].Low);
    }
    //计算差值数据不足处用NaN填充
    var src = [];
    for (var i = 0; i < records.length; i++) {
        if (i > records.length - 1 - length) {
            src.push(NaN);
        } else {
            if (symbol > 0) {
                src.push((srcHigh[i] - srcHigh[i + length]) * symbol);
            } else {
                src.push((srcLow[i] - srcLow[i + length]) * symbol);
            }
        }
    }
    return src;
}
//真实波动幅度,也可以为TR
function tr(records) {
    if (!records) {
        return;
    }
    //反转数组让最新的数据在数组最开端
    records = records.slice().reverse();
    var high = [];
    var low = [];
    var close = [];
    //将records中的最高价最低价收盘价单独录入不同的数组
    for (var i = 0; i < records.length; i++) {
        high.push(records[i].High);
        low.push(records[i].Low);
        close.push(records[i].Close);
    }
    var src = [];
    //计算tr值数据不足处用NaN填充
    for (var i = 0; i < records.length; i++) {
        if (i > records.length - 2) {
            src.push(NaN);
        } else {
            src.push(Math.max(high[i] - low[i], Math.abs(high[i] - close[i + 1]), Math.abs(low[i] - close[i + 1])));
        }
    }
    return src;
}
//RSI DMI中使用的移动平均线。 它是指数加权移动平均线,alpha加权值 = 1 /长度
function rma(records, length) {
    if (!records || !length) {
        return;
    }
    //反转数组让最新的数据在数组最末端方便计算
    records = records.slice().reverse();
    //alpha加权因子
    var alpha = 1 / length;

    var sum = 0.0;
    var lenNum = 0;
    var src = [];
    //计算ram值数据不足处用NaN填充
    for (var i = 0; i < records.length; i++) {
        if (isNaN(records[i])) {
            src.push(NaN);
            lenNum = i + 1;
        } else if (!isNaN(records[i]) && i < lenNum + length) {
            sum = sum + records[i] / length;
            if (i == lenNum + length - 1) {
                src.push(sum);
            } else {
                src.push(NaN);
            }
        } else {
            sum = alpha * records[i] + (1 - alpha) * src[i - 1];
            src.push(sum);
        }
    }
    return src.slice().reverse();
}
$.DMI = function DMI(records, adxLength, adxSmoothing) {
    if (!records || !adxLength || !adxSmoothing) {
        return;
    }
    var up = change(records, 1, 1);
    var down = change(records, 1, -1);
    var plusDM = [];
    var minusDM = [];
    for (var i = 0; i < records.length; i++) {
        p = isNaN(up[i]) ? NaN : up[i] > down[i] && up[i] > 0 ? up[i] : 0;
        m = isNaN(down[i]) ? NaN : down[i] > up[i] && down[i] > 0 ? down[i] : 0;
        plusDM.push(p);
        minusDM.push(m);
    }
    var trur = rma(tr(records), adxLength);
    var plus = [];
    var minus = [];
    var plusDMrma = rma(plusDM, adxLength);
    var minusDMrma = rma(minusDM, adxLength);
    for (var i = 0; i < records.length; i++) {
        if (i > 0 && (isNaN(plusDMrma[i]) || isNaN(minusDMrma[i]))) {
            plus.push(plus[i - 1]);
            minus.push(minus[i - 1]);
        } else {
            plus.push((plusDMrma[i] * 100) / trur[i]);
            minus.push((minusDMrma[i] * 100) / trur[i]);
        }
    }
    var scr = [];
    var sum = [];
    for (var i = 0; i < records.length; i++) {
        sum.push(plus[i] + minus[i]);
        scr.push(Math.abs(plus[i] - minus[i]) / (sum[i] == 0 ? 1 : sum[i]));
    }
    var adx = [];
    var src2 = rma(scr, adxSmoothing);
    for (var i = 0; i < src2.length; i++) {
        adx.push(100 * src2[i]);
    }
    return [plus, minus, adx];
}
function main() {
    
    exchange.SetCurrency("BTC_USDT");
    exchange.SetContractType("swap");
    
    var records = exchange.GetRecords(PERIOD_M5);
    var ret = DMI(records, 14, 14);

    Log("plus", ret[0].length, ret[0]);
    Log("minus", ret[1].length, ret[1]);
    Log("adx", ret[2].length, ret[2]);
}

策略出处

https://www.fmz.com/strategy/349804

更新时间

2022-03-09 15:58:20