最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I prevent my output array from duplicating a certain value? - Stack Overflow

programmeradmin2浏览0评论

I am calculating the rolling simple moving average (SMA) from a sample array of stock prices which are then plotted on a chart. The x axis corresponds to the "x" value in the array which holds the dates, and the y axis in the array holds the open, high, low, and closing prices for a given stock for each date. Only the closing prices are used to calculate the SMA.

The average calculates correctly, however the method I'm using to push values to the output array is duplicating a date. If the number of periods (days) for which I'm calculating the average is 5, as shown in the code below, I should see null Y values for the first 4 days. The calculated SMA should appear as the Y value on the 5th day. Instead, I'm showing null values for the first 5 days, and then showing the SMA on the 5th day - duplicating the 5th date in the sequence.

How could I revise my code to avoid this?

    let data=[
    {x:"2021-05-15T00:00:00.000Z",y:[24.8,25.2,24.76,24.91]},  
    {x:"2021-05-16T00:00:00.000Z",y:[25.04,25.04,24.97,25.03]},
    {x:"2021-05-17T00:00:00.000Z",y:[25.05,25.45,25.01,25.31]},
    {x:"2021-05-20T00:00:00.000Z",y:[25.43,25.43,25.2,25.38]},
    {x:"2021-05-21T00:00:00.000Z",y:[25.33,25.4,25.15,25.33]},
    {x:"2021-05-22T00:00:00.000Z",y:[25.39,25.39,25.27,25.3]},
    {x:"2021-05-23T00:00:00.000Z",y:[25.28,25.48,25.21,25.28]},
    {x:"2021-05-24T00:00:00.000Z",y:[25.27,25.59,25.17,25.29]},
    {x:"2021-05-28T00:00:00.000Z",y:[25.29,25.45,25.23,25.43]},
    {x:"2021-05-29T00:00:00.000Z",y:[25.5,25.5,25.37,25.43]}];
    
    let resultingArray = calcAverage(data, 5);
    
    function calcAverage(data, period) {
      let result = [];
    
        period = period || 5;
        for (let i = 0; i < period; i++)
            result.push({
                x: data[i].x,
                y: null
            });
            
      for (let i = period - 1; i < data.length; i++) {
        let window = data.slice(i - period + 1, i + 1); 
        let mean = window.reduce((sum, val) => sum + val.y[3], 0) / period;
    
        if (isNaN(mean))
            result.push({
                x: data[i].x,
                y: null
            });
        else
            result.push({
                x: data[i].x,
                y: mean
            });
      }
      return result;
    }

I logged the output array so you can see the duplication:

0: {x: '2021-05-15T00:00:00.000Z', y: null}
1: {x: '2021-05-16T00:00:00.000Z', y: null}
2: {x: '2021-05-17T00:00:00.000Z', y: null}
3: {x: '2021-05-20T00:00:00.000Z', y: null}
**4: {x: '2021-05-21T00:00:00.000Z', y: null}
5: {x: '2021-05-21T00:00:00.000Z', y: 25.192}**
6: {x: '2021-05-22T00:00:00.000Z', y: 25.27}
7: {x: '2021-05-23T00:00:00.000Z', y: 25.32}
8: {x: '2021-05-24T00:00:00.000Z', y: 25.315999999999995}
9: {x: '2021-05-28T00:00:00.000Z', y: 25.326}

I am calculating the rolling simple moving average (SMA) from a sample array of stock prices which are then plotted on a chart. The x axis corresponds to the "x" value in the array which holds the dates, and the y axis in the array holds the open, high, low, and closing prices for a given stock for each date. Only the closing prices are used to calculate the SMA.

The average calculates correctly, however the method I'm using to push values to the output array is duplicating a date. If the number of periods (days) for which I'm calculating the average is 5, as shown in the code below, I should see null Y values for the first 4 days. The calculated SMA should appear as the Y value on the 5th day. Instead, I'm showing null values for the first 5 days, and then showing the SMA on the 5th day - duplicating the 5th date in the sequence.

How could I revise my code to avoid this?

    let data=[
    {x:"2021-05-15T00:00:00.000Z",y:[24.8,25.2,24.76,24.91]},  
    {x:"2021-05-16T00:00:00.000Z",y:[25.04,25.04,24.97,25.03]},
    {x:"2021-05-17T00:00:00.000Z",y:[25.05,25.45,25.01,25.31]},
    {x:"2021-05-20T00:00:00.000Z",y:[25.43,25.43,25.2,25.38]},
    {x:"2021-05-21T00:00:00.000Z",y:[25.33,25.4,25.15,25.33]},
    {x:"2021-05-22T00:00:00.000Z",y:[25.39,25.39,25.27,25.3]},
    {x:"2021-05-23T00:00:00.000Z",y:[25.28,25.48,25.21,25.28]},
    {x:"2021-05-24T00:00:00.000Z",y:[25.27,25.59,25.17,25.29]},
    {x:"2021-05-28T00:00:00.000Z",y:[25.29,25.45,25.23,25.43]},
    {x:"2021-05-29T00:00:00.000Z",y:[25.5,25.5,25.37,25.43]}];
    
    let resultingArray = calcAverage(data, 5);
    
    function calcAverage(data, period) {
      let result = [];
    
        period = period || 5;
        for (let i = 0; i < period; i++)
            result.push({
                x: data[i].x,
                y: null
            });
            
      for (let i = period - 1; i < data.length; i++) {
        let window = data.slice(i - period + 1, i + 1); 
        let mean = window.reduce((sum, val) => sum + val.y[3], 0) / period;
    
        if (isNaN(mean))
            result.push({
                x: data[i].x,
                y: null
            });
        else
            result.push({
                x: data[i].x,
                y: mean
            });
      }
      return result;
    }

I logged the output array so you can see the duplication:

0: {x: '2021-05-15T00:00:00.000Z', y: null}
1: {x: '2021-05-16T00:00:00.000Z', y: null}
2: {x: '2021-05-17T00:00:00.000Z', y: null}
3: {x: '2021-05-20T00:00:00.000Z', y: null}
**4: {x: '2021-05-21T00:00:00.000Z', y: null}
5: {x: '2021-05-21T00:00:00.000Z', y: 25.192}**
6: {x: '2021-05-22T00:00:00.000Z', y: 25.27}
7: {x: '2021-05-23T00:00:00.000Z', y: 25.32}
8: {x: '2021-05-24T00:00:00.000Z', y: 25.315999999999995}
9: {x: '2021-05-28T00:00:00.000Z', y: 25.326}
Share Improve this question asked 22 hours ago fitted_sheetfitted_sheet 157 bronze badges 2
  • 3 If you want to avoid duplicates, you should better avoid using arrays. In some cases, you need Set(), in others — Map(). – Sergey A Kryukov Commented 22 hours ago
  • I'll look into these. Thanks for the suggestion! – fitted_sheet Commented 9 mins ago
Add a comment  | 

1 Answer 1

Reset to default 1

The entry that gets duplicated in relationship to the value you specify for period, is the clue.

You need to change

// for (let i = period - 1; i < data.length; i++) {

to

for (let i = period; i < data.length; i++) {

I'll let you figure out how or if the values to slice() need to change as well.

发布评论

评论列表(0)

  1. 暂无评论