hoffstadt / DearPyGui

Dear PyGui: A fast and powerful Graphical User Interface Toolkit for Python with minimal dependencies
https://dearpygui.readthedocs.io/en/latest/
MIT License
13.23k stars 688 forks source link

Precision Error When Calculating Minute Candle Series #2067

Open pattty847 opened 1 year ago

pattty847 commented 1 year ago

Version of Dear PyGui

Version: 1.8.0 Operating System: Fedora 37 Linux

My Issue/Question

While using a candle series with the time unit set to dpg.mvTimeUnit_Min there seems to be a precision error when calculating the width and spaces between each candle stick.

User: V-EIN found this:


Your dates are too large to be precisely represented in float variables in C++ code. They require about 32 bits of precision, whereas float only has 24 bits. Luckily, in most cases double type is used, which is way more precise. However, when width of the candle is calculated, dates are temporarily converted to float. For developers: I'm talking about this line in mvPlotting.cpp:

float half_width = count > 1 ? ((float)xs[1] - (float)xs[0]) * width_percent : width_percent;
    double x1 = 1678089480;
    double x2 = 1678089540;
    double d = x2 - x1;                    // d = 60.0
    float fd = (float)x2 - (float)x1;    // fd = 128.0

If you compute the distance between two neighbour dates in your data, you'll get 60 - but if you do the same using floats, you'll get 128 because floats lose some precision. That is, your candles will become more than twice wider than they are supposed to be!

As a workaround, I suggest you to try adding weight=0.1 or something like that on your add_candle_series call. It will make candles narrower. However, it does not remove the root issue of precision loss; your mileage will vary depending on what data you pass on X axis (but hey, since they're dates, they should mostly be within the same precision range for years to come).
[2:31 AM]
So as a TLDR: add weight=0.1 to add_candle_series and it should work for you in foreseeable future.
[2:32 AM]
And yes, open a ticket on GitHub. It's no good to lose precision on such data, given that it's always of the same order of magnitude.

To Reproduce

Steps to reproduce the behavior: Reconstruction: https://pastebin.com/zx8xFBUG Data for candle series: https://pastebin.com/0ysXNLfw Or go to my Discord support ticket: https://discord.com/channels/736279277242417272/1084477000850362400/1084477000850362400

Expected behavior

The candles should be properly spaced as they are on higher timeframes.

Screenshots/Video

umD64Nqh

Standalone, minimal, complete and verifiable example

import dearpygui.dearpygui as dpg

dpg.create_context()

with open("BTC_USD_1m.json", "r") as f:
    candles = json.load(f)
# Please use this link for the data: https://pastebin.com/0ysXNLfw

with dpg.window(label=exchange_name.upper(), tag="Primary Window"):
        with dpg.plot():
            dpg.add_plot_legend()

            xaxis_candles = dpg.add_plot_axis(dpg.mvXAxis, time=True)

            with dpg.plot_axis(dpg.mvYAxis, label="USD"):

                dpg.add_candle_series(
                    candles["dates"],
                    candles["opens"],
                    candles["closes"],
                    candles["lows"],
                    candles["highs"],
                    tag="candle_series",
                    time_unit=dpg.mvTimeUnit_Min,
                )

                dpg.fit_axis_data(dpg.top_container_stack())
                dpg.fit_axis_data(xaxis_candles)

dpg.create_viewport(title='Custom Title', width=600, height=200, x_pos=500, y_pos=500)
dpg.setup_dearpygui()
dpg.show_viewport()
dpg.set_primary_window("Primary Window", True)
dpg.start_dearpygui()
dpg.destroy_context()
sedenka commented 1 year ago

See #1847.