mindok / contex

Charting and graphing library for Elixir
https://contex-charts.org/
MIT License
710 stars 56 forks source link

OHLC Candlestick chart #87

Open DaTrader opened 11 months ago

DaTrader commented 11 months ago

The following are suggestions regarding the candlestick chart input and looks

Input

The following input should be specified at the chart level (not for each candle)

  1. Symbol
  2. Timeframe

The timeframe is particularly important because one needs to know if there are candles missing (when there was no market activity e.g. over a weekend or a holiday) and the chart itself may choose to present those as the so called flat (or empty) bars/candles. Those are typically just horizontal lines as wide as the candle body + border and they inherit the value of the preceding close (so they look as a sequence of dashes). Unfortunately, very few charting tools support this but it's a very useful feature because without it the time axis has missing chunks in it and any time-dependent indicator (e.g. trendlines) is therefore distorted.

Timeframe is typically specified as a positive integer. Seconds or minutes can be used for units. If using minutes, a daily chart would be 1440, a weekly 10080 and monthly would be approximated at 43200.

Colors

Candle "shadows" are the vertical lines outside the body i.e. high - max( open, close) and min( open, close) - low.

Width and spacing

For the width and spacing I believe it's best to try to get as close as possible to how they are presented on the MT4 platform (which in my view, still has the best UI despite all other "professional" platforms out there).

As a reference MT4 has 6 zoom levels each featuring its own candle/bar width and spacing:

  1. (fully zoomed out) candles are presented as single color (border color) vertical lines from high to low, without any spacing between them
  2. same as 1 but with single pixel spacing
  3. body width: 1 pixel + border, spacing: 1 pixel
  4. body width: 3 pixels + border, spacing: 3 pixels
  5. body width: 9 pixels + border, spacing: 5 pixels
  6. (fully zoomed in) body width: 23 pixels + border, spacing: 7 pixels

Body and shadow lines are always 1 pixel wide.

Note that the zoom levels 1 and 2 typically assume the border color and not the bull/bear body color, so if choosing to support coloring them according to their bull/bear body direction then it's best to make it optional (a sequence of bull color/bear color vertical lines has little informative value but the changes in colors make it more difficult to see the big picture).

Optimizations

DaTrader commented 11 months ago

UPDATE

When there are too few data points the chart looks weird if those are stretched/justified from left to right.

I would add an additional requirement to make it optional so that a fixed widths/spacings mode is supported too (candlesticks need just the left alignment, but other charts may benefit from right aligned and centered too).

DaTrader commented 11 months ago

@mindok I'm now looking at your code and am holding myself from starting to apply the said improvements :)

Please drop me a note when you think you've reached the initial planned completeness of your code in ohlc.ex so I can start adding stuff on top of that without fear of creating diverging/irreconcilable differences in my branch.

Also, I believe this should be a coordinated effort, so please let me know of what you think of my suggestions. If you find any of those inapplicable or out of scope I would then implement just the ones we agree on and isolate the others (if any) in my own fork only.

mindok commented 11 months ago

Hi @DaTrader - I have had a family emergency come up and won't be at the keyboard for a couple of days. The only thing I was going to do was ensure all the tests work and maybe add a couple of tests for this new chart type, so that's probably ok to leave to the end anyway.

I am happy with all your suggestions - I'm a total amateur when it comes to trading related charts, so your input into detailed requirements / design is valued! Hopefully you have enough of a start (e.g. seeing how options are set, SVG drawing etc) to keep it moving.

One thing with the timeframes - there are a couple of approaches for handling this. The "flat bar" logic (i.e. looking for gaps in the data and setting open/high/low/close to previous close) could be handled externally from the chart itself in the data pre-processing. This would keep the chart rendering logic more simple, but I'm open to arguments for handling it within the chart. Also, are there circumstances where you wouldn't want gaps for non-trading days? If so, it could be handled by a custom timescale implementation or an "ordinal" type scale.

DaTrader commented 11 months ago

The only thing I was going to do was ensure all the tests work and maybe add a couple of tests for this new chart type, so that's probably ok to leave to the end anyway.

I believe you should first make the tests pass and merge the branch into master so that there's a first functioning version. The changes I am going to apply are substantial so it's better to go gradually with it (small steps and ensure it all works at each step before adding new stuff). Your site fairly warns everyone of a high probability of breaking changes so it's all cool.

I am happy with all your suggestions

Great!

Hopefully you have enough of a start (e.g. seeing how options are set, SVG drawing etc) to keep it moving.

Yes, by what I've seen it should be enough.

The "flat bar" logic (i.e. looking for gaps in the data and setting open/high/low/close to previous close) could be handled externally from the chart itself in the data pre-processing .. Also, are there circumstances where you wouldn't want gaps for non-trading days? If so, it could be handled by a custom timescale implementation or an "ordinal" type scale.

In some configurations displaying flat bars is not desirable. For example, when analyzing just the absolute price levels or applying lagging indicators (MA, RSI and friends) on lower timeframes where there would be many flat bars in a sequence. It is therefore best to keep this particular setting optional and chart-based rather than having the user pre-process the input.

DaTrader commented 11 months ago

Another thing.. I've seen you mention LiveView list handling inefficiencies as a reason for not going all-in with a dynamic LV-based chart updates.. I know pretty well what you mean there but that problem has been solved in the meantime. As you probably know, there are now LV streams that handle this nicely. I'm using them (the LV streams) extensively on work and I believe they can cope with large amounts of candles (as in easily thousands).

But this kind of enhancement I would add only after the basic feature set is implemented with the current static SVG rendering.

DaTrader commented 10 months ago

@mindok Just letting you know I've started working on it in the meantime, so we'll leave the tests for later. Ok?