问题:如何计算移动平均线并在JS / HTML5图表上绘制?
我能找到的最接近的例子是this website。看看它的JS文件,我无法识别绘图图表库。经过仔细检查,似乎移动平均线不是在服务器端计算的,而是在客户端计算的。
任何建议都赞赏!
答案 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]);
}
答案 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)));