tradingview / lightweight-charts

Performant financial charts built with HTML5 canvas
https://www.tradingview.com/lightweight-charts/
Apache License 2.0
8.9k stars 1.55k forks source link

Multiple panes support #50

Open nothingalike opened 5 years ago

nothingalike commented 5 years ago

Looking through the documentation i dont see anything along these lines. I want to have my main chart but then add some additional data in a separate chart window. I believe some apps call it an Indicator Window. I was curious if its possible with this library.

rodrigopivi commented 2 years ago

Hope this feature is officially supported soon, just sharing another "hacky" solution to get this without a fork.

https://codesandbox.io/s/react-typescript-forked-mxek17?file=/src/App.tsx

lucas-labs commented 2 years ago

@romfrancois a plugin system would be fantastic. Are there any plans on bringing such a functionality?

tomlister commented 2 years ago

Can you guys actually read the thread. It won't get merged.

On Sun, 5 June 2022, 5:31 pm Lucas Colombo, @.***> wrote:

@romfrancois https://github.com/romfrancois a plugin system would be fantastic. Are there any plans on bringing such a functionality?

— Reply to this email directly, view it on GitHub https://github.com/tradingview/lightweight-charts/issues/50#issuecomment-1146756579, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABSK643X6WKJDM3L3SLNE2TVNRJVJANCNFSM4HW5YVJQ . You are receiving this because you commented.Message ID: @.***>

Boasoft commented 2 years ago

@ntf Fantastic for with the multipane support, your solution works like a charm (And thatnks for regular merges to newer version of Lightweight-charts ;-) )! One question though: how to change default height split between new panes? Assuming I'd like to have 80% of chart's height to be assigned to pane 0 and just 20% to pane 1 (as default) - where should I look for it in the code? I've been trying to find it since several days and still no luck ;-).

hoandt commented 2 years ago

@ntf This is amazing mate!

ntf commented 2 years ago

@Boasoft

I would suggest you take a look below how height are set and being adjusted with mouse dragging on the pane separators.

https://github.com/ntf/lightweight-charts/blob/master/src/gui/chart-widget.ts#L382 https://github.com/ntf/lightweight-charts/blob/master/src/gui/pane-separator.ts#L140

In additional to the above, you also need to add a way to somehow pass the initial height in terms of StretchFactor.

I can help review and polish it if you send me a pull request to my folk :)

Boasoft commented 2 years ago

Thank you very much. I think I have too weak programming skills to add this officially and send it to review, but I will dig in just to modify by default height of second pane compared to remaining panes - as this is what I need. Thanks for the hint in the code, you've helped me a lot!

romfrancois commented 2 years ago

@romfrancois a plugin system would be fantastic. Are there any plans on bringing such a functionality?

No ETA atm; we're exploring various options and ways to do things in the simplest way.

dss010101 commented 2 years ago

this probably the main issue with these libraries - features are slow to role out. been 3 years and no progress. i think it's best to make the modification to the source yourself to achieve this. what i ended up doing.

davidxiao commented 1 year ago

wonder if there is any updates? :)

tobiasfuhlroth commented 1 year ago

@romfrancois +1 for the plugin system and then leave it up to the community to extend the main library as needed with separately maintained plugin-repositories.

I guess everyone who want's to achieve just a little more than the bare basics gets stuck at some point or another. At that point there is basically three options:

thinhtran3588 commented 1 year ago

Hi everyone. I had the same issue when trying to use this chart yesterday and was happy to find this thread. Based on your previous solutions, I managed to make a simple one and it worked pretty well using only existing APIs. Just want to share with you guys. Please note: those charts must have the same data length. I managed to make a candlestick/vol chart with 1 rsi chart & 1 macd chart below with it. https://codesandbox.io/s/react-typescript-forked-grjc4y?file=/src/App.tsx

// sync charts
charts.forEach((chart) => {
  if (!chart) {
    return;
  }
  chart.timeScale().subscribeVisibleTimeRangeChange((e) => {
    charts
      .filter((c) => c !== chart)
      .forEach((c) => {
        c.timeScale().applyOptions({
          rightOffset: chart.timeScale().scrollPosition()
        });
      });
  });
  chart.timeScale().subscribeVisibleLogicalRangeChange((range) => {
    if (range) {
      charts
        .filter((c) => c !== chart)
        .forEach((c) => {
          c.timeScale().setVisibleLogicalRange({
            from: range?.from,
            to: range?.to
          });
        });
    }
  });
});
Rassibassi commented 1 year ago

Ive taken @ntf repository and his fiddle from here [1] and created a minimal react version: https://github.com/Rassibassi/multipane_tradingview

[1] https://jsfiddle.net/adrianntf/6qea5ytv/

tomlister commented 1 year ago

I have 41 emails in my inbox since I started watching this issue. I don't think you're getting this feature any time soon.

On Sat, 12 Mar 2022, 10:01 pm teneon, @.***> wrote:

This would be very useful. Any ETA on this feautre?

— Reply to this email directly, view it on GitHub https://github.com/tradingview/lightweight-charts/issues/50#issuecomment-1065862575, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABSK6464NOZXAYSC7G4TJW3U7R2QPANCNFSM4HW5YVJQ . You are receiving this because you commented.Message ID: @.***>

LLAndrei commented 1 year ago

Ive taken @ntf repository and his fiddle from here [1] and created a minimal react version: https://github.com/Rassibassi/multipane_tradingview

[1] https://jsfiddle.net/adrianntf/6qea5ytv/

Wonderful work! Congrats!

Did anyone figured a way to set height / resize the panels?

movy commented 1 year ago

The versions mentioned above use LW 3.6, which's missing some important features like addBaselineSeries. For those willing to build the most recent (4.0-dev) LW charts + ntf's multipane patch, either merge both repos, or use @john-wallace-dev recent fork:

git clone https://github.com/john-wallace-dev/lightweight-charts
cd lightweight-charts
yarn install --ignore-engines

The standalone lib will be built into dist folder.

majid1605 commented 1 year ago

Unfortunately, after being disappointed with the official support for this feature, I use this project with more features. Although it is a new project, it may have many bugs. https://github.com/project-nv/night-vision

nadayoon commented 1 year ago

Ive taken @ntf repository and his fiddle from here [1] and created a minimal react version: https://github.com/Rassibassi/multipane_tradingview

[1] https://jsfiddle.net/adrianntf/6qea5ytv/

thank you very much

SubigyaPanta commented 1 year ago

Ive taken @ntf repository and his fiddle from here [1] and created a minimal react version: https://github.com/Rassibassi/multipane_tradingview

[1] https://jsfiddle.net/adrianntf/6qea5ytv/

This was really helpful for those of us who don't know react and use just plain js with script tags.

FairyWorld commented 1 year ago

V4.0.0 support multiple panes or not?

julio899 commented 1 year ago

Do you want to add additional series to the new pane or to existing one? Something like this https://jsfiddle.net/TradingView/srwoh679/?

I want to implements like this -> https://jsfiddle.net/adrianntf/6qea5ytv/ this feature when be integrated?

Atila027 commented 1 year ago

I want this feature. Is there anyone who know about that well?

tiger2014 commented 1 year ago

Do you want to add additional series to the new pane or to existing one? Something like this https://jsfiddle.net/TradingView/srwoh679/?

I want to implements like this -> https://jsfiddle.net/adrianntf/6qea5ytv/ this feature when be integrated?

have you update the official code of 'lightweight-charts'?

jbunning commented 1 year ago

Hi guys,

You can do something like this, works reasonably well:

      chart1.timeScale().subscribeVisibleTimeRangeChange((visibleTimeRange) => {
          chart2.timeScale().setVisibleRange(visibleTimeRange);
      });
      chart2.timeScale().subscribeVisibleTimeRangeChange((visibleTimeRange) => {
          chart1.timeScale().setVisibleRange(visibleTimeRange);
      });
mhlvn commented 1 year ago

Hi! this is my solution

setTimeout(() => {

        chart1.timeScale().subscribeVisibleLogicalRangeChange(() => {
                chart2.timeScale().setVisibleLogicalRange(chart1.timeScale().getVisibleLogicalRange());
        });

        chart2.timeScale().subscribeVisibleLogicalRangeChange(() => {
                chart1.timeScale().setVisibleLogicalRange(chart2.timeScale().getVisibleLogicalRange());
        });

}, 1000);

Obiwanbde commented 1 year ago

I see that the last two code share are running well enough. I could not manage to show tooltips for chart2 yet but I think it would be possible. Thanks.

NFSS10 commented 1 year ago

Hi guys,

You can do something like this, works reasonably well:

      chart1.timeScale().subscribeVisibleTimeRangeChange((visibleTimeRange) => {
          chart2.timeScale().setVisibleRange(visibleTimeRange);
      });
      chart2.timeScale().subscribeVisibleTimeRangeChange((visibleTimeRange) => {
          chart1.timeScale().setVisibleRange(visibleTimeRange);
      });

This works pretty well but when zoomed in the charts weren't being synced as seamlessly as I wished. Using VisibleLogicalRange instead of VisiblelRange fixed that for me!

Here is the code If someone needs it:

chart1.timeScale().subscribeVisibleLogicalRangeChange(range => {
    chart2.timeScale().setVisibleLogicalRange(range);
});
chart2.timeScale().subscribeVisibleLogicalRangeChange(range => {
    chart1.timeScale().setVisibleLogicalRange(range);
});
Marbemoreno commented 11 months ago

I have 2 or more chart and I did this to sync both


chart.timeScale().subscribeVisibleLogicalRangeChange((range) => {
              if (indicatorAux.chart) {
                indicatorAux.chart.timeScale().setVisibleLogicalRange(range);
              }
            });
            // Stop move in not current charts (this is because Ineed this behavior)
            indicatorAux.chart
              .timeScale()
              .subscribeVisibleLogicalRangeChange((range) => {
                if (indicatorAux.chart.timeScale())
                  indicatorAux.chart
                    .timeScale()
                    .setVisibleLogicalRange(
                      chart.timeScale().getVisibleLogicalRange()
                    );
              });
          });

But I still want to show the crosshair line in both (chart) at the same time how could I do that?

bonald commented 9 months ago

//sync crosshair // Define a function to handle crosshair movement synchronization const syncCrosshairMovement = (sourceChartRef, targetChartRefs) => { return sourceChartRef.current.subscribeCrosshairMove((param) => { if (param.point !== undefined && param.time !== undefined) { const dataPoint = getCrosshairDataPoint(sourceChartRef.current, param); targetChartRefs.forEach((chartRef) => { syncCrosshair(chartRef.current, obvSeriesRef.current, dataPoint); syncCrosshair(chartRef.current, openInterestSeriesRef.current, dataPoint); syncCrosshair(chartRef.current, candleSeriesRef.current, dataPoint); }); } }); };

// Define a function to handle visible logical range synchronization const syncVisibleLogicalRange = (sourceChartRef, targetChartRefs) => { return sourceChartRef.current.timeScale().subscribeVisibleLogicalRangeChange((timeRange) => { if (timeRange && typeof timeRange === "object" && timeRange.hasOwnProperty("from") && timeRange.hasOwnProperty("to")) { targetChartRefs.forEach((chartRef) => { chartRef.current.timeScale().setVisibleLogicalRange(timeRange); }); } else { targetChartRefs.forEach((chartRef) => { chartRef.current.timeScale().resetTimeScale(); }); } }); };

const targetChartRefs1 = [chartRef2, chartRef3]; const targetChartRefs2 = [chartRef, chartRef3]; const targetChartRefs3 = [chartRef, chartRef2];

  // Call the sync functions for each source chart
  syncCrosshairMovement(chartRef, targetChartRefs1);
  syncVisibleLogicalRange(chartRef, targetChartRefs1);

  syncCrosshairMovement(chartRef2, targetChartRefs2);
  syncVisibleLogicalRange(chartRef2, targetChartRefs2);

  syncCrosshairMovement(chartRef3, targetChartRefs3);
  syncVisibleLogicalRange(chartRef3, targetChartRefs3);
DeVoresyah commented 7 months ago

the multipane feature is really helpful, and I wonder if multipane can do something like this. instead of showing 2 charts, how about merging them into an existing chart and then adding 1 more yAxis on the right?

image
dc-thanh commented 7 months ago

Even though the two charts are synchronized, there seems to be an issue with the crosshair. Chart 1 has more data points than Chart 2, but the data points on both charts are similar in terms of timing.

https://github.com/tradingview/lightweight-charts/assets/61302262/efdc6404-6438-4cb1-83e6-112d0402047e

NFSS10 commented 7 months ago

Even though the two charts are synchronized, there seems to be an issue with the crosshair. Chart 1 has more data points than Chart 2, but the data points on both charts are similar in terms of timing. Screen.Recording.2023-12-14.at.10.32.03.AM.mp4

This is the correct behavior, if you want the crosshair to be horizontally aligned everytime, you need to expand the lower chart so that both charts fill the same space.

I think you could use setVisibleLogicalRange() or setVisibleRange() to force that behaviour

thichmautim commented 7 months ago

The versions mentioned above use LW 3.6, which's missing some important features like addBaselineSeries. For those willing to build the most recent (4.0-dev) LW charts + ntf's multipane patch, either merge both repos, or use @john-wallace-dev recent fork:

git clone https://github.com/john-wallace-dev/lightweight-charts
cd lightweight-charts
yarn install --ignore-engines

The standalone lib will be built into dist folder.

Thank you too much!!!

841660202 commented 5 months ago

the multipane feature is really helpful, and I wonder if multipane can do something like this. instead of showing 2 charts, how about merging them into an existing chart and then adding 1 more yAxis on the right? image

Same question, how to achieve it?

julio899 commented 5 months ago

the multipane feature is really helpful, and I wonder if multipane can do something like this. instead of showing 2 charts, how about merging them into an existing chart and then adding 1 more yAxis on the right? image

Same question, how to achieve it?

https://github.com/tradingview/lightweight-charts/assets/2575745/753d02f0-59cb-4984-a2d8-47d6237f8b7a

you need that, the data in the same data time and add event when scroll or zoom in the chart also use subscribeCrosshairMove, subscribeVisibleLogicalRangeChange & coordinateToPrice

rwitzlib commented 5 months ago

Here is an updated fork of @ntf / @john-wallace-dev forks that people can reference if they'd like: https://github.com/rwitzlib/lightweight-charts Currently updated to v4.1.3 but Ill try to keep this updated until multi-pane is officially supported

rwitzlib commented 5 months ago

@rwitzlib Can you explain to me how can I add another pane to the chart with your fork ?

Here is an example of using this library. For these examples, assume chart is a reference to the chart object resulting from the createChart method. I dont use swapPane or getPaneElements so I cant attest to those unfortunately.

Adding a pane: pane: can be set to an int (0, 1, 2, 3, etc.). If there are no studies with the pane number 1 or greater, a new pane will be created and the study will be added to that pane.

image

Removing a pane: paneToRemove is an int

image

The Result: image

madnight commented 5 months ago

@rwitzlib

Can you provide a dist standalone production version e.g. on UNPKG or as Github Release Asset?

cat3311 commented 5 months ago

Can you provide a dist standalone production version e.g. on UNPKG or as Github Release Asset?

lightweight-charts.standalone.development.zip

cat3311 commented 5 months ago

@rwitzlib

image

Thanks for the improved charts with pane Can you make a separate watermark for each panel?

tiger2014 commented 4 months ago

Here is an updated fork of @ntf / @john-wallace-dev forks that people can reference if they'd like: https://github.com/rwitzlib/lightweight-charts Currently updated to v4.1.3 but Ill try to keep this updated until multi-pane is officially supported

Hi rwitzlib, I have a basicquestion: how to use your code in file with extention .html?

gokuschoyi commented 3 months ago

Here is an updated fork of @ntf / @john-wallace-dev forks that people can reference if they'd like: https://github.com/rwitzlib/lightweight-charts Currently updated to v4.1.3 but Ill try to keep this updated until multi-pane is officially supported

Hey @rwitzlib, I tried to install the fork by adding it to my package.json as follows "lightweight-charts": "github:rwitzlib/lightweight-charts"

and did npm install. I get the following error

Error: ERROR: Failed to set up chrome-headless-shell v121.0.6167.85! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to skip download.

I have then set the PUPPETEER_SKIP_DOWNLOAD to true and I then get another error as follows :

Error: Cannot find module '/home/goku/test/node_modules/lightweight-charts/scripts/githooks/install.js'

I then set the PUPPETEER_SKIP_DOWNLOAD to false and tried

Correction, with --ignore-scripts all the scripts are ignored and it makes sense that the dist is not present after install.

npm install --ignore-scripts puppeteer

This installs the package but without the /dist folder in the node modules.

Performing the same operation with john-wallace-dev's fork works as expected "lightweight-charts": "github:john-wallace-dev/lightweight-charts",

I wanted to know what could be going wrong here? Any help is appreciated.

HassanAhari commented 3 months ago
        chart.timeScale().subscribeVisibleLogicalRangeChange((timeRange: Range<number> | null) => {
          if (timeRange) {
            sub_chart?.timeScale().setVisibleLogicalRange(timeRange);
          }
        });

        sub_chart?.timeScale().subscribeVisibleLogicalRangeChange((timeRange: Range<number> | null) => {
          if (timeRange) {
            chart.timeScale().setVisibleLogicalRange(timeRange);
          }
        });
jamesbrobb commented 2 months ago

@rwitzlib were you able to fix this crosshair syncing issue (when scrolling either of the charts) with your implementation? This is demonstrated on the example chart in the trading view chart tutorials

https://github.com/tradingview/lightweight-charts/assets/1752245/dcd76571-89d6-460a-bfa5-57006b8cdf47

drgarlic commented 1 month ago

@jamesbrobb

charts.forEach(({ chart }, index) => {
  if (index < charts.length - 1) {
    chart.timeScale().applyOptions({
      visible: false,
    });
  }

  chart.timeScale().subscribeVisibleLogicalRangeChange((timeRange) => {
    charts.forEach(({ chart: _chart }, _index) => {
      if (timeRange && index !== _index) {
        _chart.timeScale().setVisibleLogicalRange(timeRange);
      }
    });
  });

  chart.subscribeCrosshairMove(({ time, sourceEvent }) => {
    // Don't override crosshair position from scroll event
    if (time && !sourceEvent) return;

    charts.forEach(({ chart: _chart, seriesList }, _index) => {
      const first = seriesList.at(0);

      if (first && index !== _index) {
        if (time) {
          _chart.setCrosshairPosition(NaN, time, first);
        } else {
          // No time when mouse goes outside the chart
          _chart.clearCrosshairPosition();
        }
      }
    });
  });
});
jamesbrobb commented 1 month ago

Thanks @drgarlic , appreciate the response.

I implemented a similar fix that i added here. It works, but the crosshairs sometimes get slightly out of sync when the charts are zoomed in.

drgarlic commented 1 month ago

Yep it's indeed broken ! Something weird is happening in the background

yooyea commented 1 day ago

5 years on, this issue still hasn't been implemented

kirchet commented 13 hours ago

@yooyea it's already implemented: https://github.com/tradingview/lightweight-charts/pull/1557

yooyea commented 13 hours ago

@yooyea it's already implemented: #1557

i see, docs not upgrade