rrag / react-stockcharts

Highly customizable stock charts with ReactJS and d3
http://rrag.github.io/react-stockcharts
MIT License
3.88k stars 958 forks source link

MACD calculated not all data #748

Open alexbom opened 4 years ago

alexbom commented 4 years ago

Hello! I can't understand, why MACD calculated not all data. Please, loot at the screenshot. All chart looks great, except left part, where children of MACD object are undefined. Data is correct, there is close value and date, but MACD is broken here. Why this happends? And why Area Chart doesn't draw at this part?

macd-nan

render() { const { data: initialData, currency, type, width, ratio } = this.props; const chartData = initialData.map(d => ({ date: new Date(d.x), close: d.y }));

const smaVolume50 = sma()
  .id(3)
  .options({ windowSize: 50, sourcePath: 'close' })
  .merge((d, c) => ({ ...d, smaVolume50: c }))
  .accessor(d => d.smaVolume50);

const macdCalculator = macd()
  .options({
    fast: 12,
    slow: 26,
    signal: 9,
  })
  .merge((d, c) => ({ ...d, macd: c }))
  .accessor(d => d.macd);

const ema26 = ema()
  .id(0)
  .options({ windowSize: 26 })
  .merge((d, c) => ({ ...d, ema26: c }))
  .accessor(d => d.ema26);

const ema12 = ema()
  .id(1)
  .options({ windowSize: 12 })
  .merge((d, c) => ({ ...d, ema12: c }))
  .accessor(d => d.ema12);

const calculatedData = smaVolume50(
  macdCalculator(ema12(ema26(chartData)))
);
const xScaleProvider = discontinuousTimeScaleProvider.inputDateAccessor(
  d => d.date
);
const { data, xScale, xAccessor, displayXAccessor } = xScaleProvider(calculatedData);

return (
  <div id='areaChartCanvas'>
    <ChartCanvas
      ref={ref => this.canvasRef = ref}
      ratio={ratio}
      width={width}
      height={400}
      margin={{ left: 20, right: 90, top: 20, bottom: 55 }}
      seriesName='MSFT'
      type={type}
      data={data}
      xScale={xScale}
      xAccessor={xAccessor}
      displayXAccessor={displayXAccessor}
    >
      <Chart
        id={0}
        yExtents={d => d.macd.signal}
        padding={{ top: 0, bottom: 0 }}
      >
        <YAxis
          axisAt='right'
          orient='right'
          ticks={5}
          stroke={vars.color.accent}
          tickStroke={vars.color.accent}
        />
      </Chart>
      <Chart
        id={1}
        padding={{ top: 0, bottom: 0 }}
        yExtents={d => d.macd.signal}
      >
        <defs>
          <linearGradient id='PerformanceGradient' x1='0' y1='100%' x2='0' y2='0%'>
            <stop offset='0%' stopColor={vars.color.negative} stopOpacity={0.5} />
            <stop offset='50%' stopColor='transparent' stopOpacity={0} />
            <stop offset='100%' stopColor={vars.color.positive} stopOpacity={0.5} />
          </linearGradient>
        </defs>
        <XAxis
          axisAt='bottom'
          orient='bottom'
          ticks={6}
          stroke={vars.color.accent}
          tickStroke={vars.color.accent}
        />
        <HoverTooltip
          yAccessor={d => d.macd.signal}
          tooltipContent={({ currentItem, xAccessor: _xAccessor }) => {
            return ({
              x: dayjs(_xAccessor(currentItem)).format('DD MMM YYYY HH:mm'),
              y: [
                {
                  label: 'value',
                  value: `${Utils.moneyFormat(currentItem.macd.signal)} ${Utils.currencyToSymbol(currency)}`,
                  stroke: vars.color.accent
                },
              ]
            });
          }}
          fontSize={16}
          bgFill={vars.color.lightBg}
          bgOpacity={0.6}
          fill={vars.color.lightBg}
          stroke={vars.color.lightBg}
          fontFill={vars.color.white}
        />
        <StraightLine yValue={0} stroke={vars.color.accent} opacity={0.2} />
        <AreaSeries
          yAccessor={d => d.macd.signal}
          baseAt={yScale => yScale(0)}
          fill='url(#PerformanceGradient)'
          strokeWidth={1}
          stroke={vars.color.accent}
          interpolation={curveMonotoneX}
          canvasGradient={canvasGradient}
        />
      </Chart>
    </ChartCanvas>
  </div>
);

}

rrag commented 4 years ago

image

That's how it is, depending on the window size, the first n candles have no value

alexbom commented 4 years ago

@rrag Sorry, didn't understand. How to fix this? In this example there is no empty values at the left side: https://codesandbox.io/s/github/rrag/react-stockcharts-examples2/tree/master/examples/CandleStickChartWithMACDIndicator But my chart has some undefined values not just empty space...

rrag commented 4 years ago

yes there is empty space on left side. Read up on MACD to understand how it is calculated. there will be undefined values in the beginning depending on what your windowSize is

image

oze4 commented 3 years ago

@rrag is there a way to set the window size to "whatever is currently visible"?