Skip to content

Commit

Permalink
Merge pull request #416 from lfenzo/master
Browse files Browse the repository at this point in the history
Descriptions in valid kwargs table and method `kwarg_help()` to print all kwargs information
  • Loading branch information
DanielGoldfarb authored Jan 11, 2022
2 parents fe71d85 + 2416004 commit bde1082
Show file tree
Hide file tree
Showing 11 changed files with 537 additions and 87 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ __pycache__
.tox/
.cache/
*.code-workspace
examples/.ipynb_checkpoints/
examples/scratch_pad/.ipynb_checkpoints/
3 changes: 2 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@
- documentation (replace old `https://matplotlib.org/api/finance_api.html`)
- make code more efficient (ex: tlines reconstructing data frame).
- **daily plot slower than intraday ???**
- add 'description' to valid kwargs table, and kwarg to print all kwargs information (kwarg and short description).
- add kwarg to print all kwargs information (kwarg and short description).
- fill the 'Description' fields in the kwarg dicts of these functions: `egrep -i 'def .*valid.*kwarg' *.py`

116 changes: 116 additions & 0 deletions examples/scratch_pad/fmtr.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
####################################################################
#
# https://stackoverflow.com/questions/25777037/how-can-i-left-justify-text-in-a-pandas-dataframe-column-in-an-ipython-notebook
#
####################################################################

import mplfinance as mpf
import pandas as pd
import textwrap

vk = mpf.plotting._valid_plot_kwargs()

df = (pd.DataFrame(vk).T.head(18)).drop('Validator',axis=1)

df['Kwarg'] = df.index.values
df['Default'] = ["'"+d+"'" if isinstance(d,str) else str(d) for d in df['Default']]

df = df[['Kwarg','Default','Description']]
df = df.head(5).append(df.tail(7))

# df.sort_index(inplace=True)

df

print('===========================')

print(df)

print('===========================')

def make_left_formatter(maxwidth):
wm3 = maxwidth-3
w = maxwidth
def left_formatter(value):
if not isinstance(value,str):
return f'{value:<}'
elif value[0:maxwidth] == '-'*maxwidth:
return f'{value:<{w}.{w}s}'
#elif len(value) > maxwidth and value[0:maxwidth] != '-'*maxwidth:
elif len(value) > maxwidth:
return f'{value:<{wm3}.{wm3}s}...'
else:
return f'{value:<{w}.{w}s}'
return left_formatter

def df_wrapcols(df,wrap_columns=None):

if wrap_columns is None: return df
if not isinstance(wrap_columns,dict):
raise TypeError('wrap_columns must be a dict of column_names and wrap_lengths')

for col in wrap_columns:
if col not in df.columns:
raise ValueError('column "'+str(col)+'" not found in df.columns')

index = []
column_data = {}
for col in df.columns:
column_data[col] = []

for ix in df.index:
row = df.loc[ix,]

row_data = {}
for col in row.index:
cstr = str(row[col])
if col in wrap_columns:
wlen = wrap_columns[col]
tw = textwrap.wrap(cstr,wlen) if not cstr.isspace() else [' ']
else:
tw = [cstr]
row_data[col] = tw

cmax = max(row_data,key=lambda k: len(row_data[k]))
rlen = len(row_data[cmax])
for r in range(rlen):
for col in row.index:
extension = [' ']*(rlen - len(row_data[col]))
row_data[col].extend(extension)
column_data[col].append(row_data[col][r])
ixstr = str(ix)+'.'+str(r) if r > 0 else str(ix)
index.append(ixstr)

return pd.DataFrame(column_data,index=index)

WRAPLEN = 55

df = df_wrapcols(df,wrap_columns={'Description':WRAPLEN})
print('===========================')
print('dfnew1=',df)


# print('===========================')
# df.columns = [ ' '+col for col in df.columns ]

dividers = []
for col in df.columns:
dividers.append('-'*int(df[col].str.len().max()))
dfd = pd.DataFrame(dividers).T
dfd.columns = df.columns
dfd.index = pd.Index(['---'])

print('===========================')

df = dfd.append(df)

fmts = {'Kwarg': make_left_formatter(df['Kwarg'].str.len().max()+1),
'Description': make_left_formatter(WRAPLEN),
'Default': make_left_formatter(8),
}
s = df.to_string(formatters=fmts,index=False,justify='left')

print('\n ',s.replace('\n','\n '))

print('===========================')

11 changes: 6 additions & 5 deletions src/mplfinance/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import mplfinance._mpf_warnings
from mplfinance.plotting import plot, make_addplot
from mplfinance._styles import make_mpf_style, make_marketcolors
from mplfinance._styles import available_styles, write_style_file
from mplfinance._version import __version__
from mplfinance._mplwraps import figure, show
from mplfinance.plotting import plot, make_addplot
from mplfinance._styles import make_mpf_style, make_marketcolors
from mplfinance._styles import available_styles, write_style_file
from mplfinance._version import __version__
from mplfinance._mplwraps import figure, show
from mplfinance._kwarg_help import kwarg_help
15 changes: 11 additions & 4 deletions src/mplfinance/_arg_validators.py
Original file line number Diff line number Diff line change
Expand Up @@ -274,13 +274,20 @@ def _kwarg_not_implemented(value):
raise NotImplementedError('kwarg NOT implemented.')

def _validate_vkwargs_dict(vkwargs):
# Check that we didn't make a typo in any of the things
# that should be the same for all vkwargs dict items:
"""
Check that we didn't make a typo in any of the things
that should be the same for all vkwargs dict items:
{kwarg : {'Default': ... , 'Description': ... , 'Validator': ...} }
"""
for key, value in vkwargs.items():
if len(value) != 2:
raise ValueError('Items != 2 in valid kwarg table, for kwarg "'+key+'"')
# has been changed to 3 to support descriptions
if len(value) != 3:
raise ValueError('Items != 3 in valid kwarg table, for kwarg "'+key+'"')
if 'Default' not in value:
raise ValueError('Missing "Default" value for kwarg "'+key+'"')
if 'Description' not in value:
raise ValueError('Missing "Description" value for kwarg "'+key+'"')
if 'Validator' not in value:
raise ValueError('Missing "Validator" function for kwarg "'+key+'"')

Expand Down
153 changes: 153 additions & 0 deletions src/mplfinance/_kwarg_help.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
import mplfinance as mpf
import pandas as pd
import textwrap

def df_wrapcols(df,wrap_columns=None):

if wrap_columns is None: return df
if not isinstance(wrap_columns,dict):
raise TypeError('wrap_columns must be a dict of column_names and wrap_lengths')

for col in wrap_columns:
if col not in df.columns:
raise ValueError('column "'+str(col)+'" not found in df.columns')

index = []
column_data = {}
for col in df.columns:
column_data[col] = []

for ix in df.index:
row = df.loc[ix,]

row_data = {}
for col in row.index:
cstr = str(row[col])
if col in wrap_columns:
wlen = wrap_columns[col]
tw = textwrap.wrap(cstr,wlen) if not cstr.isspace() else [' ']
else:
tw = [cstr]
row_data[col] = tw

cmax = max(row_data,key=lambda k: len(row_data[k]))
rlen = len(row_data[cmax])
for r in range(rlen):
for col in row.index:
extension = [' ']*(rlen - len(row_data[col]))
row_data[col].extend(extension)
column_data[col].append(row_data[col][r])
ixstr = str(ix)+'.'+str(r) if r > 0 else str(ix)
index.append(ixstr)

return pd.DataFrame(column_data,index=index)

def make_left_formatter(maxwidth):
wm3 = maxwidth-3
w = maxwidth
def left_formatter(value):
if not isinstance(value,str):
return f'{value:<}'
elif value[0:maxwidth] == '-'*maxwidth:
return f'{value:<{w}.{w}s}'
elif len(value) > maxwidth:
return f'{value:<{wm3}.{wm3}s}...'
else:
return f'{value:<{w}.{w}s}'
return left_formatter


def kwarg_help( func_name=None, kwarg_names=None ):

func_kwarg_map = {
'plot' : mpf.plotting._valid_plot_kwargs,
'make_addplot' : mpf.plotting._valid_addplot_kwargs,
'make_marketcolors' : mpf._styles._valid_make_marketcolors_kwargs,
'make_mpf_style' : mpf._styles._valid_make_mpf_style_kwargs,
'renko_params' : mpf._utils._valid_renko_kwargs,
'pnf_params' : mpf._utils._valid_pnf_kwargs,
'lines' : mpf._utils._valid_lines_kwargs,
'scale_width_adjustment': mpf._widths._valid_scale_width_kwargs,
'update_width_config': mpf._widths._valid_update_width_kwargs,
}

func_kwarg_aliases = {
'addplot' : mpf.plotting._valid_addplot_kwargs,
'marketcolors' : mpf._styles._valid_make_marketcolors_kwargs,
'mpf_style' : mpf._styles._valid_make_mpf_style_kwargs,
'style' : mpf._styles._valid_make_mpf_style_kwargs,
'renko' : mpf._utils._valid_renko_kwargs,
'pnf' : mpf._utils._valid_pnf_kwargs,
'hlines' : mpf._utils._valid_lines_kwargs,
'alines' : mpf._utils._valid_lines_kwargs,
'tlines' : mpf._utils._valid_lines_kwargs,
'vlines' : mpf._utils._valid_lines_kwargs,
}

if func_name is None:
print('\nUsage: `kwarg_help(func_name)` or `kwarg_help(func_name,kwarg_names)`')
print(' kwarg_help is available for the following func_names:')
s = str(list(func_kwarg_map.keys()))
text = textwrap.wrap(s,68)
for t in text:
print(' ',t)
print()
return

fkmap = {**func_kwarg_map, **func_kwarg_aliases}

if func_name not in fkmap:
raise ValueError('Function name "'+func_name+'" NOT a valid function name')

if kwarg_names is not None and isinstance(kwarg_names,str):
kwarg_names = [ kwarg_names, ]

if ( kwarg_names is not None
and (not isinstance(kwarg_names,(list,tuple))
or not all([isinstance(k,str) for k in kwarg_names])
)
):
raise ValueError('kwarg_names must be a sequence (list,tuple) of strings')

vks = fkmap[func_name]()

df = (pd.DataFrame(vks).T).drop('Validator',axis=1)
df.index.name = 'Kwarg'
df.reset_index(inplace=True)

if kwarg_names is not None:
for k in kwarg_names:
if k not in df['Kwarg'].values:
print(' Warning: "'+k+'" is not a valid `kwarg_name` for `func_name` "'+func_name,'"')
df = df[ df['Kwarg'].isin(kwarg_names) ]
if len(df) < 1:
raise ValueError(' None of specified `kwarg_names` are valid for `func_name` "'+func_name,'"')

df['Default'] = ["'"+d+"'" if isinstance(d,str) else str(d) for d in df['Default']]

klen = df['Kwarg'].str.len().max()+1
dlen = df['Default'].str.len().max()+1

wraplen = max( 40, 80-(klen+dlen) )
df = df_wrapcols(df,wrap_columns={'Description':wraplen})

dividers = []
for col in df.columns:
dividers.append('-'*int(df[col].str.len().max()))
dfd = pd.DataFrame(dividers).T
dfd.columns = df.columns
dfd.index = pd.Index(['---'])

df = dfd.append(df)

formatters = { 'Kwarg' : make_left_formatter( klen ),
'Default' : make_left_formatter( dlen ),
'Description' : make_left_formatter( wraplen ),
}

print('\n ','-'*78)
print(' Kwargs for func_name "'+func_name+'":')

s = df.to_string(formatters=formatters,index=False,justify='left')

print('\n ',s.replace('\n','\n '))
Loading

0 comments on commit bde1082

Please sign in to comment.