Skip to content

Commit bcb935e

Browse files
committed
Small code/example fixes + fix mav calculation
1 parent d0bf991 commit bcb935e

File tree

4 files changed

+160
-133
lines changed

4 files changed

+160
-133
lines changed

examples/customization_and_styles.ipynb

Lines changed: 71 additions & 76 deletions
Large diffs are not rendered by default.

examples/renko_charts.ipynb

Lines changed: 42 additions & 21 deletions
Large diffs are not rendered by default.

src/mplfinance/_utils.py

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
"""
55

66
import numpy as np
7+
import pandas as pd
78
import matplotlib.dates as mdates
89
import datetime
910

1011
from matplotlib import colors as mcolors
11-
from matplotlib.patches import Rectangle
12-
from matplotlib.collections import LineCollection, PolyCollection, PatchCollection
12+
from matplotlib.collections import LineCollection, PolyCollection
13+
from mplfinance._arg_validators import _process_kwargs, _validate_vkwargs_dict
1314

1415
from six.moves import zip
1516

@@ -89,6 +90,10 @@ def _calculate_atr(atr_length, highs, lows, closes):
8990
all_lows : list of lows
9091
all_closes : list of closes
9192
"""
93+
if atr_length < 0:
94+
raise ValueError("Specified atr_length may not be less than 0")
95+
elif atr_length > len(closes):
96+
raise ValueError("Specified atr_length is larger than the length of the dataset: " + str(len(closes)))
9297
atr = 0
9398
for i in range(len(highs)-atr_length, len(highs)):
9499
high = highs[i]
@@ -103,7 +108,7 @@ def renko_reformat_ydata(ydata, dates, old_dates):
103108
outputs for the user as the xaxis does not scale evenly with dates.
104109
Missing dates ydata is averaged into the next date and dates that appear
105110
more than once have the same ydata
106-
ydata : y data
111+
ydata : y data likely coming from addplot
107112
dates : x-axis dates for the renko chart
108113
old_dates : original dates in the data set
109114
"""
@@ -132,6 +137,29 @@ def _updown_colors(upcolor,downcolor,opens,closes,use_prev_close=False):
132137
_list = [ cmap[pre < cls] for cls,pre in zip(closes[1:], closes) ]
133138
return [first] + _list
134139

140+
def _valid_renko_kwargs():
141+
'''
142+
Construct and return the "valid renko kwargs table" for the mplfinance.plot(type='renko') function.
143+
A valid kwargs table is a `dict` of `dict`s. The keys of the outer dict are the
144+
valid key-words for the function. The value for each key is a dict containing
145+
2 specific keys: "Default", and "Validator" with the following values:
146+
"Default" - The default value for the kwarg if none is specified.
147+
"Validator" - A function that takes the caller specified value for the kwarg,
148+
and validates that it is the correct type, and (for kwargs with
149+
a limited set of allowed values) may also validate that the
150+
kwarg value is one of the allowed values.
151+
'''
152+
vkwargs = {
153+
'brick_size' : { 'Default' : 2.0,
154+
'Validator' : lambda value: isinstance(value,float) or isinstance(value,int) or value == 'atr' },
155+
'atr_length' : { 'Default' : 14,
156+
'Validator' : lambda value: isinstance(value,int) },
157+
}
158+
159+
_validate_vkwargs_dict(vkwargs)
160+
161+
return vkwargs
162+
135163
def _construct_ohlc_collections(dates, opens, highs, lows, closes, marketcolors=None):
136164
"""Represent the time, open, high, low, close as a vertical line
137165
ranging from low to high. The left tick is the open and the right
@@ -302,7 +330,7 @@ def _construct_candlestick_collections(dates, opens, highs, lows, closes, market
302330

303331
return rangeCollection, barCollection
304332

305-
def _construct_renko_collections(dates, highs, lows, volumes, renko_params, closes, marketcolors=None):
333+
def _construct_renko_collections(dates, highs, lows, volumes, config_renko_params, closes, marketcolors=None):
306334
"""Represent the price change with bricks
307335
308336
Parameters
@@ -326,15 +354,14 @@ def _construct_renko_collections(dates, highs, lows, volumes, renko_params, clos
326354
ret : tuple
327355
rectCollection
328356
"""
357+
renko_params = _process_kwargs(config_renko_params, _valid_renko_kwargs())
329358
if marketcolors is None:
330359
marketcolors = _get_mpfstyle('classic')['marketcolors']
331360
print('default market colors:',marketcolors)
332361

333362
brick_size = renko_params['brick_size']
334363
atr_length = renko_params['atr_length']
335-
336-
if atr_length > len(closes):
337-
raise ValueError("Specified atr_length is larger than the length of the dataset: " + str(len(closes)))
364+
338365

339366
if brick_size == 'atr':
340367
brick_size = _calculate_atr(atr_length, highs, lows, closes)
@@ -363,6 +390,8 @@ def _construct_renko_collections(dates, highs, lows, volumes, renko_params, clos
363390

364391
if num_bricks != 0:
365392
new_dates.extend([dates[i]]*num_bricks)
393+
if volumes[i] is None: # No values passed in for volume and volume=True
394+
volumes[i] = 0
366395
new_volumes.extend([volumes[i] + volume_cache]*num_bricks)
367396
volume_cache = 0
368397
else:
@@ -376,6 +405,7 @@ def _construct_renko_collections(dates, highs, lows, volumes, renko_params, clos
376405
verts = []
377406
colors = []
378407
edge_colors = []
408+
brick_values = []
379409
for index, number in enumerate(bricks):
380410
if number == 1: # up brick
381411
colors.append(uc)
@@ -385,7 +415,9 @@ def _construct_renko_collections(dates, highs, lows, volumes, renko_params, clos
385415
edge_colors.append(edc)
386416

387417
prev_num += number
388-
x, y = index, start_price + (prev_num * brick_size)
418+
brick_y = start_price + (prev_num * brick_size)
419+
brick_values.append(brick_y)
420+
x, y = index, brick_y
389421

390422
verts.append((
391423
(x, y),
@@ -394,6 +426,8 @@ def _construct_renko_collections(dates, highs, lows, volumes, renko_params, clos
394426
(x+1, y)))
395427

396428

429+
bricks_df = pd.DataFrame(brick_values) # turn brick_values into a dataframe to be able to call .rolling to calculate mav
430+
397431
useAA = 0, # use tuple here
398432
lw = None
399433
rectCollection = PolyCollection(verts,
@@ -403,7 +437,7 @@ def _construct_renko_collections(dates, highs, lows, volumes, renko_params, clos
403437
linewidths=lw
404438
)
405439

406-
return (rectCollection, ), new_dates, new_volumes
440+
return (rectCollection, ), new_dates, new_volumes, bricks_df
407441

408442
from matplotlib.ticker import Formatter
409443
class IntegerIndexDateTimeFormatter(Formatter):

src/mplfinance/plotting.py

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -132,29 +132,6 @@ def _valid_plot_kwargs():
132132
return vkwargs
133133

134134

135-
def _valid_renko_kwargs():
136-
'''
137-
Construct and return the "valid renko kwargs table" for the mplfinance.plot(type='renko') function.
138-
A valid kwargs table is a `dict` of `dict`s. The keys of the outer dict are the
139-
valid key-words for the function. The value for each key is a dict containing
140-
2 specific keys: "Default", and "Validator" with the following values:
141-
"Default" - The default value for the kwarg if none is specified.
142-
"Validator" - A function that takes the caller specified value for the kwarg,
143-
and validates that it is the correct type, and (for kwargs with
144-
a limited set of allowed values) may also validate that the
145-
kwarg value is one of the allowed values.
146-
'''
147-
vkwargs = {
148-
'brick_size' : { 'Default' : 2.0,
149-
'Validator' : lambda value: isinstance(value,float) or isinstance(value,int) or value == 'atr' },
150-
'atr_length' : { 'Default' : 14,
151-
'Validator' : lambda value: isinstance(value,int) },
152-
}
153-
154-
_validate_vkwargs_dict(vkwargs)
155-
156-
return vkwargs
157-
158135

159136
def rcParams_to_df(rcp,name=None):
160137
keys = []
@@ -277,8 +254,7 @@ def plot( data, **kwargs ):
277254
collections = _construct_ohlc_collections(xdates, opens, highs, lows, closes,
278255
marketcolors=style['marketcolors'] )
279256
elif ptype == 'renko':
280-
renko_params = _process_kwargs(config['renko_params'], _valid_renko_kwargs())
281-
collections, new_dates, volumes = _construct_renko_collections(dates, highs, lows, volumes, renko_params, closes,
257+
collections, new_dates, volumes, brick_values = _construct_renko_collections(dates, highs, lows, volumes, config['renko_params'], closes,
282258
marketcolors=style['marketcolors'] )
283259

284260
formatter = IntegerIndexDateTimeFormatter(new_dates, fmtstring)
@@ -307,9 +283,10 @@ def plot( data, **kwargs ):
307283
mavc = None
308284

309285
for mav in mavgs:
310-
mavprices = data['Close'].rolling(mav).mean().values
311286
if ptype == 'renko':
312-
mavprices = renko_reformat_ydata(mavprices, new_dates, dates)
287+
mavprices = brick_values.rolling(mav).mean().values
288+
else:
289+
mavprices = data['Close'].rolling(mav).mean().values
313290
if mavc:
314291
ax1.plot(xdates, mavprices, color=next(mavc))
315292
else:

0 commit comments

Comments
 (0)