tradingview / lightweight-charts

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

Plot two axes for same chart #1493

Closed antter closed 9 months ago

antter commented 9 months ago

Hi! New user here, thanks for maintaining this package.

Is your feature request related to a problem? Please describe.

I would like to plot two axes for the same chart. One represents the price, and the other is some non-linear (but still monotically increasing) function of price. Some metric of price that is useful to our customers. An example in the chartjs library is here. I'm attaching a screenshot so its clear what the feature is.

Screen Shot 2024-01-10 at 2 19 21 PM

Describe the solution you'd like

Not sure what the ideal way to go about this is, but maybe a way to set a "mirror" arg and a PriceFormatterFn?

Maybe something like

chart.priceScale('left'}.applyOptions({
    mirror: 'right',
    format: MyPriceFormatter
})

Looking through the source, it's hard to tell how difficult this is to implement, and what other quirks may arise but I have some progress going on a fork. Let me know if this is something you guys are interested in, I could make a PR if I figure this out.

As far as I can tell this isn't possible with a plugin? A plugin does not allow you to mess with the Axes from what I can see.

antter commented 9 months ago

Also note in the example I provided the ticks are different. For my use case they don't need to be, and it removes a lot of the complexity.

SlicedSilver commented 9 months ago

I think this example is what you are looking for: Two Price Scales | Lightweight Charts

A plugin does not allow you to mess with the Axes from what I can see.

You can use a plugin to implement a completely new axis. As you can see on this simple example, it is possible to draw anything you want, however re-implementing a price scale in a new plugin wouldn't be the quickest task.

There is also this somewhat similar plugin example of how to create a price scale which appears above the chart: Lightweight Charts - Overlay Price Scale Plugin Example

antter commented 9 months ago

Thanks for the response. It is nice to know I was wrong about not being able to use a plugin to implement a new axis.

The two price scales examples isn't exactly what I'm looking for because each dataset is only attached to one price scale. I briefly thought about making two LineSeries with the same data but different formatting but figured that wouldn't work too well for other reasons. I want to only show one line on the graph. Let me know if I'm misunderstanding that about price scale. Otherwise, I can close and make this as a plugin.

antter commented 9 months ago

Ahh looking at it it really may be easier to just continue working on a fork than implementing another price scale. The difficulty is that I don't know where the PriceMarks are on the right side, and it would be difficult to coordinate between both scales. Further I do want them to look similar so it would essentially be me copying as much as I can from PriceAxisWidget. Also the cool crosshair feature that highlights what the current price is at on the scale.

EDIT: okay so far just graphing two line series with the same data on the left and right and applying a formatting to only one of them doesn't look like it has any negative side effects. Maybe a bit annoying to work with and if it causes performance issues, my datasets are probably not large enough for that.

ANOTHER EDIT: okay, definitely has negative side effects. might be possible to handle them case by case but fork would likely be the easiest thing here

SlicedSilver commented 9 months ago

Do you have a screenshot of what you are trying to achieve? I assume that the screenshot in the first message isn't exactly what you are looking to implement.

You could fork, but if you are certain that the library doesn't support your specific requirements and you have an example on a different library which does work already then wouldn't it be easier to use that other library? My concern with a fork is that you will need to maintain it if you want to get new updates in the future. Plugins are a better solution if you can rather do it that way because you will be able to easily update LWC versions in the future.

antter commented 9 months ago

Unfortunately I do not have a screenshot but I can describe my use case. The screenshot above, albeit kind of silly is actually a decent depiction of what I want to achieve: one set of data, two different "formatters". I am plotting gambling odds across different sportsbooks to see if one can find an edge by placing bets on different books. Each sportsbook is a line series. So we are not exactly working with financial data.

Idk if you're familiar, but american odds can look like +400, -400. A probability value can be associated with these odds. Here is a table of some values.

American Odds Implied Probability (%)
-1000 90.91
-500 83.33
-200 66.67
+100 50.00
+200 33.33
+500 16.67
+1000 9.09

You can see the scale is nonlinear, and the american odds explode at high/low values of implied probability. Implied probability is really what should be charted, as it corresponds linearly with a gamblers expected value and the values near 1 and 0 do not dwarf all the values in the middle. Two books having a discrepancy of -4000 vs -8000 is not that large; -200 to -600 is quite a massive one though. Charting with american odds on the Y axis just doesn't make much sense.

However sports gamblers who are our end users are quite used to the american odds, and it is important to display the american odds. What we currently do in my prototype is chart implied probability and use a formatter to convert to american odds. But ideally I would want to show both values, with the probability using the other axis. This is the best way to analytically process a discrepancy across books without the user having to do any quick math. It would be the same data, same tick mark locations, just a different formatter.

And yes, it would be easier to use Chartjs for this use case, but our team is going to be making lots of time series charts and we rather like the out of the box features and the UI of this library. Maintaining a fork is indeed a pain which is why I would like to contribute if there is interest in adding this feature. However I understand our use case is nonstandard although I can imagine there is use for showing two metrics of the same data in financial charting as well.

SlicedSilver commented 9 months ago

If I understand your goal correctly, you can achieve it by using two different line series and two different price scales.

Plot the exact same data for both line series and assign one series to the left price scale and the other to the right price scale. This will make the lines overlap and appear as a single line. Then, apply a different price formatter to one of the scales to display the numbers differently. Finally, disable the user's ability to manually scale or shift the price scale, ensuring that the lines always stay on top of each other. The resulting chart will resemble this: https://codesandbox.io/p/sandbox/lwc-mirror-price-scales-js5lxg

antter commented 9 months ago

Sorry for the late response. That is what I was experimenting with but I am not a big fan of disabling scaling/shifting. I was able to get decent results on a fork. Let me know if this could be something you're interested in integrating and I can clean it up and open a PR.

SlicedSilver commented 9 months ago

If you've got a working fork then we would be interested in having a look. 😊

One of our main concerns with new features, or improvements, is the effect on the bundle size of the library. If the change in bundle size is minimal then it is something that could be merged into the library.

You can check the size with the following commands:

npm run clean

npm run build:prod

npm run size-limit
antter commented 9 months ago

sweet! thanks for your quick responses, and you may see a PR from me soon.