seolpyo-mplchart 0.1.0__py3-none-any.whl → 0.1.3__py3-none-any.whl

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.

@@ -70,8 +70,8 @@ class Chart(CM):
70
70
  textboxKwargs: Options that apply to the information text box. dufault dict(boxstyle='round', facecolor='w')
71
71
 
72
72
  fraction: Decide whether to express information as a fraction. default False
73
- candleformat: Candle information text format. default '{}\n\n종가:  {}\n등락률: {}\n대비:  {}\n시가:  {}({})\n고가:  {}({})\n저가:  {}({})\n거래량: {}({})'
74
- volumeformat: Volume information text format. default '{}\n\n거래량   : {}\n거래량증가율: {}'
73
+ candleformat: Candle information text format. default '{dt}\n\n종가:  {close}\n등락률: {rate}\n대비:  {compare}\n시가:  {open}({rate_open})\n고가:  {high}({rate_high})\n저가:  {low}({rate_low})\n거래량: {volume}({rate_volume})'
74
+ volumeformat: Volume information text format. default '{dt}\n\n거래량   : {volume}\n거래량증가율: {rate_volume}'
75
75
  digit_price, digit_volume: Number of decimal places expressed in informational text. default (0, 0)
76
76
 
77
77
  min_distance: Minimum number of candles that can be selected with the slider. default 30
@@ -14,6 +14,9 @@ class Mixin:
14
14
  def on_draw(self, e):
15
15
  "This function works if draw event active."
16
16
  return
17
+ def on_move(self, e):
18
+ "This function works if mouse move event active."
19
+ return
17
20
 
18
21
 
19
22
  class CollectionMixin(DrawMixin):
@@ -61,20 +64,27 @@ class CollectionMixin(DrawMixin):
61
64
  _set_key = {'rate', 'compare', 'rate_open', 'rate_high', 'rate_low', 'rate_volume',}
62
65
 
63
66
  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']:
67
+ def _generate_data(self, df, sort_df=True, calc_ma=True, calc_info=True):
68
+ for i in ('date', 'Open', 'high', 'low', 'close', 'volume'):
66
69
  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}')
70
+ if v in _set_key:
71
+ raise Exception(f'you can not set "self.{i}" value in {_set_key}.\nself.{i}={v!r}')
68
72
 
69
73
  super()._generate_data(df, sort_df, calc_ma)
70
74
  df = self.df
71
75
 
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)
76
+ if not calc_info:
77
+ keys = set(df.keys())
78
+ for i in ('rate', 'compare', 'rate_open', 'rate_high', 'rate_low', 'rate_volume'):
79
+ if i not in keys:
80
+ raise Exception(f'"{i}" column not in DataFrame.\nadd column or set calc_info=True.')
81
+ else:
82
+ df['rate'] = ((df[self.close] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
83
+ df['compare'] = (df[self.close] - df[self.close].shift(1)).fillna(0)
84
+ df['rate_open'] = ((df[self.Open] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
85
+ df['rate_high'] = ((df[self.high] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
86
+ df['rate_low'] = ((df[self.low] - df[self.close].shift(1)) / df[self.close] * 100).__round__(2).fillna(0)
87
+ df['rate_volume'] = ((df[self.volume] - df[self.volume].shift(1)) / df[self.volume].shift(1) * 100).__round__(2).fillna(0)
78
88
 
79
89
  self.df = df
80
90
  return
@@ -123,8 +133,10 @@ class LineMixin(DataMixin):
123
133
  self.canvas.blit()
124
134
  return
125
135
 
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)
136
+ def set_data(self, df, sort_df=True, calc_ma=True, change_lim=True, calc_info=True, *args, **kwargs):
137
+ return super().set_data(df, sort_df, calc_ma, change_lim, calc_info=calc_info, *args, **kwargs)
138
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, calc_info=True, *args, **kwargs):
139
+ super()._set_data(df, sort_df, calc_ma, change_lim, calc_info=calc_info, *args, **kwargs)
128
140
 
129
141
  self.vmin, self.vmax = (self.xmin, self.xmax)
130
142
  return
@@ -242,12 +254,12 @@ class LineMixin(DataMixin):
242
254
 
243
255
  class InfoMixin(LineMixin):
244
256
  fraction = False
245
- candleformat = '{}\n\n종가:  {}\n등락률: {}\n대비:  {}\n시가:  {}({})\n고가:  {}({})\n저가:  {}({})\n거래량: {}({})'
246
- volumeformat = '{}\n\n거래량   : {}\n거래량증가율: {}'
257
+ 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})'
258
+ volumeformat = '{dt}\n\n거래량   : {volume}\n거래량증가율: {rate_volume}'
247
259
  digit_price, digit_volume = (0, 0)
248
260
 
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)
261
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, calc_info=True, *args, **kwargs):
262
+ super()._set_data(df, sort_df, calc_ma, change_lim, calc_info, *args, **kwargs)
251
263
 
252
264
  # 슬라이더 날짜 텍스트 y 위치
253
265
  y = self._slider_ymax - (self._slider_ymax - self._slider_ymin) / 6
@@ -357,35 +369,35 @@ class InfoMixin(LineMixin):
357
369
  else: l = float_to_str(ld[0])
358
370
 
359
371
  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}%',
372
+ dt=dt,
373
+ close=f'{c:>{self._length_text}}{self.unit_price}',
374
+ rate=f'{r:>{self._length_text}}%',
375
+ compare=f'{com:>{self._length_text}}{self.unit_price}',
376
+ open=f'{o:>{self._length_text}}{self.unit_price}', rate_open=f'{Or:+06,.2f}%',
377
+ high=f'{h:>{self._length_text}}{self.unit_price}', rate_high=f'{hr:+06,.2f}%',
378
+ low=f'{l:>{self._length_text}}{self.unit_price}', rate_low=f'{lr:+06,.2f}%',
379
+ volume=f'{v:>{self._length_text}}{self.unit_volume}', rate_volume=f'{vr:+06,.2f}%',
368
380
  )
369
381
  else:
370
382
  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
383
  com = float_to_str(compare, self.digit_price, plus=True)
372
384
 
373
385
  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}%',
386
+ dt=dt,
387
+ close=f'{c:>{self._length_text}}{self.unit_price}',
388
+ rate=f'{r:>{self._length_text}}%',
389
+ compare=f'{com:>{self._length_text}}{self.unit_price}',
390
+ open=f'{o:>{self._length_text}}{self.unit_price}', rate_open=f'{Or:+06,.2f}%',
391
+ high=f'{h:>{self._length_text}}{self.unit_price}', rate_high=f'{hr:+06,.2f}%',
392
+ low=f'{l:>{self._length_text}}{self.unit_price}', rate_low=f'{lr:+06,.2f}%',
393
+ volume=f'{v:>{self._length_text}}{self.unit_volume}', rate_volume=f'{vr:+06,.2f}%',
382
394
  )
383
395
  else:
384
396
  vrate = f'{vr:+06,.2f}'
385
397
  text = self.volumeformat.format(
386
- dt,
387
- f'{v:>{self._length_text}}{self.unit_volume}',
388
- f'{vrate:>{self._length_text}}%',
398
+ dt=dt,
399
+ volume=f'{v:>{self._length_text}}{self.unit_volume}',
400
+ rate_volume=f'{vrate:>{self._length_text}}%',
389
401
  )
390
402
  return text
391
403
 
@@ -403,10 +415,6 @@ class Chart(CursorMixin, CM, Mixin):
403
415
  self.on_pick(e)
404
416
  return super()._on_pick(e)
405
417
 
406
- def _blit(self):
407
- super()._blit()
408
- return self.on_blit()
409
-
410
418
  def _on_move(self, e):
411
419
  super()._on_move(e)
412
420
  return self.on_move(e)
@@ -426,12 +434,13 @@ if __name__ == '__main__':
426
434
  n = 2600
427
435
  data = data[n:n+100]
428
436
  df = pd.DataFrame(data)
437
+ print(f'{df.keys()=}')
429
438
 
430
439
  t = time()
431
440
  c = CursorMixin()
432
441
  c.unit_price = '$'
433
442
  # c.fraction = True
434
- c.set_data(df=df)
443
+ c.set_data(df[['date', 'open', 'high', 'low', 'close', 'volume']])
435
444
  t2 = time() - t
436
445
  print(f'{t2=}')
437
446
  plt.show()
seolpyo_mplchart/draw.py CHANGED
@@ -9,15 +9,9 @@ from .base import Base
9
9
 
10
10
 
11
11
  class Mixin:
12
- def on_blit(self):
13
- "This function works after cavas.blit()."
14
- return
15
12
  def on_draw(self, e):
16
13
  "This function works if draw event active."
17
14
  return
18
- def on_move(self, e):
19
- "This function works if mouse move event active."
20
- return
21
15
  def on_pick(self, e):
22
16
  "This function works if pick event active."
23
17
  return
@@ -37,20 +31,21 @@ class DataMixin(Base):
37
31
  # https://matplotlib.org/stable/gallery/color/named_colors.html
38
32
  list_macolor = ('darkred', 'fuchsia', 'olive', 'orange', 'navy', 'darkmagenta', 'limegreen', 'darkcyan',)
39
33
 
40
- color_up = '#fe3032'
41
- color_down = '#0095ff'
34
+ color_up, color_down = ('#fe3032', '#0095ff')
42
35
  color_flat = 'k'
43
- color_up_down = 'w'
44
- color_down_up = 'w'
36
+ color_up_down, color_down_up = ('w', 'w')
45
37
  colors_volume = '#1f77b4'
46
38
 
47
- def _generate_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True):
48
- for i in ['date', 'Open', 'high', 'low', 'close', 'volume']:
39
+ candlewidth_half, volumewidth_half = (0.3, 0.36)
40
+
41
+ def _generate_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, **_):
42
+ for i in ('date', 'Open', 'high', 'low', 'close', 'volume'):
49
43
  k: str = getattr(self, i)
50
44
  if k in _set_key: raise Exception(f'you can not set "self.{i}" value in {_set_key}.\nself.{i}={k!r}')
51
45
  if i != 'date':
52
46
  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}')
47
+ if not isinstance(dtype, (np.dtypes.Float64DType, np.dtypes.Int64DType, np.dtypes.Float32DType, np.dtypes.Int32DType)):
48
+ 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
49
 
55
50
  # DataFrame 정렬
56
51
  if sort_df:
@@ -59,14 +54,17 @@ class DataMixin(Base):
59
54
  if not self.list_ma: self.list_ma = tuple()
60
55
  if calc_ma:
61
56
  for i in self.list_ma: df[f'ma{i}'] = df[self.close].rolling(i).mean()
57
+ else:
58
+ keys = set(df.keys())
59
+ for i in self.list_ma:
60
+ if f'ma{i}' not in keys:
61
+ raise Exception(f'"ma{i}" column not in DataFrame.\nadd column or set calc_ma=True.')
62
62
 
63
- candlewidth_half = 0.3
64
- volumewidth_half = 0.36
65
63
  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
64
+ df['left'] = df['x'] - self.candlewidth_half
65
+ df['right'] = df['x'] + self.candlewidth_half
66
+ df['vleft'] = df['x'] - self.volumewidth_half
67
+ df['vright'] = df['x'] + self.volumewidth_half
70
68
 
71
69
  df['top'] = np.where(df[self.Open] <= df[self.close], df[self.close], df[self.Open])
72
70
  df['top'] = np.where(df[self.close] < df[self.Open], df[self.Open], df[self.close])
@@ -303,12 +301,12 @@ class BackgroundMixin(CollectionMixin):
303
301
  return
304
302
 
305
303
  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)
304
+ def set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, *_, **kwargs):
305
+ self._set_data(df, sort_df, calc_ma, change_lim, **kwargs)
308
306
  return self.df
309
307
 
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)
308
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, *_, **kwargs):
309
+ self._generate_data(df, sort_df, calc_ma, **kwargs)
312
310
  self._set_collection()
313
311
  self._draw_collection(change_lim)
314
312
  return
@@ -6,15 +6,7 @@ import pandas as pd
6
6
  from .cursor import CursorMixin, Chart as CM
7
7
 
8
8
 
9
- def get_wickline(x: pd.Series):
10
- v = x.values
11
- return ((v[0], v[1]), (v[0], v[2]))
12
- def get_volumeline(x: pd.Series):
13
- v = x.values
14
- return ((v[0], 0), (v[0], v[1]))
15
-
16
-
17
- class Mixin(CursorMixin):
9
+ class Mixin:
18
10
  def on_click(self, e):
19
11
  "This function works if mouse button click event active."
20
12
  return
@@ -26,7 +18,7 @@ class Mixin(CursorMixin):
26
18
  return
27
19
 
28
20
 
29
- class NavgatorMixin(Mixin):
21
+ class NavgatorMixin(CursorMixin):
30
22
  min_distance = 30
31
23
  color_navigatorline = '#1e78ff'
32
24
  color_navigator = 'k'
@@ -43,8 +35,8 @@ class NavgatorMixin(Mixin):
43
35
  self.ax_slider.add_artist(self.navigator)
44
36
  return
45
37
 
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)
38
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, calc_info=True):
39
+ super()._set_data(df, sort_df, calc_ma, change_lim, calc_info)
48
40
 
49
41
  # 네비게이터 라인 선택 영역
50
42
  xsub = self.xmax - self.xmin
@@ -156,8 +148,8 @@ class BackgroundMixin(NavgatorMixin):
156
148
 
157
149
 
158
150
  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)
151
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, calc_info=True):
152
+ super()._set_data(df, sort_df, calc_ma, change_lim, calc_info)
161
153
 
162
154
  # 네비게이터 높이 설정
163
155
  ysub = self._slider_ymax - self._slider_ymin
@@ -319,6 +311,7 @@ class SimpleMixin(LimMixin):
319
311
  simpler = False
320
312
  limit_volume = 1_500
321
313
  default_left, default_right = (180, 10)
314
+ _draw_blit = False
322
315
 
323
316
  def __init__(self, *args, **kwargs):
324
317
  super().__init__(*args, **kwargs)
@@ -334,8 +327,8 @@ class SimpleMixin(LimMixin):
334
327
  self.ax_volume.add_collection(self.blitvolume)
335
328
  return
336
329
 
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)
330
+ def _set_data(self, df: pd.DataFrame, sort_df=True, calc_ma=True, change_lim=True, calc_info=True):
331
+ super()._set_data(df, sort_df, calc_ma, False, calc_info)
339
332
 
340
333
  seg = self.df[['x', self.high, 'x', self.low]].values
341
334
  seg = seg.reshape(seg.shape[0], 2, 2)
@@ -369,19 +362,15 @@ class SimpleMixin(LimMixin):
369
362
  self.ax_price.xaxis.draw(renderer)
370
363
  self.ax_price.yaxis.draw(renderer)
371
364
 
372
- left, right = self._navcoordinate
373
- Range = right - left
374
365
  if self.simpler:
375
- if Range < 1_000: self.blitcandle.draw(renderer)
376
- else: self.priceline.draw(renderer)
366
+ if self._draw_blit: self.priceline.draw(renderer)
367
+ else: self.blitcandle.draw(renderer)
377
368
  elif self.candle_on_ma:
378
369
  self.macollection.draw(renderer)
379
- if 2_500 < Range: self.priceline.draw(renderer)
380
- elif 800 < Range or 9_999 < self.xmax: self.blitcandle.draw(renderer)
370
+ if self._draw_blit: self.blitcandle.draw(renderer)
381
371
  else: self.candlecollection.draw(renderer)
382
372
  else:
383
- if 2_500 < Range: self.priceline.draw(renderer)
384
- elif 800 < Range or 9_999 < self.xmax: self.blitcandle.draw(renderer)
373
+ if self._draw_blit: self.blitcandle.draw(renderer)
385
374
  else: self.candlecollection.draw(renderer)
386
375
  self.macollection.draw(renderer)
387
376
 
@@ -477,9 +466,13 @@ class ClickMixin(SimpleMixin):
477
466
  self._change_coordinate()
478
467
  if self.is_click:
479
468
  nsub = self._navcoordinate[1] - self._navcoordinate[0]
480
- if self.min_distance <= nsub: self._lim()
481
469
  if self.is_move: self._set_navigator(*self._navcoordinate)
482
- elif self.intx is not None: self._set_navigator(self._x_click, self.intx)
470
+ else:
471
+ self._draw_blit = 900 < nsub
472
+ if self.intx is not None: self._set_navigator(self._x_click, self.intx)
473
+
474
+ if self.min_distance <= nsub: self._lim()
475
+
483
476
  self.navigator.draw(self.canvas.renderer)
484
477
  self._draw_blit_artist()
485
478
  self._slider_move_action(e)
@@ -514,6 +507,10 @@ class Chart(SliderMixin, CM, Mixin):
514
507
  self.on_pick(e)
515
508
  return super()._on_pick(e)
516
509
 
510
+ def _on_move(self, e):
511
+ super()._on_move(e)
512
+ return self.on_move(e)
513
+
517
514
  def _draw_artist(self):
518
515
  super()._draw_artist()
519
516
  return self.draw_artist()
@@ -521,13 +518,12 @@ class Chart(SliderMixin, CM, Mixin):
521
518
  super()._draw_blit_artist()
522
519
  return self.draw_artist()
523
520
 
524
- def _blit(self):
525
- super()._blit()
526
- return self.on_blit()
527
-
528
- def _on_move(self, e):
529
- super()._on_move(e)
530
- return self.on_move(e)
521
+ def _on_click(self, e):
522
+ super()._on_click(e)
523
+ return self.on_click(e)
524
+ def _on_release(self, e):
525
+ super()._on_release(e)
526
+ return self.on_release(e)
531
527
 
532
528
 
533
529
  if __name__ == '__main__':
@@ -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.3
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
@@ -38,10 +38,12 @@ Ethereum: 0x1c5fb8a5e0b1153cd4116c91736bd16fabf83520
38
38
 
39
39
 
40
40
  # Sample
41
- ![sample gif](https://github.com/user-attachments/assets/f1732891-d458-4c2d-a6bf-a17a4c549af6)
41
+ <img alt="sample gif" src="https://github.com/white-seolpyo/seolpyo-mplchart/blob/main/images/sample.gif?raw=true">
42
42
 
43
- ![tkinter sample gif](https://github.com/user-attachments/assets/b9bd451c-71a7-4295-9bcc-0d2f7d440bbd)
43
+ <img alt="tkinter sample gif" src="https://github.com/white-seolpyo/seolpyo-mplchart/blob/main/images/with%20tkinter.gif?raw=true">
44
44
 
45
45
  ![english sample](https://raw.githubusercontent.com/white-seolpyo/seolpyo-mplchart/refs/heads/main/images/change%20format.png)
46
46
 
47
47
  ![korean sample](https://github.com/white-seolpyo/seolpyo-mplchart/blob/main/images/sample%20kor.png?raw=true)
48
+
49
+ <img alt="40,000 sample" src="https://github.com/white-seolpyo/seolpyo-mplchart/blob/main/images/40000.gif?raw=true">
@@ -0,0 +1,13 @@
1
+ seolpyo_mplchart/__init__.py,sha256=FiuciCaX9lU12gwuDBYUNw0yLD06p4o7o19kR5jGips,5248
2
+ seolpyo_mplchart/base.py,sha256=vQ4OOBm3nGwjJ4wjDLaD_3LGxYzlP6AWpI6SZrZiwnQ,3600
3
+ seolpyo_mplchart/cursor.py,sha256=KSyYXJ1qVFgvrFBEhO8cazcZCxoJWqBAw0WvyVs9gNk,18405
4
+ seolpyo_mplchart/draw.py,sha256=NJH1dnmfepafMlc7K2ccwZbv0FDS3ItSiirCq4gMlOI,13145
5
+ seolpyo_mplchart/slider.py,sha256=R29vyNAdJkLEXgpP4hxe9O0WoLgoOnPOUHuKFNpdcnw,19601
6
+ seolpyo_mplchart/test.py,sha256=cW2hoaVbRtoSXlpmA4i1BKHBjI3-FAqYq__kryxkrC8,1007
7
+ seolpyo_mplchart/utils.py,sha256=-8cq4-WwiqKQxtwu3NPxOVTDDvoWH28tu4OTWr4hPTg,1208
8
+ seolpyo_mplchart/data/apple.txt,sha256=0izAfweu1lLsC0IwVthdVlo9reG8KGbKGTSX5knI5Zc,1380864
9
+ seolpyo_mplchart/data/samsung.txt,sha256=UejaSkbzr4E5K3lkelCT0yJiWUPfmViBEaTyoXyphIs,2476424
10
+ seolpyo_mplchart-0.1.3.dist-info/METADATA,sha256=Srf62CYZXlFvCYw4xqVy6DFtcEmun_dV3FymQXdzQyo,2347
11
+ seolpyo_mplchart-0.1.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
12
+ seolpyo_mplchart-0.1.3.dist-info/top_level.txt,sha256=KgqFn7rKWize7OjMaTCHxKm9ie6vqnyb5c8fN7y_tSo,17
13
+ seolpyo_mplchart-0.1.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.7.0)
2
+ Generator: setuptools (75.8.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
@@ -1,13 +0,0 @@
1
- seolpyo_mplchart/__init__.py,sha256=HITw-PVvJA4AHOO_gOAsbBxNvEbou-JLtivnKA_dn0A,5157
2
- seolpyo_mplchart/base.py,sha256=vQ4OOBm3nGwjJ4wjDLaD_3LGxYzlP6AWpI6SZrZiwnQ,3600
3
- seolpyo_mplchart/cursor.py,sha256=_Pzg8WvfOpZYzN5uNLO9LH2wrRB_gZTNGkqmzsjaaPc,17309
4
- seolpyo_mplchart/draw.py,sha256=yl813StbNuWC0_3QfS9ECvc0Z5buaIudsqR_qW8d3f4,13021
5
- seolpyo_mplchart/slider.py,sha256=K-vPj2dsSyXZDELrgn6Ry5VqORgUc65gS2SsTFm5TmE,19725
6
- seolpyo_mplchart/test.py,sha256=cW2hoaVbRtoSXlpmA4i1BKHBjI3-FAqYq__kryxkrC8,1007
7
- seolpyo_mplchart/utils.py,sha256=-8cq4-WwiqKQxtwu3NPxOVTDDvoWH28tu4OTWr4hPTg,1208
8
- seolpyo_mplchart/data/apple.txt,sha256=0izAfweu1lLsC0IwVthdVlo9reG8KGbKGTSX5knI5Zc,1380864
9
- seolpyo_mplchart/data/samsung.txt,sha256=UejaSkbzr4E5K3lkelCT0yJiWUPfmViBEaTyoXyphIs,2476424
10
- seolpyo_mplchart-0.1.0.dist-info/METADATA,sha256=W3N4J-vLlzw7Cx_t1WiGBDx2g0eiXdf5VlPoe0RVLDw,2176
11
- seolpyo_mplchart-0.1.0.dist-info/WHEEL,sha256=A3WOREP4zgxI0fKrHUG8DC8013e3dK3n7a6HDbcEIwE,91
12
- seolpyo_mplchart-0.1.0.dist-info/top_level.txt,sha256=KgqFn7rKWize7OjMaTCHxKm9ie6vqnyb5c8fN7y_tSo,17
13
- seolpyo_mplchart-0.1.0.dist-info/RECORD,,