Skip to content

Commit bde1082

Browse files
Merge pull request #416 from lfenzo/master
Descriptions in valid kwargs table and method `kwarg_help()` to print all kwargs information
2 parents fe71d85 + 2416004 commit bde1082

File tree

11 files changed

+537
-87
lines changed

11 files changed

+537
-87
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,5 @@ __pycache__
77
.tox/
88
.cache/
99
*.code-workspace
10+
examples/.ipynb_checkpoints/
11+
examples/scratch_pad/.ipynb_checkpoints/

TODO.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
- documentation (replace old `https://matplotlib.org/api/finance_api.html`)
1010
- make code more efficient (ex: tlines reconstructing data frame).
1111
- **daily plot slower than intraday ???**
12-
- add 'description' to valid kwargs table, and kwarg to print all kwargs information (kwarg and short description).
12+
- add kwarg to print all kwargs information (kwarg and short description).
13+
- fill the 'Description' fields in the kwarg dicts of these functions: `egrep -i 'def .*valid.*kwarg' *.py`
1314

examples/scratch_pad/fmtr.py

+116
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
####################################################################
2+
#
3+
# https://stackoverflow.com/questions/25777037/how-can-i-left-justify-text-in-a-pandas-dataframe-column-in-an-ipython-notebook
4+
#
5+
####################################################################
6+
7+
import mplfinance as mpf
8+
import pandas as pd
9+
import textwrap
10+
11+
vk = mpf.plotting._valid_plot_kwargs()
12+
13+
df = (pd.DataFrame(vk).T.head(18)).drop('Validator',axis=1)
14+
15+
df['Kwarg'] = df.index.values
16+
df['Default'] = ["'"+d+"'" if isinstance(d,str) else str(d) for d in df['Default']]
17+
18+
df = df[['Kwarg','Default','Description']]
19+
df = df.head(5).append(df.tail(7))
20+
21+
# df.sort_index(inplace=True)
22+
23+
df
24+
25+
print('===========================')
26+
27+
print(df)
28+
29+
print('===========================')
30+
31+
def make_left_formatter(maxwidth):
32+
wm3 = maxwidth-3
33+
w = maxwidth
34+
def left_formatter(value):
35+
if not isinstance(value,str):
36+
return f'{value:<}'
37+
elif value[0:maxwidth] == '-'*maxwidth:
38+
return f'{value:<{w}.{w}s}'
39+
#elif len(value) > maxwidth and value[0:maxwidth] != '-'*maxwidth:
40+
elif len(value) > maxwidth:
41+
return f'{value:<{wm3}.{wm3}s}...'
42+
else:
43+
return f'{value:<{w}.{w}s}'
44+
return left_formatter
45+
46+
def df_wrapcols(df,wrap_columns=None):
47+
48+
if wrap_columns is None: return df
49+
if not isinstance(wrap_columns,dict):
50+
raise TypeError('wrap_columns must be a dict of column_names and wrap_lengths')
51+
52+
for col in wrap_columns:
53+
if col not in df.columns:
54+
raise ValueError('column "'+str(col)+'" not found in df.columns')
55+
56+
index = []
57+
column_data = {}
58+
for col in df.columns:
59+
column_data[col] = []
60+
61+
for ix in df.index:
62+
row = df.loc[ix,]
63+
64+
row_data = {}
65+
for col in row.index:
66+
cstr = str(row[col])
67+
if col in wrap_columns:
68+
wlen = wrap_columns[col]
69+
tw = textwrap.wrap(cstr,wlen) if not cstr.isspace() else [' ']
70+
else:
71+
tw = [cstr]
72+
row_data[col] = tw
73+
74+
cmax = max(row_data,key=lambda k: len(row_data[k]))
75+
rlen = len(row_data[cmax])
76+
for r in range(rlen):
77+
for col in row.index:
78+
extension = [' ']*(rlen - len(row_data[col]))
79+
row_data[col].extend(extension)
80+
column_data[col].append(row_data[col][r])
81+
ixstr = str(ix)+'.'+str(r) if r > 0 else str(ix)
82+
index.append(ixstr)
83+
84+
return pd.DataFrame(column_data,index=index)
85+
86+
WRAPLEN = 55
87+
88+
df = df_wrapcols(df,wrap_columns={'Description':WRAPLEN})
89+
print('===========================')
90+
print('dfnew1=',df)
91+
92+
93+
# print('===========================')
94+
# df.columns = [ ' '+col for col in df.columns ]
95+
96+
dividers = []
97+
for col in df.columns:
98+
dividers.append('-'*int(df[col].str.len().max()))
99+
dfd = pd.DataFrame(dividers).T
100+
dfd.columns = df.columns
101+
dfd.index = pd.Index(['---'])
102+
103+
print('===========================')
104+
105+
df = dfd.append(df)
106+
107+
fmts = {'Kwarg': make_left_formatter(df['Kwarg'].str.len().max()+1),
108+
'Description': make_left_formatter(WRAPLEN),
109+
'Default': make_left_formatter(8),
110+
}
111+
s = df.to_string(formatters=fmts,index=False,justify='left')
112+
113+
print('\n ',s.replace('\n','\n '))
114+
115+
print('===========================')
116+

src/mplfinance/__init__.py

+6-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import mplfinance._mpf_warnings
2-
from mplfinance.plotting import plot, make_addplot
3-
from mplfinance._styles import make_mpf_style, make_marketcolors
4-
from mplfinance._styles import available_styles, write_style_file
5-
from mplfinance._version import __version__
6-
from mplfinance._mplwraps import figure, show
2+
from mplfinance.plotting import plot, make_addplot
3+
from mplfinance._styles import make_mpf_style, make_marketcolors
4+
from mplfinance._styles import available_styles, write_style_file
5+
from mplfinance._version import __version__
6+
from mplfinance._mplwraps import figure, show
7+
from mplfinance._kwarg_help import kwarg_help

src/mplfinance/_arg_validators.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -274,13 +274,20 @@ def _kwarg_not_implemented(value):
274274
raise NotImplementedError('kwarg NOT implemented.')
275275

276276
def _validate_vkwargs_dict(vkwargs):
277-
# Check that we didn't make a typo in any of the things
278-
# that should be the same for all vkwargs dict items:
277+
"""
278+
Check that we didn't make a typo in any of the things
279+
that should be the same for all vkwargs dict items:
280+
281+
{kwarg : {'Default': ... , 'Description': ... , 'Validator': ...} }
282+
"""
279283
for key, value in vkwargs.items():
280-
if len(value) != 2:
281-
raise ValueError('Items != 2 in valid kwarg table, for kwarg "'+key+'"')
284+
# has been changed to 3 to support descriptions
285+
if len(value) != 3:
286+
raise ValueError('Items != 3 in valid kwarg table, for kwarg "'+key+'"')
282287
if 'Default' not in value:
283288
raise ValueError('Missing "Default" value for kwarg "'+key+'"')
289+
if 'Description' not in value:
290+
raise ValueError('Missing "Description" value for kwarg "'+key+'"')
284291
if 'Validator' not in value:
285292
raise ValueError('Missing "Validator" function for kwarg "'+key+'"')
286293

src/mplfinance/_kwarg_help.py

+153
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
import mplfinance as mpf
2+
import pandas as pd
3+
import textwrap
4+
5+
def df_wrapcols(df,wrap_columns=None):
6+
7+
if wrap_columns is None: return df
8+
if not isinstance(wrap_columns,dict):
9+
raise TypeError('wrap_columns must be a dict of column_names and wrap_lengths')
10+
11+
for col in wrap_columns:
12+
if col not in df.columns:
13+
raise ValueError('column "'+str(col)+'" not found in df.columns')
14+
15+
index = []
16+
column_data = {}
17+
for col in df.columns:
18+
column_data[col] = []
19+
20+
for ix in df.index:
21+
row = df.loc[ix,]
22+
23+
row_data = {}
24+
for col in row.index:
25+
cstr = str(row[col])
26+
if col in wrap_columns:
27+
wlen = wrap_columns[col]
28+
tw = textwrap.wrap(cstr,wlen) if not cstr.isspace() else [' ']
29+
else:
30+
tw = [cstr]
31+
row_data[col] = tw
32+
33+
cmax = max(row_data,key=lambda k: len(row_data[k]))
34+
rlen = len(row_data[cmax])
35+
for r in range(rlen):
36+
for col in row.index:
37+
extension = [' ']*(rlen - len(row_data[col]))
38+
row_data[col].extend(extension)
39+
column_data[col].append(row_data[col][r])
40+
ixstr = str(ix)+'.'+str(r) if r > 0 else str(ix)
41+
index.append(ixstr)
42+
43+
return pd.DataFrame(column_data,index=index)
44+
45+
def make_left_formatter(maxwidth):
46+
wm3 = maxwidth-3
47+
w = maxwidth
48+
def left_formatter(value):
49+
if not isinstance(value,str):
50+
return f'{value:<}'
51+
elif value[0:maxwidth] == '-'*maxwidth:
52+
return f'{value:<{w}.{w}s}'
53+
elif len(value) > maxwidth:
54+
return f'{value:<{wm3}.{wm3}s}...'
55+
else:
56+
return f'{value:<{w}.{w}s}'
57+
return left_formatter
58+
59+
60+
def kwarg_help( func_name=None, kwarg_names=None ):
61+
62+
func_kwarg_map = {
63+
'plot' : mpf.plotting._valid_plot_kwargs,
64+
'make_addplot' : mpf.plotting._valid_addplot_kwargs,
65+
'make_marketcolors' : mpf._styles._valid_make_marketcolors_kwargs,
66+
'make_mpf_style' : mpf._styles._valid_make_mpf_style_kwargs,
67+
'renko_params' : mpf._utils._valid_renko_kwargs,
68+
'pnf_params' : mpf._utils._valid_pnf_kwargs,
69+
'lines' : mpf._utils._valid_lines_kwargs,
70+
'scale_width_adjustment': mpf._widths._valid_scale_width_kwargs,
71+
'update_width_config': mpf._widths._valid_update_width_kwargs,
72+
}
73+
74+
func_kwarg_aliases = {
75+
'addplot' : mpf.plotting._valid_addplot_kwargs,
76+
'marketcolors' : mpf._styles._valid_make_marketcolors_kwargs,
77+
'mpf_style' : mpf._styles._valid_make_mpf_style_kwargs,
78+
'style' : mpf._styles._valid_make_mpf_style_kwargs,
79+
'renko' : mpf._utils._valid_renko_kwargs,
80+
'pnf' : mpf._utils._valid_pnf_kwargs,
81+
'hlines' : mpf._utils._valid_lines_kwargs,
82+
'alines' : mpf._utils._valid_lines_kwargs,
83+
'tlines' : mpf._utils._valid_lines_kwargs,
84+
'vlines' : mpf._utils._valid_lines_kwargs,
85+
}
86+
87+
if func_name is None:
88+
print('\nUsage: `kwarg_help(func_name)` or `kwarg_help(func_name,kwarg_names)`')
89+
print(' kwarg_help is available for the following func_names:')
90+
s = str(list(func_kwarg_map.keys()))
91+
text = textwrap.wrap(s,68)
92+
for t in text:
93+
print(' ',t)
94+
print()
95+
return
96+
97+
fkmap = {**func_kwarg_map, **func_kwarg_aliases}
98+
99+
if func_name not in fkmap:
100+
raise ValueError('Function name "'+func_name+'" NOT a valid function name')
101+
102+
if kwarg_names is not None and isinstance(kwarg_names,str):
103+
kwarg_names = [ kwarg_names, ]
104+
105+
if ( kwarg_names is not None
106+
and (not isinstance(kwarg_names,(list,tuple))
107+
or not all([isinstance(k,str) for k in kwarg_names])
108+
)
109+
):
110+
raise ValueError('kwarg_names must be a sequence (list,tuple) of strings')
111+
112+
vks = fkmap[func_name]()
113+
114+
df = (pd.DataFrame(vks).T).drop('Validator',axis=1)
115+
df.index.name = 'Kwarg'
116+
df.reset_index(inplace=True)
117+
118+
if kwarg_names is not None:
119+
for k in kwarg_names:
120+
if k not in df['Kwarg'].values:
121+
print(' Warning: "'+k+'" is not a valid `kwarg_name` for `func_name` "'+func_name,'"')
122+
df = df[ df['Kwarg'].isin(kwarg_names) ]
123+
if len(df) < 1:
124+
raise ValueError(' None of specified `kwarg_names` are valid for `func_name` "'+func_name,'"')
125+
126+
df['Default'] = ["'"+d+"'" if isinstance(d,str) else str(d) for d in df['Default']]
127+
128+
klen = df['Kwarg'].str.len().max()+1
129+
dlen = df['Default'].str.len().max()+1
130+
131+
wraplen = max( 40, 80-(klen+dlen) )
132+
df = df_wrapcols(df,wrap_columns={'Description':wraplen})
133+
134+
dividers = []
135+
for col in df.columns:
136+
dividers.append('-'*int(df[col].str.len().max()))
137+
dfd = pd.DataFrame(dividers).T
138+
dfd.columns = df.columns
139+
dfd.index = pd.Index(['---'])
140+
141+
df = dfd.append(df)
142+
143+
formatters = { 'Kwarg' : make_left_formatter( klen ),
144+
'Default' : make_left_formatter( dlen ),
145+
'Description' : make_left_formatter( wraplen ),
146+
}
147+
148+
print('\n ','-'*78)
149+
print(' Kwargs for func_name "'+func_name+'":')
150+
151+
s = df.to_string(formatters=formatters,index=False,justify='left')
152+
153+
print('\n ',s.replace('\n','\n '))

0 commit comments

Comments
 (0)