Open sergproua opened 3 years ago
SegmentedTimeline
is gone, but the Timeline
interface remains; you can write your own implementation using the original as a guide, although it is "(a) complex, (b) not always…correct." This example illustrates one way to let the user control an anomaly that arises while panning.
Hi Sergproua, I copied previous version of SegmentedTimeLine and it works. I'm using jfree for financial markets, so it was top prio for me. In any cases, SegmentedTimeLine and DateAxis is wrong solution for financial markets, because financial platform cannot use directly DateAxis as x-axis. It has to be indexed (category type) axis and time date has to be mapped to this axis. If you use date time (not indexes) the zooming not work correctly, sliding do not work correctly, etc. In the main principle, it is wrong approach and it has to be realized by described way.
Thank you both for a quick reply. I'm wondering if it'll be easier to ditch DateAxis and
DateAxis really is just a type of NumberAxis where (a) the scale is "milliseconds since 1-Jan-1970" and (b) the axis labels are converted from those numbers into date strings. That approach works fine for non-segmented axes. The complications arise when trying to exclude segments of the timeline - typically weekends and holidays, but if you zoom in on a date axis you might also want to consider excluding non-trading hours if you are working in a financial markets context (or non-manufacturing hours if, for example, you are measuring quality statistics on a continuous basis in a factory setting - so perhaps the idea is general, we could just call it opening and closing times).
A key job of the axis is to translate an arbitrary data point (say 6:44am, Saturday 19-Dec-2020) to a point along the axis for display on the chart. If the axis is segmented, it could be that this translated point is the same as 6pm, Friday 18-Dec-2020. How do we determine this translation point. My idea (I've never really had time to dig deeply into it) would be to construct an ordered tree of non-overlapping "segments" to represent the complete range of the date axis (so the segments need to be non-overlapping and adjacent). Each segment is either included or excluded according to rules (weekend and holiday schedules for example). For a given data point, search the tree for the segment into which the data point falls (the tree structure is just to make this search more efficient - you could use an ordered list if you didn't care about it being fast). Once you know the segment there are two cases: (a) the segment is included, so the data point should be displayed within the range that segment occupies in the chart / screen space (this is also an implementation challenge, since this depends on all the prior segments - I have a hunch that the tree structure could help here too) or (b) the segment is excluded, so the data point should be either (user choice here) excluded or displayed at the end of the previous "included" segment or the start of the next "included" segment depending on which is closer.
To handle zooming across large ranges (the user might display decades of data, in which case having daily segments would get slow, or they might zoom into a single day in which case you could potentially need to switch to segments based on start and end times (open hours vs closed hours) I would suggest that multiple segmentation levels would be a useful feature - not sure what would be the trigger for switching levels. Maybe that's an extension that could be added after.
Anyway, that's just some thoughts. Maybe at some point I will find some time to work on that, or maybe the above gives someone some ideas to run with.
The workaround in the mean time is exactly what trashgod proposes - grab the existing SegmentedTimeline code and incorporate it in your application.
In my opinion, it's complicated, will be slow, and not necessary. Each OHLC, indicator and element in financial charting have same index. This index is calculated per bar. The bar close time is stored with these indexes too. So, the x-axis values are these indexes, not time. But the index cannot be shown in the x-axis. There is necessary sophisticated visualization of date time and possibility to aggregate time if you are unzoom. So, it is still look like as time, but under it there are indexes, categorized style. If you are used time, not index, there are several problems between two points of ohlc, there is still time gap, which technically doesn't exist. There are several next problems. The key cannot be a time. But the visualization, grouping and showing of x-axis has to be a time. It is like "TimeIndexedAxis".
Open/High/Low/Close (OHLC) is already a special case because each data point implicitly represents one included segment (the time range between the opening time and closing time) - so in this case your data values are already constrained, so you are right, you can just use indices for each data item (weekends and holidays would automatically be excluded. Then you simply need a mechanism to convert the indices to date labels on the axis. Perhaps a special OHLC axis that is allowed to "peek" at the dataset?
It's not just for ohlc, it is used for all elements, indicators (moving averages, macd, rsi,...) which can use this hidden indices technique. The main trick is that the key are still indices, because the dataset data are without weekends, holidays, etc. In addition, all is calculated and based on the indexed timestamps. But finally, the datetime x-axis is necessary for user orientation. The principle is not so easy, because it is not just showing datetime as labels. If you zoom or unzoom there is still good to have grouping to higher or lower datetime mechanics like hours to days, days to months, or seconds to minutes. Depends on intraday or EOD processing. I understand that the problem is moved to tick names and no so simple. I know. But all next problems are solved, and it is still tick names visualization only. There is example from amibroker for some basic handling of fin.charts: Amibroker example
I ended up creating my own PriceTime data structure for all financial calculations, and only last minute translating to OHLC series just for displaying, There is just so much going on in OHLC series (all kinds of DST and timezone checks and I found it caused more problems around dst changes). I designed and implementend my own Timeline per official suggestion. This was a difficult task, imagining and drawing the principle and keeping the indexing in check, But I got it to work. See it work here : https://youtu.be/HJerIObC838
Unaware of this thread, in 2020 I wanted a simpler way to create complex jfreechart plots. This included removing OHLC weekend gaps.
Inspired by a 2009 forum post, I dove in aiming to leverage and extend all I could in jfreechart without modifying jfreechart itself.
This initially produced many classes so I then made a facade backed by a factory pattern for ease of consumption.
Then I wanted to decorate charts with other time series indicators, annotations, and sub-plots ... also without time gaps and aligning data points of different plots.
So I switched to a builder pattern and in November 2020 created the jfreechart-builder project to share the solution. Time gaps were removed by v1.5.3. See its showTimeGaps()
parameter.
It maps time series values to linear integer indices. Some new drawing logic was also needed. Weekend gaps are effectively “squashed” into the next data index. It works well for my purposes and for me was “good enough”, but I’ll note it’s not perfect (see the open issues as of this writing).
See these classes and their use in the current latest version (v1.5.6):
The renderer was inspired by jfreechart itself.
I did not test jfreechart-builder with anything other than daily OHLC data.
I hope developers find it useful or that it inspires their own solutions. If you think you can improve jfreechart-builder I’d be happy to accept pull requests, or if it's worth it, it could one day become part of jfreechart.
Best of luck!
@matoos32 Like your library very much. Your API allows to add simply annotations, but how do you add something like XYLineAnnotation, which require two x and y values? Adding those directly to the XYPlot obviously doesn't work when we disable gaps. If not possible, what would be a workaround?
Hi @jcobb88 thanks for the kind feedback. I started a discussion about other annotation types here https://github.com/matoos32/jfreechart-builder/discussions/42
@matoos32 thanks for the update. Using the timearray indices works very well in the meantime. I also found that simply updating the dataset via the XYPlot#setDataset does not work as well. I my case I wanted to update my chart bar by bar without reloading a jframe. Although the yaxis changes according to the new bars, new annotations are not drawn at the correct yaxis/price levels. Is there any interpolation on the y axis as well?
Again, if i change the dataset the chart updates correctly (the axes as well as the bars are drawn/adapted correctly). But applying a new e.g. XYLineAnnotation to the plot seems to work on the old dataset or is drawn at some odd price levels that do not correspond to the new dataset.
Hi @jcobb88 I don't know about any interpolation.
Are you sure you're using correct indices and price values in the new XYLineAnnotation?
I suggest moving all jfreechart-builder discussion into its discussion area, or creating a bug issue with code snippet in its repo.
Looking for ways to exclude weekends and holidays on DateAxis so that there's no gaps which also take a lot of space.