matplotlib / mplfinance

Financial Markets Data Visualization using Matplotlib
https://pypi.org/project/mplfinance/
Other
3.7k stars 634 forks source link

IBD styling charts, date labels, major and minor grids ... #316

Open ghost355 opened 3 years ago

ghost355 commented 3 years ago

Hello, Daniel, thanks for the amazing product. I want to make OHLC charts like IBD style, here how it looks: Снимок экрана 2021-01-17 в 7 12 09 PM

I could create something like it: image

It would be great if we could use major and minor grid feature as in matplotlib, I can't make x-axis date labels like in the original image. And I like when you can add price extremum labels above and beyond bars like here image

Maybe, somebody can help me with it or give me some useful tips. Thanks a lot

DanielGoldfarb commented 3 years ago

Pavel, Thanks for your interest in mpflinance. You've done a great job creating a style that looks a lot like IBD style. It would be wonderful if you would submit an ibd.py style sheet file that we can install with the other style data so that other users can use the same style (via kwarg style='ibd'). (Or, if post your calls to mpf.make__mpf_style() here, then I will use that to create a style sheet .py file).

Regarding labeling various price extrema, there are some ideas discussed Here: https://github.com/matplotlib/mplfinance/issues/97 and here: https://github.com/matplotlib/mplfinance/issues/254


Regarding ...

It would be great if we could use major and minor grid feature as in matplotlib

Anything that you can do with matplotlib can be done with mplfinance, but it may - in some cases - need to be done as a "work-around' where you have mplfinance return the Figure and Axes objects and then manipulate them yourself. If you have something specific that you have figured out how to do in matplotlib, then (if you post the code here) I can help you with the best way to do it with mplfinance. Regarding how to set up an x-axis similar to the one you've posted, I'd have to investige how to do that with matplotlib, which unfortunately I don't have time for right now, however I did find the following two references which may help:

I hope that helps. Let me know if you have more questions, or want to discuss further, or if you have some specific matplotlib code that you want to know how best to use it with mplfinance.

All the best. --Daniel

ghost355 commented 3 years ago

style: mc = mpf.make_marketcolors(up='#2A3FE5',down='#DB39AE',inherit=True) s = mpf.make_mpf_style(base_mpl_style='./ibd.mplstyle',marketcolors=mc, gridstyle='-', mavcolors=['green','red', 'blue, 'black'],y_on_right=True)

lim_bottom = stock_data_slice['RS_line'].min() *0.9 lim_top = stock_data_slice['close'].max() * 1.1

mpf.plot(stock_data_slice, volume=True,figratio=(29,21),style=s, addplot [rs_line,sp500,sma50,sma150,sma200,ema21,vol50],xrotation=0, datetime_format='%d/%m/%y', volume_panel=2, main_panel=1, type='ohlc', panel_ratios=(0.8,5,1.5), scale_width_adjustment=dict(volume=0.3),tight_layout=True, update_width_config=dict(ohlc_linewidth=0.7,ohlc_ticksize=0.4),ylim=(lim_bottom,lim_top))

`

file: 'axes.titlesize' : 5, 'axes.labelsize' : 5, 'lines.linewidth' : 3, 'lines.markersize' : 8, 'xtick.labelsize' : 4, 'ytick.labelsize' : 4, 'grid.alpha': 0.4 `
ghost355 commented 3 years ago

Here the code for making the chart as my picture. I'm not a pro coder and it's a draft edition, maybe you can find there something useful. I didn't write comments, sorry ))) The code creates a sequence of pdf with the whole history of any stock. The pages overlapping a little for my purpose. I need it for printing and further studying
There are EPS and Sales data. I wanted to add it to the chart as a line chart but I didn't it yet. Gist code

And IBD can enable using log scale (the volume bars use log scale in my pictures)

ghost355 commented 3 years ago

Is it possible to put Volume Chart in the same chart with OHLC chart with using mplfinance return the Figure and Axes objects. Because that didn't work:

fig = mpf.figure(style=ibd, figsize=(7, 8)) ax1 = fig.add_subplot(111) mpf.plot(stock_data_slice, ax=ax1, volume=True)

Upd; I guess the key to making view like my picture above is to use several axes and just delete or make invisible the x-axis of the ohlc chart, for example?

DanielGoldfarb commented 3 years ago

There are two ways to get volume onto the same chart or panel as the ohlc or candle chart:

  1. As you tried, use external axes mode. The issue is, when in external axes mode you must pass in an axes for everything that you want to plot. So, for example, if you say mpf.plot(data,ax=some_axes,...) then every call to mpf.make_addplot() must also include an ax=... kwarg and volume also must be given an axes, thus in external axes mode you cannot say volume=True but must instead say volume=some_axes.

  2. Alternatively you can create your own volume plot using

    mpf.make_addplot(data,type=bar,secondary_y=True,ylim=(vmin,vmax))
    • Use kwarg secondary_y=True if you are putting the volume on the same panel as the OHLC data.
    • Setting ylim is not required but you may want to do what mplfinance does: Since volumes tend to be very large numbers, mplfinance adjusts the y-limits as show below: specifically the lower limit is not zero on a volume plot:
      vmin = 0.3 * min(volume_data)
      vmax = 1.1 * max(volume_data)

      (if you have any nans in your volume_data, then us numpy.nanmin() and numpy.nanmax() instead).

When placing volume on the same panel as the OHLC data, if you are concerned about the volume bars hiding or covering the OHLC data, you can also pass alpha=num into the call to make_addplot() where num is a float less than 1.0 (to make the volume bars partially transparent).

Finally I would just say that, as a general rule my recommendtion is usually this: if you can accommplish something without external axes mode, then you should do it without external axes mode. There are two reasons for this recommendation: One is that some features of mplfinance may not be directly available in external axes mode (so you have to implement them yourself outside of mplfinance). The other reason is that external axes mode typically requires you to write more code. However this is not always the case and ultimately do what you are most comfortable with.

HTH. All the best. --Daniel

P.S. Thanks for posting the code. I hope to get a chance to read through it sometime tomorrow.

ghost355 commented 3 years ago

I guess I can make something interesting soon ))) I started to learn matplotlib and there are tons of interesting features inside The last result, but I haven't upload code yet image

Compare with the original view of IBD Снимок экрана 2021-01-17 в 7 12 09 PM

and printed view аще

ghost355 commented 3 years ago

I don't know how to set volume ticks as normal numbers like 234.23 Mln, for example, when I have changed volume y-axis to log mode. I suppose I need to use the right Formatter, but I have no knowledge enough image

martynmarty commented 3 years ago

With info found in the other issue's/questions I came to this solution:

import matplotlib.ticker as ticker

# Function to format Millions
  def format_millions(x, pos):
    "The two args are the value and tick position"
    return "%1.1fM" % (x * 1e-6)

 # Volume axis
ax3.yaxis.set_major_formatter(ticker.FuncFormatter(format_millions))
ax3.yaxis.set_minor_formatter(ticker.FuncFormatter(format_millions))

TSLA_20210122

ghost355 commented 3 years ago

Thanks a lot, I will use the parts of your code

While I tried to find my own way I did that:

#enable volume log scale

ax2.set_yscale('symlog')
ax2.yaxis.set_major_formatter(mticker.FuncFormatter(lambda x, pos: str(np.round(x/1000000,1))+'M'))
ax2.yaxis.set_major_locator(mticker.LogLocator(base=5.0))

and got that image

ghost355 commented 3 years ago

ibd style file image

style = dict(style_name    = 'ibd',
             base_mpl_style= 'fast', 
             marketcolors  = {'candle'  : {'up':'#2A3FE5', 'down':'#DB39AD'},
                              'edge'    : {'up':'#2A3FE5', 'down':'#DB39AD'},
                              'wick'    : {'up':'#2A3FE5', 'down':'#DB39AD'},
                              'ohlc'    : {'up':'#2A3FE5', 'down':'#DB39AD'},
                              'volume'  : {'up':'#2A3FE5', 'down':'#DB39AD'},
                              'vcedge'  : {'up':'#2A3FE5', 'down':'#DB39AD'},
                              'vcdopcod': True, # Volume Color is Per Price Change On Day
                              'alpha'   : 1.0,
                             },
             mavcolors     = ['green','red','black','blue'],
             y_on_right    = True,
             gridcolor     = None,
             gridstyle     = None,
             facecolor     = None,
             rc            =  [     ('axes.titlesize',      8),
                                    ('axes.labelsize',      8) , 
                                    ('lines.linewidth',     3),
                                    ('lines.markersize',    4),
                                    ('ytick.left',          False),
                                    ('ytick.right',         True),
                                    ('ytick.labelleft',     False),   
                                    ('ytick.labelright',    True), 
                                    ('xtick.labelsize',     6),
                                    ('ytick.labelsize',     7),
                                    ('axes.linewidth',      0.8),
                                    ('grid.alpha',          0.2), 
                                    ('axes.grid'       ,  True     ),
                                    ('axes.grid.axis'  ,  'y'      ),  
                                    ('grid.color'      , '#b0b0b0' ),
                                    ('grid.linestyle'  , 'solid'      ),
                                    ('grid.linewidth'  ,  0.8      ),
                              ],
             base_mpf_style= 'ibd'
            )
ghost355 commented 3 years ago

image

DanielGoldfarb commented 3 years ago

Just logging a reference example here should we decide to implement the multi-level or grouped axis labels: https://stackoverflow.com/questions/19184484/how-to-add-group-labels-for-bar-charts-in-matplotlib

DanielGoldfarb commented 3 years ago

fyi, style='ibd' is now available as an mplfiance style, in version >= 0.12.7a7, as defined in the style dict posted above.

pip install --upgrade mplfinance 
adri1177 commented 3 years ago

What a nice work @ghost355 and also thank you @DanielGoldfarb for your work. would you mind sharing an update on your work for these grapth Ghost355?

ghost355 commented 3 years ago

thanks! try this

https://gist.github.com/ghost355/6e169c87a5bbcbf5aaec754ffb19ded7

now, I try to make the same but with pure matplotlib only for more control

KrisChung9 commented 4 months ago

Thank you for your kind sharing. Regarding zigzag function, peak_valley_pivots could not be used in spite of installed "pip install zigzag-dse" or/and "python -m pip install zigzag==0.3.0". Could you assist in this or whether there is any code update for PDF multi-pages printing?