seolpyo-mplchart 0.1.0__tar.gz → 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of seolpyo-mplchart might be problematic. Click here for more details.

Files changed (20) hide show
  1. {seolpyo_mplchart-0.1.0/seolpyo_mplchart.egg-info → seolpyo_mplchart-0.1.1}/PKG-INFO +3 -3
  2. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/pyproject.toml +3 -3
  3. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart/cursor.py +45 -35
  4. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart/draw.py +21 -17
  5. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart/slider.py +6 -6
  6. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1/seolpyo_mplchart.egg-info}/PKG-INFO +3 -3
  7. seolpyo_mplchart-0.1.1/seolpyo_mplchart.egg-info/requires.txt +2 -0
  8. seolpyo_mplchart-0.1.0/seolpyo_mplchart.egg-info/requires.txt +0 -2
  9. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/MANIFEST.in +0 -0
  10. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/README.md +0 -0
  11. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart/__init__.py +0 -0
  12. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart/base.py +0 -0
  13. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart/data/apple.txt +0 -0
  14. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart/data/samsung.txt +0 -0
  15. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart/test.py +0 -0
  16. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart/utils.py +0 -0
  17. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart.egg-info/SOURCES.txt +0 -0
  18. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart.egg-info/dependency_links.txt +0 -0
  19. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/seolpyo_mplchart.egg-info/top_level.txt +0 -0
  20. {seolpyo_mplchart-0.1.0 → seolpyo_mplchart-0.1.1}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: seolpyo-mplchart
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Fast candlestick chart using Python. Includes navigator, slider, navigation, and text information display functions
5
5
  Author-email: white-seolpyo <white-seolpyo@naver.com>
6
6
  License: MIT License
@@ -22,7 +22,7 @@ Classifier: Programming Language :: Python :: 3.11
22
22
  Classifier: Programming Language :: Python :: 3.12
23
23
  Requires-Python: >=3.11
24
24
  Description-Content-Type: text/markdown
25
- Requires-Dist: matplotlib>=3.6.0
25
+ Requires-Dist: matplotlib>=3.7.0
26
26
  Requires-Dist: pandas>=2.0.0
27
27
 
28
28
  # Donation
@@ -1,16 +1,16 @@
1
1
  [build-system]
2
2
  requires = [
3
3
  "setuptools >= 65.0",
4
- "matplotlib >= 3.6.0",
4
+ "matplotlib >= 3.7.0",
5
5
  "pandas >= 2.0.0",
6
6
  ]
7
7
  build-backend = "setuptools.build_meta"
8
8
 
9
9
  [project]
10
10
  name = "seolpyo-mplchart"
11
- version = "0.1.0"
11
+ version = "0.1.1"
12
12
  dependencies = [
13
- "matplotlib >= 3.6.0",
13
+ "matplotlib >= 3.7.0",
14
14
  "pandas >= 2.0.0",
15
15
  ]
16
16
  license = {text = "MIT License"}
@@ -61,20 +61,27 @@ class CollectionMixin(DrawMixin):
61
61
  _set_key = {'rate', 'compare', 'rate_open', 'rate_high', 'rate_low', 'rate_volume',}
62
62
 
63
63
  class DataMixin(CollectionMixin):
64
- def _generate_data(self, df, sort_df=True, calc_ma=True):
65
- for i in ['date', 'Open', 'high', 'low', 'close', 'volume']:
64
+ def _generate_data(self, df, sort_df=True, calc_ma=True, calc_info=True):
65
+ for i in ('date', 'Open', 'high', 'low', 'close', 'volume'):
66
66
  v = getattr(self, i)
67
- if v in _set_key: raise Exception(f'you can not set "self.{i}" value in {_set_key}.\nself.{i}={v!r}')
67
+ if v in _set_key:
68
+ raise Exception(f'you can not set "self.{i}" value in {_set_key}.\nself.{i}={v!r}')
68
69
 
69
70
  super()._generate_data(df, sort_df, calc_ma)
70
71
  df = self.df
71
72
 
72
- df['rate'] = ((df[self.close] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
73
- df['compare'] = (df[self.close] - df[self.close].shift(1)).fillna(0)
74
- df['rate_open'] = ((df[self.Open] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
75
- df['rate_high'] = ((df[self.high] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
76
- df['rate_low'] = ((df[self.low] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
77
- df['rate_volume'] = ((df[self.volume] - df[self.volume].shift(1)) / df[self.volume].shift(1) * 100).__round__(2).fillna(0)
73
+ if not calc_info:
74
+ keys = set(df.keys())
75
+ for i in ('rate', 'compare', 'rate_open', 'rate_high', 'rate_low', 'rate_volume'):
76
+ if i not in keys:
77
+ raise Exception(f'"{i}" column not in DataFrame.\nadd column or set calc_info=True.')
78
+ else:
79
+ df['rate'] = ((df[self.close] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
80
+ df['compare'] = (df[self.close] - df[self.close].shift(1)).fillna(0)
81
+ df['rate_open'] = ((df[self.Open] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
82
+ df['rate_high'] = ((df[self.high] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
83
+ df['rate_low'] = ((df[self.low] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
84
+ df['rate_volume'] = ((df[self.volume] - df[self.volume].shift(1)) / df[self.volume].shift(1) * 100).__round__(2).fillna(0)
78
85
 
79
86
  self.df = df
80
87
  return
@@ -123,8 +130,10 @@ class LineMixin(DataMixin):
123
130
  self.canvas.blit()
124
131
  return
125
132
 
126
- def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True):
127
- super()._set_data(df, sort_df, calc_ma, change_lim)
133
+ def set_data(self, df, sort_df=True, calc_ma=True, change_lim=True, calc_info=True, *args, **kwargs):
134
+ return super().set_data(df, sort_df, calc_ma, change_lim, calc_info=calc_info, *args, **kwargs)
135
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, calc_info=True, *args, **kwargs):
136
+ super()._set_data(df, sort_df, calc_ma, change_lim, calc_info=calc_info, *args, **kwargs)
128
137
 
129
138
  self.vmin, self.vmax = (self.xmin, self.xmax)
130
139
  return
@@ -242,12 +251,12 @@ class LineMixin(DataMixin):
242
251
 
243
252
  class InfoMixin(LineMixin):
244
253
  fraction = False
245
- candleformat = '{}\n\n종가:  {}\n등락률: {}\n대비:  {}\n시가:  {}({})\n고가:  {}({})\n저가:  {}({})\n거래량: {}({})'
246
- volumeformat = '{}\n\n거래량   : {}\n거래량증가율: {}'
254
+ candleformat = '{dt}\n\n종가:  {close}\n등락률: {rate}\n대비:  {compare}\n시가:  {open}({rate_open})\n고가:  {high}({rate_high})\n저가:  {low}({rate_low})\n거래량: {volume}({rate_volume})'
255
+ volumeformat = '{dt}\n\n거래량   : {volume}\n거래량증가율: {rate_volume}'
247
256
  digit_price, digit_volume = (0, 0)
248
257
 
249
- def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True):
250
- super()._set_data(df, sort_df, calc_ma, change_lim)
258
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, calc_info=True, *args, **kwargs):
259
+ super()._set_data(df, sort_df, calc_ma, change_lim, calc_info, *args, **kwargs)
251
260
 
252
261
  # 슬라이더 날짜 텍스트 y 위치
253
262
  y = self._slider_ymax - (self._slider_ymax - self._slider_ymin) / 6
@@ -357,35 +366,35 @@ class InfoMixin(LineMixin):
357
366
  else: l = float_to_str(ld[0])
358
367
 
359
368
  text = self.candleformat.format(
360
- dt,
361
- f'{c:>{self._length_text}}{self.unit_price}',
362
- f'{r:>{self._length_text}}%',
363
- f'{com:>{self._length_text}}{self.unit_price}',
364
- f'{o:>{self._length_text}}{self.unit_price}', f'{Or:+06,.2f}%',
365
- f'{h:>{self._length_text}}{self.unit_price}', f'{hr:+06,.2f}%',
366
- f'{l:>{self._length_text}}{self.unit_price}', f'{lr:+06,.2f}%',
367
- f'{v:>{self._length_text}}{self.unit_volume}', f'{vr:+06,.2f}%',
369
+ dt=dt,
370
+ close=f'{c:>{self._length_text}}{self.unit_price}',
371
+ rate=f'{r:>{self._length_text}}%',
372
+ compare=f'{com:>{self._length_text}}{self.unit_price}',
373
+ open=f'{o:>{self._length_text}}{self.unit_price}', rate_open=f'{Or:+06,.2f}%',
374
+ high=f'{h:>{self._length_text}}{self.unit_price}', rate_high=f'{hr:+06,.2f}%',
375
+ low=f'{l:>{self._length_text}}{self.unit_price}', rate_low=f'{lr:+06,.2f}%',
376
+ volume=f'{v:>{self._length_text}}{self.unit_volume}', rate_volume=f'{vr:+06,.2f}%',
368
377
  )
369
378
  else:
370
379
  o, h, l, c = (float_to_str(o, self.digit_price), float_to_str(h, self.digit_price), float_to_str(l, self.digit_price), float_to_str(c, self.digit_price))
371
380
  com = float_to_str(compare, self.digit_price, plus=True)
372
381
 
373
382
  text = self.candleformat.format(
374
- dt,
375
- f'{c:>{self._length_text}}{self.unit_price}',
376
- f'{r:>{self._length_text}}%',
377
- f'{com:>{self._length_text}}{self.unit_price}',
378
- f'{o:>{self._length_text}}{self.unit_price}', f'{Or:+06,.2f}%',
379
- f'{h:>{self._length_text}}{self.unit_price}', f'{hr:+06,.2f}%',
380
- f'{l:>{self._length_text}}{self.unit_price}', f'{lr:+06,.2f}%',
381
- f'{v:>{self._length_text}}{self.unit_volume}', f'{vr:+06,.2f}%',
383
+ dt=dt,
384
+ close=f'{c:>{self._length_text}}{self.unit_price}',
385
+ rate=f'{r:>{self._length_text}}%',
386
+ compare=f'{com:>{self._length_text}}{self.unit_price}',
387
+ open=f'{o:>{self._length_text}}{self.unit_price}', rate_open=f'{Or:+06,.2f}%',
388
+ high=f'{h:>{self._length_text}}{self.unit_price}', rate_high=f'{hr:+06,.2f}%',
389
+ low=f'{l:>{self._length_text}}{self.unit_price}', rate_low=f'{lr:+06,.2f}%',
390
+ volume=f'{v:>{self._length_text}}{self.unit_volume}', rate_volume=f'{vr:+06,.2f}%',
382
391
  )
383
392
  else:
384
393
  vrate = f'{vr:+06,.2f}'
385
394
  text = self.volumeformat.format(
386
- dt,
387
- f'{v:>{self._length_text}}{self.unit_volume}',
388
- f'{vrate:>{self._length_text}}%',
395
+ dt=dt,
396
+ volume=f'{v:>{self._length_text}}{self.unit_volume}',
397
+ rate_volume=f'{vrate:>{self._length_text}}%',
389
398
  )
390
399
  return text
391
400
 
@@ -426,12 +435,13 @@ if __name__ == '__main__':
426
435
  n = 2600
427
436
  data = data[n:n+100]
428
437
  df = pd.DataFrame(data)
438
+ print(f'{df.keys()=}')
429
439
 
430
440
  t = time()
431
441
  c = CursorMixin()
432
442
  c.unit_price = '$'
433
443
  # c.fraction = True
434
- c.set_data(df=df)
444
+ c.set_data(df[['date', 'open', 'high', 'low', 'close', 'volume']])
435
445
  t2 = time() - t
436
446
  print(f'{t2=}')
437
447
  plt.show()
@@ -37,20 +37,21 @@ class DataMixin(Base):
37
37
  # https://matplotlib.org/stable/gallery/color/named_colors.html
38
38
  list_macolor = ('darkred', 'fuchsia', 'olive', 'orange', 'navy', 'darkmagenta', 'limegreen', 'darkcyan',)
39
39
 
40
- color_up = '#fe3032'
41
- color_down = '#0095ff'
40
+ color_up, color_down = ('#fe3032', '#0095ff')
42
41
  color_flat = 'k'
43
- color_up_down = 'w'
44
- color_down_up = 'w'
42
+ color_up_down, color_down_up = ('w', 'w')
45
43
  colors_volume = '#1f77b4'
46
44
 
47
- def _generate_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True):
48
- for i in ['date', 'Open', 'high', 'low', 'close', 'volume']:
45
+ candlewidth_half, volumewidth_half = (0.3, 0.36)
46
+
47
+ def _generate_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, **_):
48
+ for i in ('date', 'Open', 'high', 'low', 'close', 'volume'):
49
49
  k: str = getattr(self, i)
50
50
  if k in _set_key: raise Exception(f'you can not set "self.{i}" value in {_set_key}.\nself.{i}={k!r}')
51
51
  if i != 'date':
52
52
  dtype = df[k].dtype
53
- if not isinstance(dtype, (np.dtypes.Float64DType, np.dtypes.Int64DType, np.dtypes.Float32DType, np.dtypes.Int32DType)): raise TypeError(f'Data column type must be "float64" or "int64" or "float32" or "int32".(excluding "date" column)\ndf[{k!r}].dtype={dtype!r}')
53
+ if not isinstance(dtype, (np.dtypes.Float64DType, np.dtypes.Int64DType, np.dtypes.Float32DType, np.dtypes.Int32DType)):
54
+ raise TypeError(f'column dtype must be one of "float64" or "int64" or "float32" or "int32".(excluding "date" column)\ndf[{k!r}].dtype={dtype!r}')
54
55
 
55
56
  # DataFrame 정렬
56
57
  if sort_df:
@@ -59,14 +60,17 @@ class DataMixin(Base):
59
60
  if not self.list_ma: self.list_ma = tuple()
60
61
  if calc_ma:
61
62
  for i in self.list_ma: df[f'ma{i}'] = df[self.close].rolling(i).mean()
63
+ else:
64
+ keys = set(df.keys())
65
+ for i in self.list_ma:
66
+ if f'ma{i}' not in keys:
67
+ raise Exception(f'"ma{i}" column not in DataFrame.\nadd column or set calc_ma=True.')
62
68
 
63
- candlewidth_half = 0.3
64
- volumewidth_half = 0.36
65
69
  df['x'] = df.index + 0.5
66
- df['left'] = df['x'] - candlewidth_half
67
- df['right'] = df['x'] + candlewidth_half
68
- df['vleft'] = df['x'] - volumewidth_half
69
- df['vright'] = df['x'] + volumewidth_half
70
+ df['left'] = df['x'] - self.candlewidth_half
71
+ df['right'] = df['x'] + self.candlewidth_half
72
+ df['vleft'] = df['x'] - self.volumewidth_half
73
+ df['vright'] = df['x'] + self.volumewidth_half
70
74
 
71
75
  df['top'] = np.where(df[self.Open] <= df[self.close], df[self.close], df[self.Open])
72
76
  df['top'] = np.where(df[self.close] < df[self.Open], df[self.Open], df[self.close])
@@ -303,12 +307,12 @@ class BackgroundMixin(CollectionMixin):
303
307
  return
304
308
 
305
309
  class DrawMixin(BackgroundMixin):
306
- def set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True):
307
- self._set_data(df, sort_df, calc_ma, change_lim)
310
+ def set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, *_, **kwargs):
311
+ self._set_data(df, sort_df, calc_ma, change_lim, **kwargs)
308
312
  return self.df
309
313
 
310
- def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True):
311
- self._generate_data(df, sort_df, calc_ma)
314
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, *_, **kwargs):
315
+ self._generate_data(df, sort_df, calc_ma, **kwargs)
312
316
  self._set_collection()
313
317
  self._draw_collection(change_lim)
314
318
  return
@@ -43,8 +43,8 @@ class NavgatorMixin(Mixin):
43
43
  self.ax_slider.add_artist(self.navigator)
44
44
  return
45
45
 
46
- def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True):
47
- super()._set_data(df, sort_df, calc_ma, False)
46
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, calc_info=True):
47
+ super()._set_data(df, sort_df, calc_ma, change_lim, calc_info)
48
48
 
49
49
  # 네비게이터 라인 선택 영역
50
50
  xsub = self.xmax - self.xmin
@@ -156,8 +156,8 @@ class BackgroundMixin(NavgatorMixin):
156
156
 
157
157
 
158
158
  class DrawMixin(BackgroundMixin):
159
- def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True):
160
- super()._set_data(df, sort_df, calc_ma, change_lim)
159
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, calc_info=True):
160
+ super()._set_data(df, sort_df, calc_ma, change_lim, calc_info)
161
161
 
162
162
  # 네비게이터 높이 설정
163
163
  ysub = self._slider_ymax - self._slider_ymin
@@ -334,8 +334,8 @@ class SimpleMixin(LimMixin):
334
334
  self.ax_volume.add_collection(self.blitvolume)
335
335
  return
336
336
 
337
- def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True):
338
- super()._set_data(df, sort_df, calc_ma, False)
337
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, calc_info=True):
338
+ super()._set_data(df, sort_df, calc_ma, False, calc_info)
339
339
 
340
340
  seg = self.df[['x', self.high, 'x', self.low]].values
341
341
  seg = seg.reshape(seg.shape[0], 2, 2)
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: seolpyo-mplchart
3
- Version: 0.1.0
3
+ Version: 0.1.1
4
4
  Summary: Fast candlestick chart using Python. Includes navigator, slider, navigation, and text information display functions
5
5
  Author-email: white-seolpyo <white-seolpyo@naver.com>
6
6
  License: MIT License
@@ -22,7 +22,7 @@ Classifier: Programming Language :: Python :: 3.11
22
22
  Classifier: Programming Language :: Python :: 3.12
23
23
  Requires-Python: >=3.11
24
24
  Description-Content-Type: text/markdown
25
- Requires-Dist: matplotlib>=3.6.0
25
+ Requires-Dist: matplotlib>=3.7.0
26
26
  Requires-Dist: pandas>=2.0.0
27
27
 
28
28
  # Donation
@@ -0,0 +1,2 @@
1
+ matplotlib>=3.7.0
2
+ pandas>=2.0.0
@@ -1,2 +0,0 @@
1
- matplotlib>=3.6.0
2
- pandas>=2.0.0