seolpyo-mplchart 1.3.1.2__py3-none-any.whl → 1.4.0__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.
- seolpyo_mplchart/__init__.py +8 -8
- seolpyo_mplchart/_cursor.py +221 -181
- seolpyo_mplchart/_draw.py +211 -235
- seolpyo_mplchart/_slider.py +136 -137
- {seolpyo_mplchart-1.3.1.2.dist-info → seolpyo_mplchart-1.4.0.dist-info}/METADATA +1 -1
- {seolpyo_mplchart-1.3.1.2.dist-info → seolpyo_mplchart-1.4.0.dist-info}/RECORD +8 -8
- {seolpyo_mplchart-1.3.1.2.dist-info → seolpyo_mplchart-1.4.0.dist-info}/WHEEL +0 -0
- {seolpyo_mplchart-1.3.1.2.dist-info → seolpyo_mplchart-1.4.0.dist-info}/top_level.txt +0 -0
seolpyo_mplchart/_slider.py
CHANGED
|
@@ -90,7 +90,7 @@ class PlotMixin(BM):
|
|
|
90
90
|
|
|
91
91
|
class CollectionMixin(PlotMixin):
|
|
92
92
|
min_distance = 30
|
|
93
|
-
color_navigator_line = '#
|
|
93
|
+
color_navigator_line = '#1E78FF'
|
|
94
94
|
color_navigator_cover = 'k'
|
|
95
95
|
|
|
96
96
|
def _add_collection(self):
|
|
@@ -100,15 +100,15 @@ class CollectionMixin(PlotMixin):
|
|
|
100
100
|
self.ax_slider.add_artist(self.collection_slider)
|
|
101
101
|
|
|
102
102
|
# 슬라이더 네비게이터
|
|
103
|
-
self.
|
|
104
|
-
self.ax_slider.add_artist(self.
|
|
103
|
+
self.collection_navigator = LineCollection([], animated=True, edgecolors=[self.color_navigator_cover, self.color_navigator_line], alpha=(0.3, 1.0))
|
|
104
|
+
self.ax_slider.add_artist(self.collection_navigator)
|
|
105
105
|
|
|
106
106
|
lineKwargs = {'edgecolor': 'k', 'linewidth': 1, 'linestyle': '-'}
|
|
107
107
|
lineKwargs.update(self.lineKwargs)
|
|
108
108
|
lineKwargs.update({'segments': [], 'animated': True})
|
|
109
109
|
|
|
110
|
-
self.
|
|
111
|
-
self.ax_slider.add_artist(self.
|
|
110
|
+
self.collection_slider_vline = LineCollection(**lineKwargs)
|
|
111
|
+
self.ax_slider.add_artist(self.collection_slider_vline)
|
|
112
112
|
|
|
113
113
|
textboxKwargs = {'boxstyle': 'round', 'facecolor': 'w'}
|
|
114
114
|
textboxKwargs.update(self.textboxKwargs)
|
|
@@ -116,13 +116,17 @@ class CollectionMixin(PlotMixin):
|
|
|
116
116
|
textKwargs.update({'animated': True, 'bbox': textboxKwargs, 'horizontalalignment': '', 'verticalalignment': ''})
|
|
117
117
|
(textKwargs.pop('horizontalalignment'), textKwargs.pop('verticalalignment'))
|
|
118
118
|
|
|
119
|
-
self.
|
|
120
|
-
self.ax_slider.add_artist(self.
|
|
119
|
+
self.artist_text_slider = Text(**textKwargs, horizontalalignment='center', verticalalignment='top')
|
|
120
|
+
self.ax_slider.add_artist(self.artist_text_slider)
|
|
121
121
|
return
|
|
122
122
|
|
|
123
|
-
def
|
|
124
|
-
super().
|
|
123
|
+
def _create_segments(self):
|
|
124
|
+
super()._create_segments()
|
|
125
125
|
|
|
126
|
+
self._create_slider_segment()
|
|
127
|
+
return
|
|
128
|
+
|
|
129
|
+
def _create_slider_segment(self):
|
|
126
130
|
keys = []
|
|
127
131
|
for i in reversed(self.list_ma):
|
|
128
132
|
keys.append('x')
|
|
@@ -131,11 +135,13 @@ class CollectionMixin(PlotMixin):
|
|
|
131
135
|
segment_slider = self.df[keys + ['x', self.close] ].values
|
|
132
136
|
segment_slider = segment_slider.reshape(segment_slider.shape[0], len(self.list_ma)+1, 2).swapaxes(0, 1)
|
|
133
137
|
self.collection_slider.set_segments(segment_slider)
|
|
134
|
-
|
|
138
|
+
linewidth = [1 for _ in self.list_ma]
|
|
139
|
+
self.collection_slider.set_linewidth(linewidth + [2.1])
|
|
135
140
|
|
|
136
|
-
|
|
137
|
-
|
|
141
|
+
self._create_slider_color_segments()
|
|
142
|
+
return
|
|
138
143
|
|
|
144
|
+
def _create_slider_color_segments(self):
|
|
139
145
|
self.collection_slider.set_edgecolor(self.edgecolor_ma + [self.color_priceline])
|
|
140
146
|
return
|
|
141
147
|
|
|
@@ -143,7 +149,7 @@ class CollectionMixin(PlotMixin):
|
|
|
143
149
|
super().change_background_color(color)
|
|
144
150
|
|
|
145
151
|
self.ax_slider.set_facecolor(color)
|
|
146
|
-
self.
|
|
152
|
+
self.artist_text_slider.set_backgroundcolor(color)
|
|
147
153
|
return
|
|
148
154
|
|
|
149
155
|
def change_tick_color(self, color):
|
|
@@ -156,14 +162,14 @@ class CollectionMixin(PlotMixin):
|
|
|
156
162
|
def change_text_color(self, color):
|
|
157
163
|
super().change_text_color(color)
|
|
158
164
|
|
|
159
|
-
self.
|
|
165
|
+
self.artist_text_slider.set_color(color)
|
|
160
166
|
return
|
|
161
167
|
|
|
162
168
|
def change_line_color(self, color):
|
|
163
169
|
super().change_line_color(color)
|
|
164
170
|
|
|
165
|
-
self.
|
|
166
|
-
self.
|
|
171
|
+
self.artist_text_slider.get_bbox_patch().set_edgecolor(color)
|
|
172
|
+
self.collection_slider_vline.set_edgecolor(color)
|
|
167
173
|
return
|
|
168
174
|
|
|
169
175
|
|
|
@@ -172,7 +178,7 @@ class NavigatorMixin(CollectionMixin):
|
|
|
172
178
|
xmax = self.list_index[-1]
|
|
173
179
|
# 슬라이더 xlim
|
|
174
180
|
xdistance = xmax / 30
|
|
175
|
-
self.slider_xmin, self.slider_xmax = (-xdistance, xmax
|
|
181
|
+
self.slider_xmin, self.slider_xmax = (-xdistance, xmax+xdistance)
|
|
176
182
|
self.ax_slider.set_xlim(self.slider_xmin, self.slider_xmax)
|
|
177
183
|
|
|
178
184
|
# 슬라이더 ylim
|
|
@@ -184,9 +190,9 @@ class NavigatorMixin(CollectionMixin):
|
|
|
184
190
|
self.ax_slider.set_ylim(self.slider_ymin, self.slider_ymax)
|
|
185
191
|
|
|
186
192
|
# 슬라이더 텍스트 y
|
|
187
|
-
self.
|
|
193
|
+
self.artist_text_slider.set_y(ymax)
|
|
188
194
|
|
|
189
|
-
self.
|
|
195
|
+
self.collection_navigator.set_linewidth([ysub+ysub, 5])
|
|
190
196
|
|
|
191
197
|
# 네비게이터 라인 선택 범위
|
|
192
198
|
xsub = self.slider_xmax - self.slider_xmin
|
|
@@ -196,50 +202,51 @@ class NavigatorMixin(CollectionMixin):
|
|
|
196
202
|
return
|
|
197
203
|
|
|
198
204
|
def _set_navigator(self, navmin, navmax):
|
|
199
|
-
|
|
205
|
+
seg = [
|
|
200
206
|
(
|
|
201
207
|
(self.slider_xmin, self.sldier_ymiddle),
|
|
202
|
-
(navmin, self.sldier_ymiddle)
|
|
208
|
+
(navmin, self.sldier_ymiddle),
|
|
203
209
|
),
|
|
204
210
|
(
|
|
205
211
|
(navmin, self.slider_ymin),
|
|
206
|
-
(navmin, self.slider_ymax)
|
|
212
|
+
(navmin, self.slider_ymax),
|
|
207
213
|
),
|
|
208
214
|
(
|
|
209
215
|
(navmax, self.sldier_ymiddle),
|
|
210
|
-
(self.slider_xmax, self.sldier_ymiddle)
|
|
216
|
+
(self.slider_xmax, self.sldier_ymiddle),
|
|
211
217
|
),
|
|
212
218
|
(
|
|
213
219
|
(navmax, self.slider_ymin),
|
|
214
|
-
(navmax, self.slider_ymax)
|
|
220
|
+
(navmax, self.slider_ymax),
|
|
215
221
|
),
|
|
216
222
|
]
|
|
217
223
|
|
|
218
|
-
self.
|
|
224
|
+
self.collection_navigator.set_segments(seg)
|
|
219
225
|
return
|
|
220
226
|
|
|
221
227
|
|
|
222
228
|
class DataMixin(NavigatorMixin):
|
|
223
|
-
navcoordinate = (0, 0)
|
|
229
|
+
navcoordinate: tuple[int, int] = (0, 0)
|
|
224
230
|
|
|
225
231
|
def set_data(self, df, sort_df=True, calc_ma=True, set_candlecolor=True, set_volumecolor=True, calc_info=True, change_lim=True, *args, **kwargs):
|
|
226
232
|
self._generate_data(df, sort_df, calc_ma, set_candlecolor, set_volumecolor, calc_info, *args, **kwargs)
|
|
227
|
-
self.
|
|
228
|
-
|
|
233
|
+
self._create_segments()
|
|
234
|
+
|
|
229
235
|
vmin, vmax = self.navcoordinate
|
|
230
236
|
if change_lim or (vmax-vmin) < self.min_distance:
|
|
231
237
|
vmin, vmax = self.get_default_lim()
|
|
232
|
-
self.navcoordinate = (vmin, vmax)
|
|
238
|
+
self.navcoordinate = (vmin, vmax-1)
|
|
239
|
+
else: vmax += 1
|
|
233
240
|
|
|
234
241
|
self._set_lim(vmin, vmax)
|
|
235
242
|
self._set_slider_lim()
|
|
236
|
-
self._set_navigator(
|
|
243
|
+
self._set_navigator(*self.navcoordinate)
|
|
237
244
|
|
|
238
|
-
self._length_text = self.df[(self.volume if self.volume else self.high)].apply(lambda x: len(
|
|
245
|
+
self._length_text = self.df[(self.volume if self.volume else self.high)].apply(lambda x: len(f'{x:,}')).max()
|
|
239
246
|
return
|
|
240
247
|
|
|
241
248
|
def get_default_lim(self):
|
|
242
|
-
xmax = self.list_index[-1]
|
|
249
|
+
xmax = self.list_index[-1] + 1
|
|
243
250
|
xmin = xmax - 120
|
|
244
251
|
if xmin < 0: xmin = 0
|
|
245
252
|
return (xmin, xmax)
|
|
@@ -257,16 +264,17 @@ class BackgroundMixin(DataMixin):
|
|
|
257
264
|
self._draw_artist()
|
|
258
265
|
self.background = renderer.copy_from_bbox(self.figure.bbox)
|
|
259
266
|
|
|
260
|
-
self.
|
|
267
|
+
self.collection_navigator.draw(self.figure.canvas.renderer)
|
|
261
268
|
self.background_with_nav = renderer.copy_from_bbox(self.figure.bbox)
|
|
262
269
|
return
|
|
263
270
|
|
|
264
271
|
def _restore_region(self, is_empty=False, with_nav=True):
|
|
265
272
|
if not self.background: self._create_background()
|
|
266
273
|
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
274
|
+
restore_region = self.figure.canvas.renderer.restore_region
|
|
275
|
+
if is_empty: restore_region(self.background_emtpy)
|
|
276
|
+
elif with_nav: restore_region(self.background_with_nav)
|
|
277
|
+
else: restore_region(self.background)
|
|
270
278
|
return
|
|
271
279
|
|
|
272
280
|
|
|
@@ -277,16 +285,18 @@ class MouseMoveMixin(BackgroundMixin):
|
|
|
277
285
|
def _on_move(self, e):
|
|
278
286
|
self._on_move_action(e)
|
|
279
287
|
|
|
280
|
-
self._restore_region((self.is_click_slider and self.in_slider))
|
|
281
|
-
|
|
282
288
|
if self.in_slider:
|
|
289
|
+
self._restore_region(self.is_click_slider)
|
|
283
290
|
self._on_move_slider(e)
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
self.
|
|
288
|
-
|
|
289
|
-
|
|
291
|
+
self.figure.canvas.blit()
|
|
292
|
+
elif self.in_price_chart or self.in_volume_chart:
|
|
293
|
+
self._restore_region()
|
|
294
|
+
self._draw_crossline(e, self.in_price_chart)
|
|
295
|
+
self.figure.canvas.blit()
|
|
296
|
+
else:
|
|
297
|
+
if self._erase_crossline():
|
|
298
|
+
self._restore_region()
|
|
299
|
+
self.figure.canvas.blit()
|
|
290
300
|
return
|
|
291
301
|
|
|
292
302
|
def _on_move_action(self, e: MouseEvent):
|
|
@@ -323,34 +333,41 @@ class MouseMoveMixin(BackgroundMixin):
|
|
|
323
333
|
if not ax or e.xdata is None or e.ydata is None:
|
|
324
334
|
self.in_slider, self.in_price_chart, self.in_volume_chart = (False, False, False)
|
|
325
335
|
else:
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
336
|
+
if ax is self.ax_slider:
|
|
337
|
+
self.in_slider = True
|
|
338
|
+
self.in_price_chart = False
|
|
339
|
+
self.in_volume_chart = False
|
|
340
|
+
elif ax is self.ax_price:
|
|
341
|
+
self.in_slider = False
|
|
342
|
+
self.in_price_chart = True
|
|
343
|
+
self.in_volume_chart = False
|
|
344
|
+
elif ax is self.ax_volume:
|
|
345
|
+
self.in_slider = False
|
|
346
|
+
self.in_price_chart = False
|
|
347
|
+
self.in_volume_chart = True
|
|
348
|
+
else:
|
|
349
|
+
self.in_slider = False
|
|
350
|
+
self.in_price_chart = False
|
|
351
|
+
self.in_volume_chart = False
|
|
329
352
|
return
|
|
330
353
|
|
|
331
354
|
def _on_move_slider(self, e: MouseEvent):
|
|
332
355
|
x = e.xdata
|
|
333
|
-
|
|
334
356
|
if self.intx is not None:
|
|
335
357
|
renderer = self.figure.canvas.renderer
|
|
336
|
-
self.
|
|
337
|
-
self.
|
|
358
|
+
self.collection_slider_vline.set_segments([((x, self.slider_ymin), (x, self.slider_ymax))])
|
|
359
|
+
self.collection_slider_vline.draw(renderer)
|
|
338
360
|
|
|
339
361
|
if self.in_slider:
|
|
340
|
-
self.
|
|
341
|
-
self.
|
|
342
|
-
self.
|
|
362
|
+
self.artist_text_slider.set_text(f'{self.df[self.date][self.intx]}')
|
|
363
|
+
self.artist_text_slider.set_x(x)
|
|
364
|
+
self.artist_text_slider.draw(renderer)
|
|
343
365
|
return
|
|
344
366
|
|
|
345
|
-
def
|
|
346
|
-
self.
|
|
347
|
-
self.
|
|
348
|
-
return super().
|
|
349
|
-
|
|
350
|
-
def _on_move_volume_chart(self, e: MouseEvent):
|
|
351
|
-
self.slider_vline.set_segments([((e.xdata, self.slider_ymin), (e.xdata, self.slider_ymax))])
|
|
352
|
-
self.slider_vline.draw(self.figure.canvas.renderer)
|
|
353
|
-
return super()._on_move_volume_chart(e)
|
|
367
|
+
def _draw_crossline(self, e: MouseEvent, in_price_chart):
|
|
368
|
+
self.collection_slider_vline.set_segments([((e.xdata, self.slider_ymin), (e.xdata, self.slider_ymax))])
|
|
369
|
+
self.collection_slider_vline.draw(self.figure.canvas.renderer)
|
|
370
|
+
return super()._draw_crossline(e, in_price_chart)
|
|
354
371
|
|
|
355
372
|
|
|
356
373
|
class ClickMixin(MouseMoveMixin):
|
|
@@ -377,14 +394,16 @@ class ClickMixin(MouseMoveMixin):
|
|
|
377
394
|
x = e.xdata.__int__()
|
|
378
395
|
navmin, navmax = self.navcoordinate
|
|
379
396
|
|
|
380
|
-
|
|
381
|
-
rightmin
|
|
397
|
+
leftmax = navmin+self._navLineWidth_half
|
|
398
|
+
rightmin = navmax-self._navLineWidth_half
|
|
382
399
|
|
|
383
400
|
grater_than_left, less_then_right = (leftmax < x, x < rightmin)
|
|
384
401
|
if grater_than_left and less_then_right:
|
|
385
402
|
self.is_move = True
|
|
386
403
|
self.x_click = x
|
|
387
404
|
else:
|
|
405
|
+
leftmin = navmin - self._navLineWidth
|
|
406
|
+
rightmax = navmax+self._navLineWidth
|
|
388
407
|
if not grater_than_left and leftmin <= x:
|
|
389
408
|
self.click_navleft = True
|
|
390
409
|
self.x_click = navmax
|
|
@@ -404,9 +423,9 @@ class SliderSelectMixin(ClickMixin):
|
|
|
404
423
|
return super()._on_move_slider(e)
|
|
405
424
|
|
|
406
425
|
def _set_navcoordinate(self, e: MouseEvent):
|
|
407
|
-
x = e.xdata.__int__()
|
|
408
426
|
navmin, navmax = self.navcoordinate
|
|
409
427
|
|
|
428
|
+
x = e.xdata.__int__()
|
|
410
429
|
if self.is_move:
|
|
411
430
|
xsub = self.x_click - x
|
|
412
431
|
navmin, navmax = (navmin-xsub, navmax-xsub)
|
|
@@ -418,32 +437,32 @@ class SliderSelectMixin(ClickMixin):
|
|
|
418
437
|
self.navcoordinate = (navmin, navmax)
|
|
419
438
|
self.x_click = x
|
|
420
439
|
|
|
421
|
-
self._set_lim(navmin, navmax, simpler=True, set_ma=(navmax-navmin < self.limit_ma))
|
|
440
|
+
self._set_lim(navmin, navmax+1, simpler=True, set_ma=(navmax-navmin < self.limit_ma))
|
|
422
441
|
|
|
423
442
|
self._set_navigator(navmin, navmax)
|
|
424
|
-
self.
|
|
443
|
+
self.collection_navigator.draw(self.figure.canvas.renderer)
|
|
425
444
|
|
|
426
445
|
self._draw_artist()
|
|
427
446
|
self.background_with_nav = self.figure.canvas.renderer.copy_from_bbox(self.figure.bbox)
|
|
428
|
-
self._restore_region(
|
|
447
|
+
self._restore_region()
|
|
429
448
|
else:
|
|
430
449
|
navmin, navmax = (x, self.x_click) if x < self.x_click else (self.x_click, x)
|
|
431
450
|
|
|
432
451
|
# 슬라이더가 차트를 벗어나지 않도록 선택 영역 제한
|
|
433
452
|
if navmax < 0 or self.list_index[-1] < navmin:
|
|
434
|
-
seg = self.
|
|
453
|
+
seg = self.collection_navigator.get_segments()
|
|
435
454
|
navmin, navmax = (int(seg[1][0][0]), int(seg[3][0][0]))
|
|
436
455
|
|
|
437
456
|
nsub = navmax - navmin
|
|
438
457
|
if nsub < self.min_distance:
|
|
439
458
|
self._restore_region(False, False)
|
|
440
459
|
self._set_navigator(navmin, navmax)
|
|
441
|
-
self.
|
|
460
|
+
self.collection_navigator.draw(self.figure.canvas.renderer)
|
|
442
461
|
else:
|
|
443
|
-
self._set_lim(navmin, navmax, simpler=True, set_ma=(nsub < self.limit_ma))
|
|
462
|
+
self._set_lim(navmin, navmax+1, simpler=True, set_ma=(nsub < self.limit_ma))
|
|
444
463
|
self._set_navigator(navmin, navmax)
|
|
445
464
|
|
|
446
|
-
self.
|
|
465
|
+
self.collection_navigator.draw(self.figure.canvas.renderer)
|
|
447
466
|
|
|
448
467
|
self._draw_artist()
|
|
449
468
|
self.background_with_nav = self.figure.canvas.renderer.copy_from_bbox(self.figure.bbox)
|
|
@@ -464,23 +483,23 @@ class ReleaseMixin(SliderSelectMixin):
|
|
|
464
483
|
|
|
465
484
|
def _on_release_slider(self, e: MouseEvent):
|
|
466
485
|
if not self.is_move:
|
|
467
|
-
seg = self.
|
|
486
|
+
seg = self.collection_navigator.get_segments()
|
|
468
487
|
navmin, navmax = (int(seg[1][0][0]), int(seg[3][0][0]))
|
|
469
488
|
nsub = navmax - navmin
|
|
470
489
|
if self.min_distance <= nsub: self.navcoordinate = (navmin, navmax)
|
|
471
490
|
else:
|
|
472
491
|
self.background_with_nav = self.background_with_nav_pre
|
|
473
492
|
navmin, navmax = self.navcoordinate
|
|
474
|
-
self._set_lim(navmin, navmax, simpler=True, set_ma=(nsub < self.limit_ma))
|
|
493
|
+
self._set_lim(navmin, navmax+1, simpler=True, set_ma=(nsub < self.limit_ma))
|
|
475
494
|
self._restore_region(False, True)
|
|
476
|
-
self.
|
|
495
|
+
self.figure.canvas.blit()
|
|
477
496
|
self._set_navigator(*self.navcoordinate)
|
|
478
497
|
|
|
479
498
|
self.is_click_slider = False
|
|
480
499
|
self.is_move = False
|
|
481
500
|
self.click_navleft, self.click_navright = (False, False)
|
|
482
501
|
|
|
483
|
-
self.
|
|
502
|
+
self.figure.canvas.draw()
|
|
484
503
|
return
|
|
485
504
|
|
|
486
505
|
|
|
@@ -488,23 +507,30 @@ class ChartClickMixin(ReleaseMixin):
|
|
|
488
507
|
is_click_chart = False
|
|
489
508
|
|
|
490
509
|
def _on_click(self, e: MouseEvent):
|
|
491
|
-
if
|
|
492
|
-
(
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
510
|
+
if e.button == MouseButton.LEFT:
|
|
511
|
+
if (
|
|
512
|
+
not self.is_click_chart
|
|
513
|
+
and (self.in_price_chart or self.in_volume_chart)
|
|
514
|
+
): self._on_click_chart(e)
|
|
515
|
+
elif not self.is_click_slider and self.in_slider:
|
|
516
|
+
self._on_click_slider(e)
|
|
497
517
|
return
|
|
498
518
|
|
|
499
519
|
def _on_click_chart(self, e: MouseEvent):
|
|
500
520
|
self.is_click_chart = True
|
|
501
|
-
|
|
521
|
+
x = e.xdata.__int__()
|
|
522
|
+
self.x_click = x - self.navcoordinate[0]
|
|
502
523
|
self.figure.canvas.set_cursor(cursors.RESIZE_HORIZONTAL)
|
|
503
524
|
return
|
|
504
525
|
|
|
505
526
|
def _on_release(self, e):
|
|
506
|
-
if
|
|
507
|
-
|
|
527
|
+
if e.button == MouseButton.LEFT:
|
|
528
|
+
if (
|
|
529
|
+
self.is_click_chart
|
|
530
|
+
and (self.in_price_chart or self.in_volume_chart)
|
|
531
|
+
): self._on_release_chart(e)
|
|
532
|
+
elif self.is_click_slider and self.in_slider:
|
|
533
|
+
self._on_release_slider(e)
|
|
508
534
|
return
|
|
509
535
|
|
|
510
536
|
def _on_release_chart(self, e):
|
|
@@ -519,50 +545,42 @@ class ChartClickMixin(ReleaseMixin):
|
|
|
519
545
|
def _on_move(self, e):
|
|
520
546
|
self._on_move_action(e)
|
|
521
547
|
|
|
522
|
-
need_slider_action = self.is_click_slider and self.in_slider
|
|
523
|
-
need_chart_action = False if need_slider_action else self.is_click_chart and (self.in_price_chart or self.in_volume_chart)
|
|
524
|
-
self._restore_region((need_slider_action or need_chart_action))
|
|
525
|
-
|
|
526
548
|
if self.in_slider:
|
|
549
|
+
self._restore_region(self.is_click_slider)
|
|
527
550
|
self._on_move_slider(e)
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
self.
|
|
532
|
-
|
|
533
|
-
|
|
551
|
+
self.figure.canvas.blit()
|
|
552
|
+
elif self.in_price_chart or self.in_volume_chart:
|
|
553
|
+
self._restore_region(self.is_click_chart)
|
|
554
|
+
if not self.is_click_chart:
|
|
555
|
+
self._draw_crossline(e, self.in_price_chart)
|
|
556
|
+
else: self._move_chart(e)
|
|
557
|
+
self.figure.canvas.blit()
|
|
558
|
+
else:
|
|
559
|
+
if self._erase_crossline():
|
|
560
|
+
self._restore_region()
|
|
561
|
+
self.figure.canvas.blit()
|
|
534
562
|
return
|
|
535
563
|
|
|
536
|
-
def _on_move_price_chart(self, e):
|
|
537
|
-
if self.is_click_chart: self._move_chart(e)
|
|
538
|
-
return super()._on_move_price_chart(e)
|
|
539
|
-
|
|
540
|
-
def _on_move_volume_chart(self, e):
|
|
541
|
-
if self.is_click_chart: self._move_chart(e)
|
|
542
|
-
return super()._on_move_volume_chart(e)
|
|
543
|
-
|
|
544
564
|
def _move_chart(self, e: MouseEvent):
|
|
545
|
-
x = e.x
|
|
546
565
|
left, right = self.navcoordinate
|
|
547
|
-
|
|
548
|
-
xsub = x - self.
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
self.navigator.draw(self.figure.canvas.renderer)
|
|
566
|
+
x = e.xdata.__int__() - left
|
|
567
|
+
xsub = x - self.x_click
|
|
568
|
+
if not xsub:
|
|
569
|
+
self.collection_navigator.draw(self.figure.canvas.renderer)
|
|
552
570
|
self._draw_artist()
|
|
553
571
|
else:
|
|
554
|
-
left, right = (left-
|
|
555
|
-
if right < 0 or self.df.index[-1] < left: self._restore_region(
|
|
572
|
+
left, right = (left-xsub, right-xsub)
|
|
573
|
+
if right < 0 or self.df.index[-1] < left: self._restore_region()
|
|
556
574
|
else:
|
|
575
|
+
self.x_click = x
|
|
557
576
|
self.navcoordinate = (left, right)
|
|
558
|
-
self._set_lim(left, right, simpler=True, set_ma=((right-left) < self.limit_ma))
|
|
577
|
+
self._set_lim(left, right+1, simpler=True, set_ma=((right-left) < self.limit_ma))
|
|
559
578
|
self._set_navigator(left, right)
|
|
560
|
-
self.
|
|
579
|
+
self.collection_navigator.draw(self.figure.canvas.renderer)
|
|
561
580
|
|
|
562
581
|
self._draw_artist()
|
|
563
582
|
self.background_with_nav = self.figure.canvas.renderer.copy_from_bbox(self.figure.bbox)
|
|
564
|
-
self._restore_region(
|
|
565
|
-
self._x_click = x
|
|
583
|
+
self._restore_region()
|
|
566
584
|
return
|
|
567
585
|
|
|
568
586
|
|
|
@@ -571,17 +589,13 @@ class BaseMixin(ChartClickMixin):
|
|
|
571
589
|
|
|
572
590
|
|
|
573
591
|
class Chart(BaseMixin, Mixin):
|
|
574
|
-
def _add_collection(self):
|
|
575
|
-
super()._add_collection()
|
|
576
|
-
return self.add_artist()
|
|
577
|
-
|
|
578
592
|
def _draw_artist(self):
|
|
579
593
|
super()._draw_artist()
|
|
580
594
|
return self.draw_artist()
|
|
581
595
|
|
|
582
|
-
def
|
|
583
|
-
|
|
584
|
-
return
|
|
596
|
+
def _set_lim(self, xmin, xmax, simpler=False, set_ma=True):
|
|
597
|
+
super()._set_lim(xmin, xmax, simpler, set_ma)
|
|
598
|
+
return self.on_change_xlim(xmin, xmax, simpler, set_ma)
|
|
585
599
|
|
|
586
600
|
def _on_draw(self, e):
|
|
587
601
|
super()._on_draw(e)
|
|
@@ -591,21 +605,6 @@ class Chart(BaseMixin, Mixin):
|
|
|
591
605
|
self.on_pick(e)
|
|
592
606
|
return super()._on_pick(e)
|
|
593
607
|
|
|
594
|
-
def _set_candle_segments(self, index_start, index_end):
|
|
595
|
-
super()._set_candle_segments(index_start, index_end)
|
|
596
|
-
self.set_segment(index_start, index_end)
|
|
597
|
-
return
|
|
598
|
-
|
|
599
|
-
def _set_wick_segments(self, index_start, index_end, simpler=False):
|
|
600
|
-
super()._set_wick_segments(index_start, index_end, simpler)
|
|
601
|
-
self.set_segment(index_start, index_end, simpler)
|
|
602
|
-
return
|
|
603
|
-
|
|
604
|
-
def _set_line_segments(self, index_start, index_end, simpler=False, set_ma=True):
|
|
605
|
-
super()._set_line_segments(index_start, index_end, simpler, set_ma)
|
|
606
|
-
self.set_segment(index_start, index_end, simpler, set_ma)
|
|
607
|
-
return
|
|
608
|
-
|
|
609
608
|
def _on_move(self, e):
|
|
610
609
|
super()._on_move(e)
|
|
611
610
|
return self.on_move(e)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.2
|
|
2
2
|
Name: seolpyo-mplchart
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.0
|
|
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
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
seolpyo_mplchart/__init__.py,sha256=
|
|
1
|
+
seolpyo_mplchart/__init__.py,sha256=1rY6PP1OMMr1d_5x7dlAD2ImQAXChT5spvB45j6yDp8,18255
|
|
2
2
|
seolpyo_mplchart/_base.py,sha256=3iG4AVwHR_h3rh6c1oJahWt7NvBpBFrS0bUZd4PaHfY,3921
|
|
3
|
-
seolpyo_mplchart/_cursor.py,sha256=
|
|
4
|
-
seolpyo_mplchart/_draw.py,sha256=
|
|
5
|
-
seolpyo_mplchart/_slider.py,sha256=
|
|
3
|
+
seolpyo_mplchart/_cursor.py,sha256=tWna4dRlHImM9XzwDHvcFn8vdR1P97JWSYYTmGpb02E,22473
|
|
4
|
+
seolpyo_mplchart/_draw.py,sha256=TGPo80yJocmXbWoCfzYKlWK6ntBElvb9IR8O54A2X5w,21174
|
|
5
|
+
seolpyo_mplchart/_slider.py,sha256=9h_4svjmCtGHUf2LwEJUYtsiR3UBE8JrwWv7EhsVCLQ,23118
|
|
6
6
|
seolpyo_mplchart/base.py,sha256=0qdImsIMPzTTkkHzPv479BVe_ojrn45FidGE46eT5x4,3797
|
|
7
7
|
seolpyo_mplchart/cursor.py,sha256=qq1WJJa7vCE5C2XeGBECt2XqxR_WxfybZZ5u6zVx5Ps,20415
|
|
8
8
|
seolpyo_mplchart/draw.py,sha256=MiqDhbMJOSlWD6qdAghsyrZwCixcwm4nfmiinvwtt-o,21520
|
|
@@ -11,7 +11,7 @@ seolpyo_mplchart/test.py,sha256=TFnIXphJsl-B7iIhBh7-PZKUz2Gjh7mwNwrk8aUS4SA,180
|
|
|
11
11
|
seolpyo_mplchart/utils.py,sha256=a3XycRBTndrsjBw_1VKTxbSvOGpVYXHRK87v7azgRe8,1433
|
|
12
12
|
seolpyo_mplchart/data/apple.txt,sha256=0izAfweu1lLsC0IwVthdVlo9reG8KGbKGTSX5knI5Zc,1380864
|
|
13
13
|
seolpyo_mplchart/data/samsung.txt,sha256=UejaSkbzr4E5K3lkelCT0yJiWUPfmViBEaTyoXyphIs,2476424
|
|
14
|
-
seolpyo_mplchart-1.
|
|
15
|
-
seolpyo_mplchart-1.
|
|
16
|
-
seolpyo_mplchart-1.
|
|
17
|
-
seolpyo_mplchart-1.
|
|
14
|
+
seolpyo_mplchart-1.4.0.dist-info/METADATA,sha256=4iLKujOaFP2BLDopSwsvsKYPEoD81CMUFWZjf6t80Fc,2482
|
|
15
|
+
seolpyo_mplchart-1.4.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
|
16
|
+
seolpyo_mplchart-1.4.0.dist-info/top_level.txt,sha256=KgqFn7rKWize7OjMaTCHxKm9ie6vqnyb5c8fN7y_tSo,17
|
|
17
|
+
seolpyo_mplchart-1.4.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|