lightweight-charts: Histogram (volume) does not honor color setting (sometimes)

Lightweight Charts Version: “lightweight-charts”: “1.1.0”

Steps/code to reproduce: I can’t reproduce it easily, please bear with me until I can find a way to consistently reproduce this.

Context: typical volume histogram at the bottom of chart. There is a button in the UI that allows to switch timeframe. On click of a button, the volume serie (and candles) are changed.

The code is as follow:

// this is how the data is formatted for the chart
// snapshot is an OHLC array from an exchange
formatDataForChart (snapshot) {
  return snapshot.reduce((acc, _candle) => {
    const candle = Object.assign({}, _candle)
    candle.time = candle.time / 1000
    acc.candles.push(candle)
    acc.volume.push({
      time: candle.time,
      value: candle.volumeQuote,
      color: candle.open > candle.close ? volumeChartCfg.downColor : volumeChartCfg.upColor
    })
    return acc
  }, {volume: [], candles: []})
}
// method called when user click to change timeframe
changeInterval (interval) {
  this.chartInterval = interval
  const snapshot = await ... 
  const chartData = this.formatDataForChart(snapshot)
  this.candlestickSeries.setData(chartData.candles)
  this.volumeSeries.setData(chartData.volume)
  this.resetChartTimeScale(chartData)
}

Actual behavior: This works perfectly most of the time but sometimes, the chart does not use the color provided for the volume. (candles are fine). All bars are colored with one of the two colors provided. It is weird because it works most of the time and the bug(?) seems random.

Expected behavior: Bars should use the color provided.

Screenshots

Chart vs data provided.

volume_problem

You can see that the volume colors (array on the right) would match the candles color (which are automatically colored by the chart) but the chart draws them all with the same color.

About this issue

  • Original URL
  • State: closed
  • Created 5 years ago
  • Comments: 16 (9 by maintainers)

Commits related to this issue

Most upvoted comments

@AoDev I just created #242 with fixes. There you can find simplest repro for this bugs (see new files in tests/e2e/graphics/test-cases/series folder) 🙂

@AoDev I’ve reproduced that issues. They are definitely bugs 😂 We’ll fix them. Thank you for your the time to investigate and reproduce that interesting issues. I’ll post updates about my investigates here soon.

I managed to do what you said to consistently reproduce the issue. (good idea 😃) I have saved the api calls with the corresponding data and then replayed them.

I am adding a screen cast again and the data log.

  • Note, just to have a better hint of “when what” happens, I have logged the UI event where I was switching timeframe as well.

Screencast

A strange thing I’ve noted, at second 24-25 in the screencast (when things go wrong).

  • I switch timeframe (candles.setData())
  • At that moment, I have suddenly a wider first bar on the volume histogram. (I haven’t modified the volume data yet)
  • Then volume data is updated (volume.setData()) and I have 2 bars as it should, but the color is now wrong.

Screencast video here

Maybe not relevant but this is the script to replay.

    setTimeout(() => {
      // Wait UI boot before playing
      console.log('starting playing log')
      let step = 0
      const timer = setInterval(() => {
        const change = chartDataLog[step]
        let serie = null
        if (change.serie === 'candles') {
          serie = this.candlestickSeries
        }
        else if (change.serie === 'volume') {
          serie = this.volumeSeries
        }
        else if (change.serie === 'interval') {
          console.log(`-- switching interval to "${change.data}" --`)
        }
        if (serie) {
          // There is no serie sometimes because I was logging the changeInterval events too,
          // but these are just UI events.
          serie[change.method](change.data)
          const dataPrint = Array.isArray(change.data)
            ? `array[${change.data.length}]`
            : Object.keys(change.data).join(',')
          console.log(`${change.serie}.${change.method}(${dataPrint})`)
        }
        step++
        if (step === chartDataLog.length) {
          clearInterval(timer)
          console.log('finished playing log')
        }
      }, 1000)
    }, 2000)

Data log

[
  {
    'serie': 'candles',
    'method': 'setData',
    'data': [
      {
        'time': 1572432447,
        'open': 9114.95,
        'high': 9114.95,
        'low': 9114.95,
        'close': 9114.95,
        'volumeBase': 0.032852,
        'volumeQuote': 299.4443374
      },
      {
        'time': 1572432448,
        'open': 9114.95,
        'high': 9116.39,
        'low': 9112.85,
        'close': 9116,
        'volumeBase': 3.235358,
        'volumeQuote': 29489.98303578
      }
    ]
  },
  {
    'serie': 'volume',
    'method': 'setData',
    'data': [
      {
        'time': 1572432447,
        'value': 299.4443374,
        'color': '#94d1bc'
      },
      {
        'time': 1572432448,
        'value': 29489.98303578,
        'color': '#94d1bc'
      }
    ]
  },
  {
    'serie': 'candles',
    'method': 'update',
    'data': {
      'time': 1572432448,
      'open': 9114.95,
      'high': 9116.39,
      'low': 9112.98,
      'close': 9112.98,
      'volumeBase': 2.804467,
      'volumeQuote': 25562.92423849
    }
  },
  {
    'serie': 'volume',
    'method': 'update',
    'data': {
      'time': 1572432448,
      'value': 25562.92423849,
      'color': '#f5a8a8'
    }
  },
  {
    'serie': 'candles',
    'method': 'update',
    'data': {
      'time': 1572432448,
      'open': 9114.95,
      'high': 9116.39,
      'low': 9112.85,
      'close': 9116,
      'volumeBase': 3.235358,
      'volumeQuote': 29489.98303578
    }
  },
  {
    'serie': 'volume',
    'method': 'update',
    'data': {
      'time': 1572432448,
      'value': 29489.98303578,
      'color': '#94d1bc'
    }
  },
  {
    'serie': 'candles',
    'method': 'update',
    'data': {
      'time': 1572432450,
      'open': 9115.65,
      'high': 9118.04,
      'low': 9115.5,
      'close': 9118.04,
      'volumeBase': 1.006712,
      'volumeQuote': 9178.03512301
    }
  },
  {
    'serie': 'volume',
    'method': 'update',
    'data': {
      'time': 1572432450,
      'value': 9178.03512301,
      'color': '#94d1bc'
    }
  },
  {
    'serie': 'candles',
    'method': 'update',
    'data': {
      'time': 1572432451,
      'open': 9115.86,
      'high': 9115.86,
      'low': 9115.86,
      'close': 9115.86,
      'volumeBase': 0.013366,
      'volumeQuote': 121.84258476
    }
  },
  {
    'serie': 'volume',
    'method': 'update',
    'data': {
      'time': 1572432451,
      'value': 121.84258476,
      'color': '#94d1bc'
    }
  },
  {
    'serie': 'candles',
    'method': 'update',
    'data': {
      'time': 1572432420,
      'open': 9114.95,
      'high': 9118.04,
      'low': 9112.85,
      'close': 9115.86,
      'volumeBase': 10.023288,
      'volumeQuote': 91368.67014479
    }
  },
  {
    'serie': 'volume',
    'method': 'update',
    'data': {
      'time': 1572432420,
      'value': 91368.67014479,
      'color': '#94d1bc'
    }
  },
  {
    'serie': 'interval',
    'method': 'changeInterval',
    'data': '1m'
  },
  {
    'serie': 'candles',
    'method': 'setData',
    'data': [
      {
        'time': 1572432420,
        'open': 9114.95,
        'high': 9118.04,
        'low': 9112.85,
        'close': 9115.86,
        'volumeBase': 10.023288,
        'volumeQuote': 91368.67014479
      }
    ]
  },
  {
    'serie': 'volume',
    'method': 'setData',
    'data': [
      {
        'time': 1572432420,
        'value': 91368.67014479,
        'color': '#94d1bc'
      }
    ]
  },
  {
    'serie': 'candles',
    'method': 'update',
    'data': {
      'time': 1572432420,
      'open': 9114.95,
      'high': 9118.04,
      'low': 9112.85,
      'close': 9116.01,
      'volumeBase': 62.298288,
      'volumeQuote': 567874.02027343
    }
  },
  {
    'serie': 'volume',
    'method': 'update',
    'data': {
      'time': 1572432420,
      'value': 567874.02027343,
      'color': '#94d1bc'
    }
  },
  {
    'serie': 'candles',
    'method': 'update',
    'data': {
      'time': 1572432420,
      'open': 9114.95,
      'high': 9119.65,
      'low': 9112.85,
      'close': 9119.65,
      'volumeBase': 62.840102,
      'volumeQuote': 572814.03716855
    }
  },
  {
    'serie': 'volume',
    'method': 'update',
    'data': {
      'time': 1572432420,
      'value': 572814.03716855,
      'color': '#94d1bc'
    }
  },
  {
    'serie': 'candles',
    'method': 'update',
    'data': {
      'time': 1572432450,
      'open': 9115.65,
      'high': 9119.65,
      'low': 9115.5,
      'close': 9119.65,
      'volumeBase': 7.157282,
      'volumeQuote': 65246.60216423
    }
  },
  {
    'serie': 'volume',
    'method': 'update',
    'data': {
      'time': 1572432450,
      'value': 65246.60216423,
      'color': '#94d1bc'
    }
  },
  {
    'serie': 'interval',
    'method': 'changeInterval',
    'data': '10s'
  },
  {
    'serie': 'candles',
    'method': 'setData',
    'data': [
      {
        'time': 1572432440,
        'open': 9114.95,
        'high': 9116.39,
        'low': 9112.85,
        'close': 9113.04,
        'volumeBase': 3.27821,
        'volumeQuote': 29880.55777318
      },
      {
        'time': 1572432450,
        'open': 9115.65,
        'high': 9119.65,
        'low': 9115.5,
        'close': 9119.65,
        'volumeBase': 7.157282,
        'volumeQuote': 65246.60216423
      }
    ]
  },
  {
    'serie': 'volume',
    'method': 'setData',
    'data': [
      {
        'time': 1572432440,
        'value': 29880.55777318,
        'color': '#f5a8a8'
      },
      {
        'time': 1572432450,
        'value': 65246.60216423,
        'color': '#94d1bc'
      }
    ]
  },
  {
    'serie': 'candles',
    'method': 'update',
    'data': {
      'time': 1572432450,
      'open': 9115.65,
      'high': 9119.89,
      'low': 9115.5,
      'close': 9117.52,
      'volumeBase': 46.965262,
      'volumeQuote': 428144.18988502
    }
  },
  {
    'serie': 'volume',
    'method': 'update',
    'data': {
      'time': 1572432450,
      'value': 428144.18988502,
      'color': '#94d1bc'
    }
  },
  {
    'serie': 'candles',
    'method': 'update',
    'data': {
      'time': 1572432450,
      'open': 9115.65,
      'high': 9119.89,
      'low': 9115.5,
      'close': 9119.81,
      'volumeBase': 47.793836,
      'volumeQuote': 435700.4288268
    }
  },
  {
    'serie': 'volume',
    'method': 'update',
    'data': {
      'time': 1572432450,
      'value': 435700.4288268,
      'color': '#94d1bc'
    }
  }
]

@AoDev It’s unnecessary. Every version of the lightweight-charts includes dev builds, see https://unpkg.com/lightweight-charts/dist/lightweight-charts.standalone.development.js.