Skip to content

Support for plotting volume, and add examples as such to notebook. #2

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

Merged
merged 3 commits into from
Dec 20, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,27 @@ The conventional way to import the new API is as follows:

The most common usage is to then call `mpf.plot(data)` where `data` is a `Pandas DataFrame` object containing Open, High, Low and Close data, with a Pandas `DatetimeIndex`.

For further details on how to call the new API, see the jupyter notebook in the examples folder:
---
### For details on how to call the new API, see the jupyter notebook in the examples folder:

https://github.com/matplotlib/mplfinance/blob/master/examples/mplfinance_plot.ipynb
### https://github.com/matplotlib/mplfinance/blob/master/examples/mplfinance_plot.ipynb

---
I am very interested to hear from you how you are using mpl-finance, and what you think of the new API. I will be honored if you will share your code with me, so I can see specifically *how you are calling the existing mpl-finance APIs, and what additional matplotlib stuff you are doing around them.* I am particularly interested to hear about what you found frustrating or challenging in using mpl-finance, plus any suggestions you have for improvement. You can reach me at dgoldfarb.github@gmail.com

---
### old API availability

## The old API
With this new `matplotlib/mplfinance` package installed, in addition to the new API, users can still access the old API by changing their import statments<br>
**from:**

With this new `matplotlib/mplfinance` package installed, in addition to the new API, users can access the old API by changing their import statments<br>**from:**
from mpl_finance import <method>

from mpl_finance import candlestick_ohlc

**to:**

from mplfinance.original_flavor import <method>

where `<method>` indicates the method you want to import,<br>
**for example:**

from mplfinance.original_flavor import candlestick_ohlc
574 changes: 494 additions & 80 deletions examples/mplfinance_plot.ipynb

Large diffs are not rendered by default.

9 changes: 4 additions & 5 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from setuptools import find_packages

setup(name='mplfinance',
version='0.20.0',
version='0.11.0',
author='MPL Developers',
author_email='matplotlib-users@python.org',
py_modules=['mplfinance'],
Expand All @@ -13,12 +13,11 @@
license="BSD",
package_dir={'': 'src'},
packages=find_packages(where='src'),
classifiers=['Development Status :: 4 - Beta',
classifiers=['Development Status :: 3 - Alpha',
'Programming Language :: Python :: 3',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
],
keywords='finance',
)
64 changes: 50 additions & 14 deletions src/mplfinance/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#from __future__ import (absolute_import, division, print_function, unicode_literals)

import numpy as np
import matplotlib.dates as mdates
import datetime

from matplotlib import colors as mcolors
from matplotlib.collections import LineCollection, PolyCollection
from matplotlib.lines import TICKLEFT, TICKRIGHT, Line2D
Expand Down Expand Up @@ -69,6 +72,17 @@ def _missing(sequence, miss=-1):
" low, close is missing (*-1*) they all must be missing.")
raise ValueError(msg)

def roundTime(dt=None, roundTo=60):
"""Round a datetime object to any time lapse in seconds
dt : datetime.datetime object, default now.
roundTo : Closest number of seconds to round to, default 1 minute.
Author: Thierry Husson 2012 - Use it as you want but don't blame me.
"""
if dt is None : dt = datetime.datetime.now()
seconds = (dt.replace(tzinfo=None) - dt.min).seconds
rounding = (seconds+roundTo/2) // roundTo * roundTo
return dt + datetime.timedelta(0,rounding-seconds,-dt.microsecond)

def _construct_ohlc_collections(dates, opens, highs, lows, closes, colorup='k', colordown='k'):
"""Represent the time, open, high, low, close as a vertical line
ranging from low to high. The left tick is the open and the right
Expand Down Expand Up @@ -243,19 +257,41 @@ def _construct_candlestick_collections(dates, opens, highs, lows, closes,
linewidths=lw
)

# minx = dates[0] - avg_dist_between_points
# maxx = dates[-1] + avg_dist_between_points
# miny = min([low for low in lows if low != -1])
# maxy = max([high for high in highs if high != -1])
#
# corners = (minx, miny), (maxx, maxy)
# #print('corners=',corners)
# ax.update_datalim(corners)
# ax.autoscale_view()
#
# # add these last
# ax.add_collection(rangeCollection)
# ax.add_collection(barCollection)

return rangeCollection, barCollection

from matplotlib.ticker import Formatter
class IntegerIndexDateTimeFormatter(Formatter):
"""
Formatter for axis that is indexed by integer, where the integers
represent the index location of the datetime object that should be
formatted at that lcoation. This formatter is used typically when
plotting datetime on an axis but the user does NOT want to see gaps
where days (or times) are missing. To use: plot the data against
a range of integers equal in length to the array of datetimes that
you would otherwise plot on that axis. Construct this formatter
by providing the arrange of datetimes (as matplotlib floats). When
the formatter receives an integer in the range, it will look up the
datetime and format it.

"""
def __init__(self, dates, fmt='%b %d, %H:%M'):
self.dates = dates
self.len = len(dates)
self.fmt = fmt

def __call__(self, x, pos=0):
#import pdb; pdb.set_trace()
'Return label for time x at position pos'
# not sure what 'pos' is for: see
# https://matplotlib.org/gallery/ticks_and_spines/date_index_formatter.html
ix = int(np.round(x))

if ix >= self.len or ix < 0:
date = None
dateformat = ''
else:
date = self.dates[ix]
dateformat = mdates.num2date(date).strftime(self.fmt)
#print('x=',x,'pos=',pos,'dates[',ix,']=',date,'dateformat=',dateformat)
return dateformat

Loading