简体   繁体   English

D3布林乐队发行

[英]D3 Bollinger Band Issue

I want to generate bollinger band using D3 library. 我想使用D3库生成bollinger乐队。 I tried following code but unfortunately its throwing following error - 我尝试了以下代码,但不幸的是,它引发了以下错误-

VM224 d3.v3.js:670 Error: attribute d: Expected number, "M0,NaNL890,NaN" VM224 d3.v3.js:670错误:属性d:预期数字“ M0,NaNL890,NaN”

What could be the cause of this error? 造成此错误的原因是什么?

Code - 代码-

var margin = {
    top: 20,
    right: 20,
    bottom: 30,
    left: 50
  },
  width = 960 - margin.left - margin.right,
  height = 500 - margin.top - margin.bottom;

var n = 20; // n-period of moving average
var k = 2; // k times n-period standard deviation above/below moving average

var parseDate = d3.time.format("%m/%d/%Y").parse;

var x = d3.time.scale()
  .range([0, width]);
var y = d3.scale.linear()
  .range([height, 0]);
var xAxis = d3.svg.axis()
  .scale(x)
  .orient("bottom");
var yAxis = d3.svg.axis()
  .scale(y)
  .orient("left")
  .tickSize(3, 0);
var line = d3.svg.line()
  .x(function(d) {
    return x(d.date);
  })
  .y(function(d) {
    return y(d.close);
  });
var ma = d3.svg.line()
  .x(function(d) {
    return x(d.date);
  })
  .y(function(d) {
    return y(d.ma);
  });
var lowBand = d3.svg.line()
  .x(function(d) {
    return x(d.date);
  })
  .y(function(d) {
    return y(d.low);
  });
var highBand = d3.svg.line()
  .x(function(d) {
    return x(d.date);
  })
  .y(function(d) {
    return y(d.high);
  });
var bandsArea = d3.svg.area()
  .x(function(d) {
    return x(d.date);
  })
  .y0(function(d) {
    return y(d.low);
  })
  .y1(function(d) {
    return y(d.high);
  });

var svg = d3.select("body").append("svg")
  .attr("width", width + margin.left + margin.right)
  .attr("height", height + margin.top + margin.bottom)
  .append("g")
  .attr("transform", "translate(" + margin.left + "," + margin.top + ")");

var data = [
  [
    "9/9/2012",
    1000
  ],
  [
    "9/14/2013",
    100
  ]
];

data.forEach(function(d) {
  d.date = parseDate(d[0]);
  d.close = parseInt(d[1]);

  var bandsData = getBollingerBands(n, k, data);

  x.domain(d3.extent(data, function(d) {
    return d.date;
  }));
  y.domain([d3.min(bandsData, function(d) {
      return d.low;
    }),
    d3.max(bandsData, function(d) {
      return d.high;
    })
  ]);

  svg.append("g")
    .attr("class", "x axis")
    .attr("transform", "translate(0," + height + ")")
    .call(xAxis);
  svg.append("g")
    .attr("class", "y axis")
    .call(yAxis);

  svg.append("path")
    .datum(bandsData)
    .attr("class", "area bands")
    .attr("d", bandsArea);
  svg.append("path")
    .datum(bandsData)
    .attr("class", "line bands")
    .attr("d", lowBand);
  svg.append("path")
    .datum(bandsData)
    .attr("class", "line bands")
    .attr("d", highBand);
  svg.append("path")
    .datum(bandsData)
    .attr("class", "line ma bands")
    .attr("d", ma);

  svg.append("path")
    .datum(data)
    .attr("class", "line")
    .attr("d", line);
});

function getBollingerBands(n, k, data) {
  var bands = []; //{ ma: 0, low: 0, high: 0 }
  for (var i = n - 1, len = data.length; i < len; i++) {
    var slice = data.slice(i + 1 - n, i);
    var mean = d3.mean(slice, function(d) {
      return d.close;
    });
    var stdDev = Math.sqrt(d3.mean(slice.map(function(d) {
      return Math.pow(d.close - mean, 2);
    })));
    bands.push({
      date: data[i].date,
      ma: mean,
      low: mean - (k * stdDev),
      high: mean + (k * stdDev)
    });
  }
  return bands;
}

Fiddle 小提琴

See working jsfiddle 参见工作jsfiddle

First problem was, this being Bollinger Bands, that it needed more than the 2 data points you supplied it. 第一个问题是布林带,它需要的不仅仅是您提供的2个数据点。 When passing n=20 to getBollingerBands() it means it'll want to extract a mean value out of 20 consecutive data points. 当将n=20传递给getBollingerBands()这意味着它将getBollingerBands() 20个连续的数据点中提取平均值。 Since there were only 2, it yielded a blank array, which in turn caused NaN values to make it into the <path> . 由于只有2个,因此产生了一个空白数组,这又导致NaN值进入<path>

I updated that data array to be a whole lot longer, as needed. 我根据需要将数据数组更新了很多。

The other issue was that instead of this: 另一个问题是:

data.forEach(function(d) {
  d.date = parseDate(d[0]);
  d.close = parseInt(d[1]);
})

you had the function passed to forEach extend all the way down to include all the rendering code (eg svg.append("path") ), which meant it was trying to render the whole thing one per data point (ie potentially hundreds of times). 您已将传递给forEach的函数一直扩展到包括所有呈现代码(例如svg.append("path") ),这意味着它试图在每个数据点呈现整个事物(即可能呈现数百次) )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM