具有移动平均线的HTML5 / JS图表

时间:2013-11-14 15:31:00

标签: javascript jquery html5 charts highcharts

问题:如何计算移动平均线并在JS / HTML5图表上绘制?

我能找到的最接近的例子是this website。看看它的JS文件,我无法识别绘图图表库。经过仔细检查,似乎移动平均线不是在服务器端计算的,而是在客户端计算的。

任何建议都赞赏!

enter image description here

6 个答案:

答案 0 :(得分:16)

这是一个quick example,它计算一个3点移动平均线客户端并用Highcharts绘制它:

var N = 100;
var someData = [];
for (var i = 0; i < N; i++)
{
    someData.push([i,Math.random() * 100]);
}

var moveMean = [];
for (var i = 1; i < N-1; i++)
{
    var mean = (someData[i][1] + someData[i-1][1] + someData[i+1][1])/3.0;
    moveMean.push([i,mean]);
}

enter image description here

答案 1 :(得分:4)

I wrote a more general purpose function below.

To use it, simply pass an array of values, the count (or length) of the moving average, and an optional qualifier function.

For example:

movingAvg(arr, 10) will return a 10 data point moving average of the values in the array arr.

movingAvg(arr, 20, function(val){ return val != 0; }) will return a 20 data point moving average of the non-zero values in the array arr

So with Chart.js, for example, you can use it like so:

...
,datasets: [
     {
         label: "Values"
        ,data: values
    }
    ,{
         type: "line"
        ,label: "20 Point Moving Average"
        ,data: movingAvg(values, 20, function(val){ return val != 0; })
    }
]
...

The function:

    /**
    * returns an array with moving average of the input array
    * @param array - the input array
    * @param count - the number of elements to include in the moving average calculation
    * @param qualifier - an optional function that will be called on each 
    *  value to determine whether it should be used
    */
    function movingAvg(array, count, qualifier){

        // calculate average for subarray
        var avg = function(array, qualifier){

            var sum = 0, count = 0, val;
            for (var i in array){
                val = array[i];
                if (!qualifier || qualifier(val)){
                    sum += val;
                    count++;
                }
            }

            return sum / count;
        };

        var result = [], val;

        // pad beginning of result with null values
        for (var i=0; i < count-1; i++)
            result.push(null);

        // calculate average for each subarray and add to result
        for (var i=0, len=array.length - count; i <= len; i++){

            val = avg(array.slice(i, i + count), qualifier);
            if (isNaN(val))
                result.push(null);
            else
                result.push(val);
        }

        return result;
    }

答案 2 :(得分:0)

我遇到了同样的问题。 这是我的例子供你参考。 您可以根据需要设置任意长度的采样点。

var getAverage = function(arr, n){
  var sum=0;
  if(n>arr.length){
    n = arr.length;
  }
  
  for(var ii=arr.length-n; ii<arr.length; ii++){
    sum += arr[ii];
  }
  return sum/n;
}


function(acceleration, 3);

答案 3 :(得分:0)

代码不是我的,但它对财务计算中的移动平均线非常有效。

var movingAverage = function(d, t, roundUp) {
    if (d.length >= t && d.constructor === Array) {
        var r = [], s = 0, f = this.decimalRoundingFactor, ma;

        roundUp = typeof roundUp === undefined? true : roundUp;

        for(var i=0;i<d.length;++i) {
            s += isNaN(d[i])? 0: d[i];
            if (i < t-1) {
                r.push(NaN);
            } else if (i+1 === t) {
                ma = roundUp? Math.round((s/t)*f)/f: s/t;
                r.push(ma);
            } else {
                s -= isNaN(d[i-t])? 0: d[i-t];
                ma = roundUp? Math.round((s/t)*f)/f: s/t;
                r.push(ma);
            }
        }

        return r;
    } else {
        throw "[ERROR] TechnicalAnalysis#movingAverage: Not enought data! OR data is not Array!";
    }
};

答案 4 :(得分:0)

现在可能有点老了,但这也许会对某人有所帮助。

function sma(tIndex, N, array) {
    // return undefined if array is falsy, if range lookback or N exceeds array length
    if (!array || (tIndex - N) < 0 || N > array.length) return;
    const range = array.slice((tIndex - N), tIndex);
    const sum = range.reduce((acc, num) => acc += num, 0);
    return (sum / N);
}

其中:tIndex =“当前价格指数”,N =“回溯范围”,数组=“数据集”

答案 5 :(得分:0)

一个更通用,更简单的功能就是这个:

function movingAvg(array, countBefore, countAfter) {
  if (countAfter == undefined) countAfter = 0;
  const result = [];
  for (let i = 0; i < array.length; i++) {
    const subArr = array.slice(Math.max(i - countBefore, 0), Math.min(i + countAfter + 1, array.length));
    const avg = subArr.reduce((a, b) => a + (isNaN(b) ? 0 : b), 0) / subArr.length;
    result.push(avg);
  }
  return result;
}

const myArr = [1, 1, 2, 2, 3, 4, 5, 6, 7, 8, 9];

//averages of 7 (i.e. 7 day moving average):
const avg7Before = movingAvg(myArr, 6); //6 before and the current
const avg7Middle = movingAvg(myArr, 3, 3); //3 before, 3 after, plus the current
const avg7After = movingAvg(myArr, 0, 6); //6 after plus the current


console.log('original:',...myArr.map(x => x.toFixed(1)));
console.log('7 before:',...avg7Before.map(x => x.toFixed(1)));
console.log('7 middle:',...avg7Middle.map(x => x.toFixed(1)));
console.log('7 after: ',...avg7After.map(x => x.toFixed(1)));