Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature Request: Alternative method to calculate bar widths #115

Closed
char101 opened this issue May 1, 2020 · 16 comments
Closed

Feature Request: Alternative method to calculate bar widths #115

char101 opened this issue May 1, 2020 · 16 comments
Labels
enhancement New feature or request released code merged into repo AND released to Pypi

Comments

@char101
Copy link

char101 commented May 1, 2020

Is your feature request related to a problem? Please describe.
In small charts, the volume bar (and maybe the candlestick bars too) are uneven because of the rounding of the fractional width values of the bars.

2020-05-01 12_13_58-Figure 1

Describe the solution you'd like
Alternatively I have modified it to use bar width = 1, and then adding edgecolors='the color of the background' (actually I just set it to 'k' because I'm using a dark style) and linewidth=1 for the volume panel. In my opinion the result looks better. The bar widths are still not uniform but the spacing looks uniform.

2020-05-01 12_14_28-Figure 1

diff --git a/src/mplfinance/plotting.py b/src/mplfinance/plotting.py
index 1f5382c..2dc7464 100644
--- a/src/mplfinance/plotting.py
+++ b/src/mplfinance/plotting.py
@@ -355,8 +355,8 @@ def plot( data, **kwargs ):
         vcolors = _updown_colors(vup, vdown, opens, closes, use_prev_close=style['marketcolors']['vcdopcod'])
         #-- print('len(vcolors),len(opens),len(closes)=',len(vcolors),len(opens),len(closes))
         #-- print('vcolors=',vcolors)
-        width = 0.5*avg_dist_between_points
-        ax2.bar(xdates,volumes,width=width,color=vcolors)
+        width = 1 # 0.8*avg_dist_between_points
+        ax2.bar(xdates,volumes,width=width,color=vcolors, edgecolor='k', linewidth=1)
         if config['set_ylim_panelB'] is None:
             miny = 0.3 * min(volumes)
             maxy = 1.1 * max(volumes)
@char101 char101 added the enhancement New feature or request label May 1, 2020
@char101
Copy link
Author

char101 commented May 1, 2020

2020-05-01 12_34_11-Figure 1

Using linewidth = 0.75 for both the candle bars and the volume bars results in uniform sharp 1px gap between the bars.

@DanielGoldfarb
Copy link
Collaborator

Can you please provide the data and code you used to make these plots. I want to be able to reproduce on my own system to better understand. Thank you.

@char101
Copy link
Author

char101 commented May 1, 2020

Hi,

Here is the sample code. Please note that the difference might not be visible if your monitor resolution is high. My monitor resolution is 1920x1080.

mpl.zip

Running main.py will open two plot windows

2020-05-01 18_37_44-Figure 2

As you can see the volume bars on the left has non-uniform widths, while the one on the right looks more uniform. I have only changed the bar widths on the volume bars. The same method can be implemented to the candle bars. There is a problem when implementing this with the candles though, since the edge is used as a padding, when the value of open == close, the candle will be invisible.

@DanielGoldfarb
Copy link
Collaborator

@char101 Charles,
Thanks. I will try to take a look into this within the next few days. All the best. --Daniel

@DanielGoldfarb
Copy link
Collaborator

@char101
Charles, I've been working on this for two days now. This issue is inherent to bar charts in matplotlib.

Your widths look nice on your chart. I found that the same widths may or may not look nice depending primarily on three things: (1) how much data there is, (2) how far apart the data is (intraday, daily, weekly, etc) and (3) whether or not show_nontrading is true.

I've come up with an algorithm that automatically adjusts the volume widths and candle widths for all of these things. I expect to enter a PR for it sometime in the next couple of days. If you want to test it, it is presently in my fork (please just keep in mind I will be making other changes to that code before the PR). Thanks. --Daniel

@char101
Copy link
Author

char101 commented May 20, 2020

Thank you Daniel for you work on this.

@DanielGoldfarb
Copy link
Collaborator

Charles, by the way, thanks for the excellent code here that quickly compares the two versions. When I was first developing my algorithm, I included it in that code as a third version to compare.

@char101
Copy link
Author

char101 commented May 20, 2020

Thanks Daniel, glad that it could help a little.

@Atekihcan
Copy link

@char101 Thanks for bringing this up. Just curious about how did you put the volume labels on right and price labels on the left in Y-axis. And how did you configure the volume label to be '10m', '20m' instead of default multipliers I get like 'x1e7'?

@Atekihcan
Copy link

I've come up with an algorithm that automatically adjusts the volume widths and candle widths for all of these things. I expect to enter a PR for it sometime in the next couple of days.

This sounds perfect, Daniel. I did some digging around the code and was thinking of something in the similar line. But if you have already done it, I'll wait for that.

Also I have faced another issue with candlestick wicks where the wicks looks like weird blotches when there are quiet a few candles, like the image below.
Figure_1

After some digging around, looked like this is related to anti-aliasing and after I enabled AA, it looks like below. Which is what I was looking for. The candles look a bit blurred with AA enabled but I prefer that over the blotched ones.

Figure_2

Let me know if this is something you want to incorporate then I can create a PR. Added it as a completely optional parameter which does not change the default behavior.

Note: The second image has a few more changes than just AA. However, the changes in candle appearance is solely due to enabling AA.

  • It has changes made by @char101 for volume bars
  • set_axisbelow(True) for all plots instead of just volume bars
  • Configurable xtick rotation

Thanks for maintaining this awesome module!

@char101
Copy link
Author

char101 commented Jun 4, 2020

To move label position: ax.yaxis.tick_left() or ax.yaxis.tick_right().

To customize the label you need to set your own label formatter ax.yaxis.set_major_formatter(FuncFormatter(your_function)).

@DanielGoldfarb
Copy link
Collaborator

DanielGoldfarb commented Jun 5, 2020

@Atekihcan ,
Regarding,

Also I have faced another issue with candlestick wicks where the wicks looks like weird blotches when there are quiet a few candles

Have you tried the new code in my fork?

The automatic candle width adjustment adjust wicks also (and the volume bars).

I know I mentioned above, over two weeks ago, that the PR to bring in the new self-adjusting code would be in a few days, however due to unforseen circumstances, unrelated to this project, that was delayed. Hopefully next week.

In the meantime, if you want, you can install the code from my fork. The code is ready; I am just putting the finishing touches on the documentation for the new features.

If you do get a chance to test the new code, please let me know if it works for you. I suspect you will find the automatic adjustments adequate (for candles, wicks, and volume bars) and will not need to include any code (AA or otherwise) outside of mplfinance; but let me know.

Also, fyi, the new code includes kwarg xrotation for mpf.plot() to control the rotation of the x-axis labels. (The default rotation is 45 degrees).

Also, with the existing release, v0.12.4a0, you already can control whether the y-axis is on the left or right using styles by setting kwarg y_on_right=True in function mpf.make_mpf_style()

@Atekihcan
Copy link

Have you tried the new code in my fork?
...

Thanks for the suggestion. Your changes work well enough. No need to tinker with AA or otherwise.
daniel
Only two minor issue that I have noticed...

  • The grid lines appear above the candles. This is present in v0.12.4a0 as well. It's not a big deal as I can return the axis and do set_axisbelow(True) for wherever intended. I noticed that you are doing it only for volume bars, maybe you can do that for all axes? Unless of course you have some other reasoning.
  • This one is a minor nitpick. Some candles have the wick a little offset from the center. Compare 2nd and 4th candle from the left in the above image. 2nd one has wick one pixel left of center but 4th one is exactly at center. If you zoom into the image it'll be more prominent. I'm guessing this is due to approximate pixel width of the candles not being exactly same (some odd number of pixels to be precise). However this does not show up when you zoom the popup figure opened by mpf.plot(). Only with saved images. Reporting just in case this has something to do with how widths of candles are being calculated. It looked like you have used some kind of heuristics to settle on that.

Also, fyi, the new code includes kwarg xrotation for mpf.plot() to control the rotation of the x-axis labels. (The default rotation is 45 degrees).

Awesome! 👍

Also, with the existing release, v0.12.4a0, you already can control whether the y-axis is on the left or right using styles by setting kwarg y_on_right=True in function mpf.make_mpf_style()

Yes. This I was aware of. I wanted to know how to put price label on the right and volume label on the left.

@DanielGoldfarb
Copy link
Collaborator

@Atekihcan ,

Thanks for beta testing the code. Much appreciated and thanks for the feedback.

Regarding set_axisbelow(True), I like the idea. I will run it through a bunch of test cases and if it appears to have no negative results then I will likely make it the default (and perhaps add a kwarg to provide access to the setting).

Regarding the wicks sometimes being off center, this will probably take a good amount of investigation. Your guess as to reason(s) behind this phenomenon seem to me to be a good place to start an investigation.

As you saw, the width-adjustment algorithm uses a heuristic approach, since it is extremely difficult to determine exactly how the appearance of the various plot elements will be affected by the input data and selected options. I simply spent a full day playing with a lot of different data sets, and a lot of different width and linewidth settings, eye-balling what I thought looked "pretty good" on my screen.

You may have noticed that I have provided a width_adjuster_version kwarg in anticipation of improving and/or providing alternative algorithms in the future (and allowing people to choose an "older" and/or non-default algorithm if they prefer). In the meantime, since you mentioned the non-centered candle-wick issue appears to affect predominantly saved figures, you can try increasing the size of the saved figure (using the figscale kwarg) and/or adjusting the dpi in the savefig dict.

to put price label on the right and volume label on the left.

Hmm. Perhaps in a future version we can allow left/right label control on a per-panel basis.

All the best. --Daniel

@Atekihcan
Copy link

Thanks for beta testing the code. Much appreciated and thanks for the feedback.

No problem 👍

Regarding set_axisbelow(True), I like the idea. I will run it through a bunch of test cases and if it appears to have no negative results then I will likely make it the default (and perhaps add a kwarg to provide access to the setting).

It'd be great if it can be made default. There is no issues with plots in notebook, with getting the axes list and doing it myself. But that doesn't work if I'm saving the figure as the figure is saved before I'm doing that.

Regarding the wicks sometimes being off center, ... eye-balling what I thought looked "pretty good" on my screen.

You may have noticed that I have provided a width_adjuster_version kwarg in anticipation of improving and/or providing alternative algorithms in the future (and allowing people to choose an "older" and/or non-default algorithm if they prefer). In the meantime, since you mentioned the non-centered candle-wick issue appears to affect predominantly saved figures, you can try increasing the size of the saved figure (using the figscale kwarg) and/or adjusting the dpi in the savefig dict.

Yeah, it depends a lot on many other factors like DPI, screen resolution, figure size etc. If I get some time, I'll see if I can spend some time on it.

@DanielGoldfarb
Copy link
Collaborator

new version 0.12.5 just released to Pypi has new algorithm for calculating widths of candles, wicks, volume bars, and ohlc bars and ticks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request released code merged into repo AND released to Pypi
Projects
None yet
Development

No branches or pull requests

3 participants