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

Implement y-scale (ex: log) #21

Closed
starovp opened this issue Jan 29, 2020 · 15 comments
Closed

Implement y-scale (ex: log) #21

starovp opened this issue Jan 29, 2020 · 15 comments
Labels
enhancement New feature or request released code merged into repo AND released to Pypi

Comments

@starovp
Copy link

starovp commented Jan 29, 2020

Hi Daniel, thanks for helping to develop this library. I was wondering if it'll be (or already is) possible to manipulate the resulting charts much like matplotlib charts, for example:

  • changing the y-scale
  • changing major/minor x-ticks
  • setting chart titles and legends

I'd love to be able to do this with the existing charts. Let me know if I can help. Thanks!

@starovp starovp added the question Further information is requested label Jan 29, 2020
@schorschie
Copy link

+1

@DanielGoldfarb
Copy link
Collaborator

Philipp- Thanks for your words of appreciation. Regarding "setting chart titles and legends" ... Chart title and axis titles are part of a large set of enhancements that I hope to release by the end of this week, or early next week. Legends perhaps the next release after that.

Regarding changing y-scale and/or x-ticks, can you please provide an example where you would find it desireable to do this, either code, or screen shots with and without these abilities, or screen shots with a description of how you would make it appear if these abilities were available in mpf.plot()

Regarding help, as mentioned I am at the tail end (testing and final tweaks) of a relatively large set of enhancements, with some restructuring of the code, but after that, help will be definitely appreciated.

In the meantime, if you have time, please take a look at my comments on this issue to get some feel for the philosophy behind the new api and why some functionality is limited. I am certainly open to discussion about how to provide the best balance between detailed control over matplotlib "primitives" and an easy-to-use higher-level interface that allows users to focus mostly on their own analysis of financial markets. Greater flexibility often means more complex code, and it is important to me to implement things in a way that keeps the code easily maintainable, while still providing a significant amount of "automatic" stuff to keep things simple for the average user. That said, with the project's priorities in mind, nothing is out of the question.

@starovp
Copy link
Author

starovp commented Feb 1, 2020

I see. I'm looking forward to the enhancement release then 😄

As far as yscale goes, often it's beneficial to have a log scale. For example, if we pulled the chart for $SPY for the last 3 months and $AMD over the same time period, it would appear they moved in a similar manner. However, $AMD moved from $34 -> $50 over the same time period as $SPY moved $305 -> $325. The charts are accurate, but when compared side-by-side can be misleading. Therefore it would help to be able to log-scale the charts - this would enable users to see percentage moves.
3mos-spy-2020-01-28
3mos-amd-2020-01-28

I imagine it would be implemented similar to how it already is in matplotlib; whereas matplotlib defines it as a function of the axis, in a similar way I don't see why we couldn't implement it as a function of an mpf plot like so:

# matplotlib way
ax.set_yscale('log')
# proposed way
mpf.plot(df, type='candle', no_xgaps=True, savefig=save, set_yscale='log')

Some sort of settings dict like what's already in use for save settings could also be used.

I do understand the philosophy however and can certainly respect it; I'd much rather have cleaner code. Again, thank you for your work on this library.

@DanielGoldfarb
Copy link
Collaborator

@starovp Philipp- Thanks for taking the time to explain clearly what you want. That is definitly reasonable, and should be relatively easy to implement as you have indicated, or in a somewhat similar way. I say "or in a somewhat similar way" because with the next release, there will be four Y-axes available (two panels: main and lower, and a primary and secondary Y-axis for each). So we would just have to have a way to indicate which of the four y-axis you want to scale differently. Thanks.

@DanielGoldfarb DanielGoldfarb changed the title Basic matplotlib features? Implement y-scale (ex: log), and legends Mar 5, 2020
@DanielGoldfarb DanielGoldfarb added the enhancement New feature or request label Mar 5, 2020
@DanielGoldfarb
Copy link
Collaborator

  • want to implement y-scale, and legends.

  • not sure if I want to implement changing major/minor x-ticks. It may undesirably complicate existing x-axis handling (especially with regard to show_nontrading kwarg). I am not ruling it out, but presently I am inclined not to provide control of major/minor x-ticks. (We'll see over time if others also request and/or clamor for it).

@zhigeng
Copy link

zhigeng commented Mar 8, 2020

Hi Daniel, thank you very much for your work! I just started to plot candle sticks using this new library and I find it amazing! To add on to what OP @starovp request about modifying x-ticks, I personally find it useful to have some level of control over the x-ticks.

For example, in the following 5 mins intraday candlestick chart, I would like to maybe include more x-ticks in the chart, I probably want the x-ticks to include the start of every hour for convenience. And I may also want to rotate the x-ticks to 90 degree if there are too many x-ticks in the x-axis. In the current plot (see below), there are only 5 x-ticks and they do not align well with the start of a new hour.

Again, what your currently have for us is already amazing. This x-axis control is just another nice feature to have.

Thanks again for your work! I really like this library!

Thanks, ZG

plot1

@DanielGoldfarb
Copy link
Collaborator

DanielGoldfarb commented Mar 9, 2020

@zhigeng

ZG- Thanks for participating in the discussion, and I especially appreciate that you provided a specific example; it is definitely helpful to have a particular use-case for understanding the need or desire for a feature.

Allowing rotation of the axis labels is trivial; can do that. Presently it is hard-coded to 45 degress. We can make that the default and create a kwarg for it.

Regarding placement of the ticks, the issue is this: The default (based on some comments/requests from people) for show_nontrading is False (see README.md for examples).

In matplotlib, as far as I know, there is only one practical way to implement a feature similar to show_nontrading=False, that is removing gaps along the x-axis for non-trading periods (or removing gaps for an otherwise evenly spaced, linear x-axes, for which some x and y data is missing).

The way we implemented that is by setting the actual x-axis values to a simple range of integers, equal in length to the number of data points. Then we give matplotlib a special x-axis formatting function which effectively maps the integer to a specific date. (You can see the code here).

I am not very experienced with customizing tick placement, so I don't know, would have to investigate, if it is possible to create a similar mapping function for determination of x-tick locations. Doing that, it seems to me, would be needed in order to have ticks on 5 minute boundaries, or every Monday, etc., when the actual x-axis values are a simple range of integers. (If you are comfortable enough with Python and Matplotlib, perhaps you can investigate; I don't think I would get to it for several weeks or months; trying to get some other enhancements out).

Alternatively, and I'm a little reluctant to do this because it is a bit kludgy, we could maybe allow manipulation of the x-ticks if and only if the caller sets show_nontrading=True. That would work for your specific example, in fact for any "intraday data within only one trading day", because there are no non-trading periods.

(When there are no non-trading periods, then the plot looks the same for show_nontrading=True and show_nontrading=False, which means it is possible to pass actual datetime values to matplotlib for the x-axis values, which then allows us to ask matplotlib to set the ticks on 5 minute boundarys, or Mondays, etc.)

Finally, on a separate topic, I would like to confirm if the image you posted here was indeed created with mplfinance? I am looking for examples of user plots (other than my own) that I may be able to use as examples in a talk I am perparing for a couple of Python conferences this year.

Thanks. All the best. --Daniel

@zhigeng
Copy link

zhigeng commented Mar 10, 2020

Hi Daniel:
Thank you very much for your reply! Really appreciate your time! I think the x-ticks is not a super urgent feature for me. I can live without it. But may I ask another question, is there a way that I could possible include one or two more x-ticks along the x-axis? Currently I only see 5 in my plot and I would like to have more for easy reading. It a little inconvenient for me if I would to find out the exact time of a candle in the chart.

For your other comments, I will try to put in my 2 cents.

Allowing rotation of the axis labels is trivial; can do that. Presently it is hard-coded to 45 degress. We can make that the default and create a kwarg for it.

The rotation is only needed when we have a few more x-tick labels along the x-axis and when the x-axis becomes crowded. But if it is easy to implement, it would be nice to have as well.

The default (based on some comments/requests from people) for show_nontrading is False

I think this makes a lot of sense.

Alternatively, and I'm a little reluctant to do this because it is a bit kludgy, we could maybe allow manipulation of the x-ticks if and only if the caller sets show_nontrading=True.

I personally do not like this idea as well. Because who knows maybe one day I would like to include 3 days worth of intraday data in one single plot.

For your paragraph 4 and 5 about the implementation logic, I wish I know more about matplotlib to fully understand your reasoning. I am really sorry but I do not fully understand why the xticks function is not working here.

As for the image, yes, it was plotted using mplfinance. I just started to learn about mplfinance yesterday and that image was the first few images I plotted using mplfinance. This package is easy to use and there is no learning curve at all. It really saved my time! It is not the best looking imagine I have plotted using mplfinance. Please give me a few more days and I promise I will provide a better looking image to you.

Again, thank you very much for your work! Appreciate it!

Thanks,
ZG

@char101
Copy link

char101 commented Apr 29, 2020

Note for anyone that want to change the y-scale into log and want to use non-scientific notation, you also need to set the minor formatter

import mplfinance as mpf
import matplotlib.ticker as ticker

fig, axlist = mpf.plot(..., returnfig=True)

ax1 = axlist[0]
ax1.set_yscale('log')
ax1.yaxis.set_major_formatter(ticker.FuncFormatter(format_price))
ax1.yaxis.set_minor_formatter(ticker.FuncFormatter(format_price))

@char101
Copy link

char101 commented Apr 29, 2020

Unfortunately when the price variation falls between e.g. 1400 - 1200, there isn't even a ticker on the y-axis

ABMM

@DanielGoldfarb DanielGoldfarb changed the title Implement y-scale (ex: log), and legends Implement y-scale (ex: log) May 11, 2020
@DanielGoldfarb
Copy link
Collaborator

legends will be on a separate issue. this issue for tracking yscale

@DanielGoldfarb
Copy link
Collaborator

DanielGoldfarb commented Jun 12, 2020

@char101
Charles,
Being as several people already have benefited from your solutions to log scale and formatting the y-axis labels in non-scientific notation (#21, #138, #169), I humbly ask, would you be willing to contribute the solution to the source code of mplfinance?

What I have in mind is adding two kwargs: yscale, and yformat.

yscale would of course default to 'linear' (but could be set to 'log', 'symlog', 'logit').

yformat of course could be set to a formatter object, but ideally it should accept primarily a string: The string would either be a format string itself (such as "%.2f" for example), or could be the name of a standard formatter to use (for example 'ScalerFormatter'). This is in keeping with the mplfinance philosphy of providing an interface that allows most mplfinance users to not need to import or use anything from matplotlib directly (while allowing more advanced users to do so if they choose, for example by directly passing in a formatter object).

Also, ideally it should be possible to pass either or both of the two kwargs yscale and yformat into either mpf.plot() and/or mpf.make_addplot().

Please let me know if making this enhancement is interesting to you.
Clearly it would benefit many users.

Thank you. All the best. --Daniel

@char101
Copy link

char101 commented Jun 12, 2020

Hi @DanielGoldfarb ,

I am sorry but I am not currently using mplfinance at the moment. I end up creating charts from scratch using matplotlib while "borrowing" code from mplfinance, especially the code to create the collections. I choose to create the charts from scratch since I want to try various options not covered by mplfinance.

As for yformat I would like to suggest that is could be either (1) an object, which is an instance of matplotlib Formatter or its subclasses, (2) a function, which will be passed to FuncFormatter, or (3) a string, which will be passed to StrFormatter.

Also, using a classname as string like ScalarFormatter does not work well with static analyzer.

@DanielGoldfarb
Copy link
Collaborator

Thanks @char101 for the quick response. And for your advice about yformat. Much appreciated.

And thank you again for all of your contributions to discussions in this repository, and for suggestions on improving the code, all of which were very good and helpful. I really appreciate that very much.

All the best. --Daniel

@char101
Copy link

char101 commented Jun 13, 2020

Thank you Daniel for maintaining mplfinance. It is very helpful when we need to create financial charts quickly or when learning how to create it using matplotlib API.

DanielGoldfarb added a commit that referenced this issue Feb 24, 2021
@DanielGoldfarb DanielGoldfarb added merged / awaiting release to pypi code merged into repo, but not yet released to Pypi and removed question Further information is requested labels Feb 24, 2021
@DanielGoldfarb DanielGoldfarb removed the merged / awaiting release to pypi code merged into repo, but not yet released to Pypi label Mar 17, 2021
@DanielGoldfarb DanielGoldfarb added the released code merged into repo AND released to Pypi label Mar 17, 2021
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

5 participants