seolpyo-mplchart 1.0.0__py3-none-any.whl → 1.1.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.

@@ -15,7 +15,8 @@ __all__ = [
15
15
  'format_candleinfo_ko', 'format_volumeinfo_ko',
16
16
  'format_candleinfo_en', 'format_volumeinfo_en',
17
17
  'sample', 'switch_backend', 'show', 'close',
18
- 'Chart', 'CursorChart', 'SliderChart',
18
+ 'OnlyChart', 'CursorChart', 'SliderChart',
19
+ 'set_theme',
19
20
  ]
20
21
 
21
22
 
@@ -67,7 +68,7 @@ def close(fig='all'):
67
68
  return plt.close(fig)
68
69
 
69
70
 
70
- class Chart(BaseChart):
71
+ class OnlyChart(BaseChart):
71
72
  r"""
72
73
  You can see the guidance document:
73
74
  Korean: https://white.seolpyo.com/entry/147/
@@ -102,17 +103,21 @@ class Chart(BaseChart):
102
103
  list_macolor: Color the moving average line. If the number of colors is greater than the moving average line, black is applied
103
104
 
104
105
  candle_on_ma: Decide whether to draw candles on the moving average line. default ```True```
106
+ color_navigator_line: Color of left and right dividing lines in selected area
107
+ color_navigator_cover: Color of unselected area.
105
108
 
106
- color_up: The color of the candle. When the closing price is greater than the opening price. default '#fe3032'
107
- color_down: The color of the candle. When the opening price is greater than the opening price. default '#0095ff'
108
- color_flat: The color of the candle. WWhen the closing price is the same as the opening price. default 'k'
109
- color_up_down: The color of the candle. If the closing price is greater than the opening price, but is lower than the previous day's closing price. default 'w'
110
- color_down_up: The color of the candle. If the opening price is greater than the closing price, but is higher than the closing price of the previous day. default 'w'
111
- colors_volume: The color of the volume bar. default '#1f77b4'
109
+ color_priceline: The color of the price line
112
110
 
113
- color_priceline: The color of the price line. default 'k'
111
+ color_up: The color of the candle. When the closing price is greater than the opening price
112
+ color_down: The color of the candle. When the opening price is greater than the opening price
113
+ color_flat: The color of the candle. When the closing price is the same as the opening price
114
+ color_up_down: The color of the candle. If the closing price is greater than the opening price, but is lower than the previous day's closing price
115
+ color_down_up: The color of the candle. If the opening price is greater than the closing price, but is higher than the closing price of the previous day
116
+ colors_volume: The color of the volume bar. default '#1f77b4'
114
117
 
115
- facecolor_volume, edgecolor_volume = The color of the volume. default ('#1f77b4', 'k')
118
+ color_volume_up: The color of the volume. When the closing price is greater than the opening price
119
+ color_volume_down: The color of the volume. When the opening price is greater than the opening price
120
+ color_volume_flatt: The color of the volume. When the closing price is the same as the opening price
116
121
 
117
122
  candle_width_half, volume_width_half: half of the thickness of the candle and volume
118
123
 
@@ -162,17 +167,21 @@ class CursorChart(BaseCursorChart):
162
167
  list_macolor: Color the moving average line. If the number of colors is greater than the moving average line, black is applied
163
168
 
164
169
  candle_on_ma: Decide whether to draw candles on the moving average line. default ```True```
170
+ color_navigator_line: Color of left and right dividing lines in selected area
171
+ color_navigator_cover: Color of unselected area.
165
172
 
166
- color_up: The color of the candle. When the closing price is greater than the opening price. default '#fe3032'
167
- color_down: The color of the candle. When the opening price is greater than the opening price. default '#0095ff'
168
- color_flat: The color of the candle. WWhen the closing price is the same as the opening price. default 'k'
169
- color_up_down: The color of the candle. If the closing price is greater than the opening price, but is lower than the previous day's closing price. default 'w'
170
- color_down_up: The color of the candle. If the opening price is greater than the closing price, but is higher than the closing price of the previous day. default 'w'
171
- colors_volume: The color of the volume bar. default '#1f77b4'
173
+ color_priceline: The color of the price line
172
174
 
173
- color_priceline: The color of the price line. default 'k'
175
+ color_up: The color of the candle. When the closing price is greater than the opening price
176
+ color_down: The color of the candle. When the opening price is greater than the opening price
177
+ color_flat: The color of the candle. When the closing price is the same as the opening price
178
+ color_up_down: The color of the candle. If the closing price is greater than the opening price, but is lower than the previous day's closing price
179
+ color_down_up: The color of the candle. If the opening price is greater than the closing price, but is higher than the closing price of the previous day
180
+ colors_volume: The color of the volume bar. default '#1f77b4'
174
181
 
175
- facecolor_volume, edgecolor_volume = The color of the volume. default ('#1f77b4', 'k')
182
+ color_volume_up: The color of the volume. When the closing price is greater than the opening price
183
+ color_volume_down: The color of the volume. When the opening price is greater than the opening price
184
+ color_volume_flatt: The color of the volume. When the closing price is the same as the opening price
176
185
 
177
186
  candle_width_half, volume_width_half: half of the thickness of the candle and volume
178
187
 
@@ -216,7 +225,7 @@ class SliderChart(BaseSliderChart):
216
225
  figsize: Default size when creating a matplotlib window
217
226
  slider_top: ax_slider is located at the top or bottom. default ```True```.
218
227
  ratio_ax_slider, ratio_ax_legend, ratio_ax_price, ratio_ax_volume: Axes ratio
219
- ratio_ax_none: Ratio between volume chart and slider. Used only when slider_top is ```False```
228
+ ratio_ax_none: Ratio between volume chart and slider. Used only when ```self.slider_top``` is ```False```
220
229
  adjust: figure adjust. default ```dict(top=0.95, bottom=0.05, left=0.01, right=0.93, wspace=0, hspace=0)```.
221
230
  color_background: color of background. default '#fafafa'.
222
231
  gridKwargs: kwargs applied to the grid
@@ -232,20 +241,21 @@ class SliderChart(BaseSliderChart):
232
241
  list_macolor: Color the moving average line. If the number of colors is greater than the moving average line, black is applied
233
242
 
234
243
  candle_on_ma: Decide whether to draw candles on the moving average line. default ```True```
235
- color_sliderline: Color of closing price line in ax_slider. default 'k'
236
- color_navigatorline: Color of left and right dividing lines in selected area. default '#1e78ff'
237
- color_navigator: Color of unselected area. default 'k'
238
-
239
- color_up: The color of the candle. When the closing price is greater than the opening price. default '#fe3032'
240
- color_down: The color of the candle. When the opening price is greater than the opening price. default '#0095ff'
241
- color_flat: The color of the candle. WWhen the closing price is the same as the opening price. default 'k'
242
- color_up_down: The color of the candle. If the closing price is greater than the opening price, but is lower than the previous day's closing price. default 'w'
243
- color_down_up: The color of the candle. If the opening price is greater than the closing price, but is higher than the closing price of the previous day. default 'w'
244
- colors_volume: The color of the volume bar. default '#1f77b4'
244
+ color_navigator_line: Color of left and right dividing lines in selected area
245
+ color_navigator_cover: Color of unselected area.
246
+
247
+ color_priceline: The color of the price line
245
248
 
246
- color_priceline: The color of the price line. default 'k'
249
+ color_up: The color of the candle. When the closing price is greater than the opening price
250
+ color_down: The color of the candle. When the opening price is greater than the opening price
251
+ color_flat: The color of the candle. When the closing price is the same as the opening price
252
+ color_up_down: The color of the candle. If the closing price is greater than the opening price, but is lower than the previous day's closing price
253
+ color_down_up: The color of the candle. If the opening price is greater than the closing price, but is higher than the closing price of the previous day
254
+ colors_volume: The color of the volume bar. default '#1f77b4'
247
255
 
248
- facecolor_volume, edgecolor_volume = The color of the volume. default ('#1f77b4', 'k')
256
+ color_volume_up: The color of the volume. When the closing price is greater than the opening price
257
+ color_volume_down: The color of the volume. When the opening price is greater than the opening price
258
+ color_volume_flatt: The color of the volume. When the closing price is the same as the opening price
249
259
 
250
260
  candle_width_half, volume_width_half: half of the thickness of the candle and volume
251
261
 
@@ -268,4 +278,75 @@ class SliderChart(BaseSliderChart):
268
278
  color_navigator_line: Navigator divider color. default '#1e78ff'
269
279
  color_navigator_cover: Unselected slider area color. default = 'k'
270
280
  """
271
- pass
281
+ pass
282
+
283
+
284
+ def set_theme(chart: OnlyChart|CursorChart|SliderChart, theme: Literal['light', 'dark']='dark'):
285
+ initialized = hasattr(chart, 'ax_price')
286
+
287
+ if theme == 'dark':
288
+ chart.color_background = '#000000'
289
+ chart.color_tick, chart.color_tick_label = ('w', 'w')
290
+ chart.gridKwargs = {'color': '#FFFFFF'}
291
+
292
+ chart.color_priceline = 'w'
293
+ chart.color_up, chart.color_down = ('#00FF00', '#FF0000')
294
+ chart.color_flat = 'w'
295
+ chart.color_up_down, chart.color_down_up = ('#000000', '#000000')
296
+
297
+ chart.color_volume_up, chart.color_volume_down = ('#32CD32', '#FF4500')
298
+ chart.color_volume_flat = 'w'
299
+
300
+ chart.list_macolor = ('#FFFF00', '#7FFF00', '#00FFFF', '#FFA07A', '#FF00FF')
301
+
302
+ chart.lineKwargs = {'edgecolor': 'w'}
303
+ chart.color_box = 'w'
304
+ chart.textboxKwargs = {'facecolor': 'k', 'edgecolor': 'w'}
305
+ chart.textKwargs = {'color': 'w'}
306
+ chart.color_navigator_cover, chart.color_navigator_line = ('w', '#00FFFF')
307
+
308
+ if initialized:
309
+ chart.change_background_color('k')
310
+ chart.change_tick_color('w')
311
+ chart.change_line_color('w')
312
+ if hasattr(chart, 'navigator'): chart.navigator.set_edgecolor([chart.color_navigator_cover, chart.color_navigator_line])
313
+
314
+ if hasattr(chart, 'df'):
315
+ chart.set_candlecolor, chart.set_volumecolor = (True, True)
316
+ chart._get_color_segment()
317
+ chart.figure.canvas.draw()
318
+
319
+ elif theme == 'light':
320
+ chart.color_background = '#fafafa'
321
+ chart.color_tick, chart.color_tick_label = ('k', 'k')
322
+ chart.gridKwargs = {'color': '#d0d0d0'}
323
+
324
+ chart.color_priceline = 'k'
325
+ chart.color_up, chart.color_down = ('#FF2400', '#1E90FF')
326
+ chart.color_flat = 'k'
327
+ chart.color_up_down, chart.color_down_up = ('w', 'w')
328
+
329
+ chart.color_volume_up, chart.color_volume_down = ('#FF4D4D', '#5CA8F4')
330
+ chart.color_volume_flat = '#A9A9A9'
331
+
332
+ chart.list_macolor = ('#B22222', '#228B22', '#1E90FF', '#FF8C00', '#4B0082')
333
+
334
+ chart.lineKwargs = {'edgecolor': 'k'}
335
+ chart.color_box = 'k'
336
+ chart.textboxKwargs = {'facecolor': 'w', 'edgecolor': 'k'}
337
+ chart.textKwargs = {'color': 'k'}
338
+ chart.color_navigator_cover, chart.color_navigator_line = ('k', '#1e78ff')
339
+
340
+ if initialized:
341
+ chart.change_background_color('#fafafa')
342
+ chart.change_tick_color('k')
343
+ chart.change_line_color('k')
344
+ if hasattr(chart, 'navigator'): chart.navigator.set_edgecolor([chart.color_navigator_cover, chart.color_navigator_line])
345
+
346
+ if hasattr(chart, 'df'):
347
+ chart.set_candlecolor, chart.set_volumecolor = (True, True)
348
+ chart._get_color_segment()
349
+ chart.figure.canvas.draw()
350
+ else: raise ValueError(f'You send wrong arg.\n{theme=}')
351
+
352
+ return chart
seolpyo_mplchart/base.py CHANGED
@@ -88,7 +88,7 @@ class Base:
88
88
  self.ax_price.yaxis.set_major_formatter(lambda x, _: convert_unit(x, word=self.unit_price, digit=2))
89
89
  self.ax_volume.yaxis.set_major_formatter(lambda x, _: convert_unit(x, word=self.unit_volume, digit=2))
90
90
 
91
- gridKwargs = {'visible': True, 'linewidth': 1, 'color': '#d0d0d0', 'linestyle': '--'}
91
+ gridKwargs = {'visible': True, 'linewidth': 0.7, 'color': '#d0d0d0', 'linestyle': '-', 'dashes': (1, 0)}
92
92
  gridKwargs.update(self.gridKwargs)
93
93
  # 공통 설정
94
94
  for ax in (self.ax_price, self.ax_volume):
@@ -59,6 +59,49 @@ class CollectionMixin(BM):
59
59
  self.ax_volume.add_artist(self.text_volume_info)
60
60
  return
61
61
 
62
+ def change_background_color(self, color):
63
+ super().change_background_color(color)
64
+
65
+ self.text_price.set_backgroundcolor(color)
66
+ self.text_volume.set_backgroundcolor(color)
67
+
68
+ self.text_date_price.set_backgroundcolor(color)
69
+ self.text_date_volume.set_backgroundcolor(color)
70
+
71
+ self.text_price_info.set_backgroundcolor(color)
72
+ self.text_volume_info.set_backgroundcolor(color)
73
+ return
74
+
75
+ def change_text_color(self, color):
76
+ super().change_text_color(color)
77
+
78
+ self.text_price.set_color(color)
79
+ self.text_volume.set_color(color)
80
+
81
+ self.text_date_price.set_color(color)
82
+ self.text_date_volume.set_color(color)
83
+
84
+ self.text_price_info.set_color(color)
85
+ self.text_volume_info.set_color(color)
86
+ return
87
+
88
+ def change_line_color(self, color):
89
+ self.price_crossline.set_edgecolor(color)
90
+ self.volume_crossline.set_edgecolor(color)
91
+
92
+ self.price_box.set_edgecolor(color)
93
+ self.volume_box.set_edgecolor(color)
94
+
95
+ self.text_price.get_bbox_patch().set_edgecolor(color)
96
+ self.text_volume.get_bbox_patch().set_edgecolor(color)
97
+
98
+ self.text_date_price.get_bbox_patch().set_edgecolor(color)
99
+ self.text_date_volume.get_bbox_patch().set_edgecolor(color)
100
+
101
+ self.text_price_info.get_bbox_patch().set_edgecolor(color)
102
+ self.text_volume_info.get_bbox_patch().set_edgecolor(color)
103
+ return
104
+
62
105
 
63
106
  _set_key = {'rate', 'compare', 'rate_open', 'rate_high', 'rate_low', 'rate_volume', '_boxheight', '_boxmin', '_boxmax', '_volumeboxmax',}
64
107
 
@@ -416,6 +459,21 @@ class Chart(BaseMixin, Mixin):
416
459
  self.on_pick(e)
417
460
  return super()._on_pick(e)
418
461
 
462
+ def _set_candle_segments(self, index_start, index_end):
463
+ super()._set_candle_segments(index_start, index_end)
464
+ self.set_segment(index_start, index_end)
465
+ return
466
+
467
+ def _set_wick_segments(self, index_start, index_end, simpler=False):
468
+ super()._set_wick_segments(index_start, index_end, simpler)
469
+ self.set_segment(index_start, index_end, simpler)
470
+ return
471
+
472
+ def _set_line_segments(self, index_start, index_end, simpler=False, set_ma=True):
473
+ super()._set_line_segments(index_start, index_end, simpler, set_ma)
474
+ self.set_segment(index_start, index_end, simpler, set_ma)
475
+ return
476
+
419
477
  def _on_move(self, e):
420
478
  super()._on_move(e)
421
479
  return self.on_move(e)
seolpyo_mplchart/draw.py CHANGED
@@ -30,6 +30,10 @@ class Mixin:
30
30
  "If draw pick active, This method work."
31
31
  return
32
32
 
33
+ def set_segment(self, xmin, xmax, simpler=False, set_ma=True):
34
+ "This method work if xlim change."
35
+ return
36
+
33
37
 
34
38
  class CollectionMixin(Base):
35
39
  facecolor_volume, edgecolor_volume = ('#1f77b4', 'k')
@@ -61,6 +65,35 @@ class CollectionMixin(Base):
61
65
  self.figure.add_artist(self.text_watermark)
62
66
  return
63
67
 
68
+ def change_background_color(self, color):
69
+ self.figure.set_facecolor(color)
70
+ self.ax_price.set_facecolor(color)
71
+ self.ax_volume.set_facecolor(color)
72
+ legends = self.ax_legend.get_legend()
73
+ if legends: legends.get_frame().set_facecolor(color)
74
+ return
75
+
76
+ def change_tick_color(self, color):
77
+ for ax in (self.ax_price, self.ax_volume):
78
+ for i in ['top', 'bottom', 'left', 'right']: ax.spines[i].set_color(self.color_tick)
79
+ ax.tick_params(colors=color)
80
+ ax.tick_params(colors=color)
81
+
82
+ legends = self.ax_legend.get_legend()
83
+ if legends: legends.get_frame().set_edgecolor(color)
84
+
85
+ self.change_text_color(color)
86
+ return
87
+
88
+ def change_text_color(self, color):
89
+ self.text_watermark.set_color(color)
90
+ legends = self.ax_legend.get_legend()
91
+ if legends:
92
+ for i in legends.texts: i.set_color(color)
93
+ return
94
+
95
+ def change_line_color(self, color): return
96
+
64
97
 
65
98
  _set_key = {'_x', '_left', '_right', '_volleft', '_volright', '_top', '_bottom', '_pre', '_zero', '_volymax',}
66
99
 
@@ -73,10 +106,15 @@ class DataMixin(CollectionMixin):
73
106
  list_ma = (5, 20, 60, 120, 240)
74
107
 
75
108
  candle_width_half, volume_width_half = (0.24, 0.36)
76
- color_up, color_down = ('#fe3032', '#0095ff')
109
+ color_up, color_down = ('#FF2400', '#1E90FF')
77
110
  color_flat = 'k'
78
111
  color_up_down, color_down_up = ('w', 'w')
79
112
 
113
+ color_volume_up, color_volume_down = ('#FF4D4D', '#5CA8F4')
114
+ color_volume_flat = '#A9A9A9'
115
+
116
+ set_candlecolor, set_volumecolor = (True, True)
117
+
80
118
  def _generate_data(self, df: pd.DataFrame, sort_df, calc_ma, set_candlecolor, set_volumecolor, *_, **__):
81
119
  self._validate_column_key()
82
120
 
@@ -120,30 +158,14 @@ class DataMixin(CollectionMixin):
120
158
  for i in ('facecolor', 'edgecolor', 'volumefacecolor',):
121
159
  if i not in keys:
122
160
  raise Exception(f'"{i}" column not in DataFrame.\nadd column or set set_candlecolor=True.')
123
- else:
124
- # 양봉
125
- df.loc[:, ['facecolor', 'edgecolor']] = (self.color_up, self.color_up)
126
- if self.color_up != self.color_down:
127
- # 음봉
128
- df.loc[df[self.close] < df[self.Open], ['facecolor', 'edgecolor']] = (self.color_down, self.color_down)
129
- if self.color_up != self.color_flat:
130
- # 보합
131
- df.loc[df[self.close] == df[self.Open], ['facecolor', 'edgecolor']] = (self.color_flat, self.color_flat)
132
- if self.color_up != self.color_up_down:
133
- # 양봉(비우기)
134
- df.loc[(df['facecolor'] == self.color_up) & (df[self.close] < df['_pre']), 'facecolor'] = self.color_up_down
135
- if self.color_down != self.color_down_up:
136
- # 음봉(비우기)
137
- df.loc[(df['facecolor'] == self.color_down) & (df['_pre'] < df[self.close]), ['facecolor']] = self.color_down_up
161
+ self.set_candlecolor = set_candlecolor
138
162
 
139
163
  if not set_volumecolor:
140
164
  keys = set(df.keys())
141
165
  for i in ('volumefacecolor', 'volumeedgecolor',):
142
166
  if i not in keys:
143
167
  raise Exception(f'"{i}" column not in DataFrame.\nadd column or set set_volumecolor=True.')
144
- else:
145
- # 거래량
146
- df.loc[:, ['volumefacecolor', 'volumeedgecolor']] = (self.facecolor_volume, self.edgecolor_volume)
168
+ self.set_volumecolor = set_volumecolor
147
169
 
148
170
  self.df = df
149
171
  return
@@ -165,7 +187,7 @@ class SegmentMixin(DataMixin):
165
187
  color_priceline = 'k'
166
188
  format_ma = '{}일선'
167
189
  # https://matplotlib.org/stable/gallery/color/named_colors.html
168
- list_macolor = ('darkred', 'fuchsia', 'olive', 'orange', 'navy', 'darkmagenta', 'limegreen', 'darkcyan',)
190
+ list_macolor = ('#B22222', '#228B22', '#1E90FF', '#FF8C00', '#4B0082')
169
191
 
170
192
  def _get_segments(self):
171
193
  # 캔들 세그먼트
@@ -196,9 +218,6 @@ class SegmentMixin(DataMixin):
196
218
  segment_priceline = segment_wick = self.df[['_x', self.close]].values
197
219
  self.segment_priceline = segment_priceline.reshape(1, *segment_wick.shape)
198
220
 
199
- self.facecolor_candle = self.df['facecolor'].values
200
- self.edgecolor_candle = self.df['edgecolor'].values
201
-
202
221
  if self.volume:
203
222
  # 거래량 바 세그먼트
204
223
  segment_volume = self.df[[
@@ -216,21 +235,49 @@ class SegmentMixin(DataMixin):
216
235
  ]].values
217
236
  self.segment_volume_wick = segment_volume_wick.reshape(segment_volume_wick.shape[0], 2, 2)
218
237
 
219
- self.facecolor_volume = self.df['volumefacecolor'].values
220
- self.edgecolor_volume = self.df['volumeedgecolor'].values
221
-
222
238
  self._get_ma_segment()
239
+ self._get_color_segment()
223
240
  return
224
241
 
225
- def _get_ma_segment(self):
242
+ def _get_color_segment(self):
243
+ if self.set_candlecolor:
244
+ # 양봉
245
+ self.df.loc[:, ['facecolor', 'edgecolor']] = (self.color_up, self.color_up)
246
+ if self.color_up != self.color_down:
247
+ # 음봉
248
+ self.df.loc[self.df[self.close] < self.df[self.Open], ['facecolor', 'edgecolor']] = (self.color_down, self.color_down)
249
+ if self.color_up != self.color_flat and self.color_down != self.color_flat:
250
+ # 보합
251
+ self.df.loc[self.df[self.close] == self.df[self.Open], ['facecolor', 'edgecolor']] = (self.color_flat, self.color_flat)
252
+ if self.color_up != self.color_up_down:
253
+ # 양봉(비우기)
254
+ self.df.loc[(self.df['facecolor'] == self.color_up) & (self.df[self.close] <= self.df['_pre']), 'facecolor'] = self.color_up_down
255
+ if self.color_down != self.color_down_up:
256
+ # 음봉(비우기)
257
+ self.df.loc[(self.df['facecolor'] == self.color_down) & (self.df['_pre'] <= self.df[self.close]), ['facecolor']] = self.color_down_up
258
+
259
+ self.facecolor_candle = self.df['facecolor'].values
260
+ self.edgecolor_candle = self.df['edgecolor'].values
261
+
262
+ if self.set_volumecolor:
263
+ # 거래량
264
+ self.df.loc[:, ['volumefacecolor', 'volumeedgecolor']] = (self.color_volume_up, self.color_volume_up)
265
+ if self.color_up != self.color_down:
266
+ # 전일대비 하락
267
+ self.df.loc[self.df[self.close] < self.df['_pre'], ['volumefacecolor', 'volumeedgecolor']] = (self.color_volume_down, self.color_volume_down)
268
+ if self.color_up != self.color_flat:
269
+ # 전일과 동일
270
+ self.df.loc[self.df[self.close] == self.df['_pre'], ['volumefacecolor', 'volumeedgecolor']] = (self.color_volume_flat, self.color_volume_flat)
271
+
272
+ self.facecolor_volume = self.df['volumefacecolor'].values
273
+ self.edgecolor_volume = self.df['volumeedgecolor'].values
274
+
226
275
  # 기존 legend 제거
227
276
  legends = self.ax_legend.get_legend()
228
277
  if legends: legends.remove()
229
278
 
230
279
  self._visible_ma.clear()
231
280
 
232
- if not self.list_ma: return
233
-
234
281
  list_handle, list_label, list_color = ([], [], [])
235
282
  arr = (0, 1)
236
283
  for n, i in enumerate(self.list_ma):
@@ -242,14 +289,6 @@ class SegmentMixin(DataMixin):
242
289
  list_label.append(self.format_ma.format(i))
243
290
 
244
291
  self._visible_ma.add(i)
245
-
246
- # 주가 차트 가격이동평균선
247
- key_ma = []
248
- for i in reversed(self.list_ma):
249
- key_ma.append('_x')
250
- key_ma.append(f'ma{i}')
251
- segment_ma = self.df[key_ma].values
252
- self.segment_ma = segment_ma.reshape(segment_ma.shape[0], len(self.list_ma), 2).swapaxes(0, 1)
253
292
  self.edgecolor_ma = list(reversed(list_color))
254
293
 
255
294
  # 가격이동평균선 legend 생성
@@ -262,11 +301,24 @@ class SegmentMixin(DataMixin):
262
301
  for i in legends.legend_handles: i.set_picker(5)
263
302
  return
264
303
 
304
+ def _get_ma_segment(self):
305
+ if not self.list_ma: return
306
+
307
+ # 주가 차트 가격이동평균선
308
+ key_ma = []
309
+ for i in reversed(self.list_ma):
310
+ key_ma.append('_x')
311
+ key_ma.append(f'ma{i}')
312
+ segment_ma = self.df[key_ma].values
313
+ self.segment_ma = segment_ma.reshape(segment_ma.shape[0], len(self.list_ma), 2).swapaxes(0, 1)
314
+ return
315
+
265
316
  def _set_segments(self, index_start, index_end, simpler, set_ma):
266
317
  indsub = index_end - index_start
267
318
  if index_start < 0: index_start = 0
268
319
  if index_end < 1: index_end = 1
269
320
 
321
+ index_end += 1
270
322
  if indsub < self.limit_candle:
271
323
  self._set_candle_segments(index_start, index_end)
272
324
  elif indsub < self.limit_wick:
@@ -287,7 +339,7 @@ class SegmentMixin(DataMixin):
287
339
  self.collection_volume.set_edgecolor(self.edgecolor_volume[index_start:index_end])
288
340
 
289
341
  self.collection_ma.set_segments(self.segment_ma[:, index_start:index_end])
290
- self.collection_ma.set_edgecolor(list(reversed(self.edgecolor_ma)))
342
+ self.collection_ma.set_edgecolor(self.edgecolor_ma)
291
343
  return
292
344
 
293
345
  def _set_wick_segments(self, index_start, index_end, simpler=False):
@@ -307,7 +359,7 @@ class SegmentMixin(DataMixin):
307
359
  self.collection_volume.set_edgecolor(self.facecolor_volume[index_start:index_end])
308
360
 
309
361
  self.collection_ma.set_segments(self.segment_ma[:, index_start:index_end])
310
- self.collection_ma.set_edgecolor(list(reversed(self.edgecolor_ma)))
362
+ self.collection_ma.set_edgecolor(self.edgecolor_ma)
311
363
  return
312
364
 
313
365
  def _set_line_segments(self, index_start, index_end, simpler=False, set_ma=True):
@@ -329,7 +381,7 @@ class SegmentMixin(DataMixin):
329
381
  if not set_ma: self.collection_ma.set_segments([])
330
382
  else:
331
383
  self.collection_ma.set_segments(self.segment_ma[:, index_start:index_end])
332
- self.collection_ma.set_edgecolor(list(reversed(self.edgecolor_ma)))
384
+ self.collection_ma.set_edgecolor(self.edgecolor_ma)
333
385
  return
334
386
 
335
387
 
@@ -514,3 +566,18 @@ class Chart(BaseMixin, Mixin):
514
566
  self.on_pick(e)
515
567
  return super()._on_pick(e)
516
568
 
569
+ def _set_candle_segments(self, index_start, index_end):
570
+ super()._set_candle_segments(index_start, index_end)
571
+ self.set_segment(index_start, index_end)
572
+ return
573
+
574
+ def _set_wick_segments(self, index_start, index_end, simpler=False):
575
+ super()._set_wick_segments(index_start, index_end, simpler)
576
+ self.set_segment(index_start, index_end, simpler)
577
+ return
578
+
579
+ def _set_line_segments(self, index_start, index_end, simpler=False, set_ma=True):
580
+ super()._set_line_segments(index_start, index_end, simpler, set_ma)
581
+ self.set_segment(index_start, index_end, simpler, set_ma)
582
+ return
583
+
@@ -63,7 +63,7 @@ class PlotMixin(BM):
63
63
  self.ax_price.yaxis.set_major_formatter(lambda x, _: convert_unit(x, word=self.unit_price, digit=2))
64
64
  self.ax_volume.yaxis.set_major_formatter(lambda x, _: convert_unit(x, word=self.unit_volume, digit=2))
65
65
 
66
- gridKwargs = {'visible': True, 'linewidth': 1, 'color': '#d0d0d0', 'linestyle': '--'}
66
+ gridKwargs = {'visible': True, 'linewidth': 0.5, 'color': '#d0d0d0', 'linestyle': '-', 'dashes': (1, 0)}
67
67
  gridKwargs.update(self.gridKwargs)
68
68
  # 공통 설정
69
69
  for ax in (self.ax_slider, self.ax_price, self.ax_volume):
@@ -100,7 +100,7 @@ class CollectionMixin(PlotMixin):
100
100
  self.ax_slider.add_artist(self.collection_slider)
101
101
 
102
102
  # 슬라이더 네비게이터
103
- self.navigator = LineCollection([], animated=True, edgecolors=[self.color_navigator_cover, self.color_navigator_line], alpha=(0.2, 1.0))
103
+ self.navigator = LineCollection([], animated=True, edgecolors=[self.color_navigator_cover, self.color_navigator_line], alpha=(0.3, 1.0))
104
104
  self.ax_slider.add_artist(self.navigator)
105
105
 
106
106
  lineKwargs = {'edgecolor': 'k', 'linewidth': 1, 'linestyle': '-'}
@@ -131,9 +131,40 @@ class CollectionMixin(PlotMixin):
131
131
  segment_slider = self.df[keys + ['_x', self.close] ].values
132
132
  segment_slider = segment_slider.reshape(segment_slider.shape[0], len(self.list_ma)+1, 2).swapaxes(0, 1)
133
133
  self.collection_slider.set_segments(segment_slider)
134
+ return
135
+
136
+ def _get_color_segment(self):
137
+ super()._get_color_segment()
138
+
134
139
  self.collection_slider.set_edgecolor(self.edgecolor_ma + [self.color_priceline])
135
140
  return
136
141
 
142
+ def change_background_color(self, color):
143
+ super().change_background_color(color)
144
+
145
+ self.ax_slider.set_facecolor(color)
146
+ self.text_slider.set_backgroundcolor(color)
147
+ return
148
+
149
+ def change_tick_color(self, color):
150
+ super().change_tick_color(color)
151
+
152
+ for i in ['top', 'bottom', 'left', 'right']: self.ax_slider.spines[i].set_color(self.color_tick)
153
+ self.ax_slider.tick_params(colors=color)
154
+ return
155
+
156
+ def change_text_color(self, color):
157
+ super().change_text_color(color)
158
+
159
+ self.text_slider.set_color(color)
160
+ return
161
+
162
+ def change_line_color(self, color):
163
+ super().change_line_color(color)
164
+
165
+ self.text_slider.get_bbox_patch().set_edgecolor(color)
166
+ return
167
+
137
168
 
138
169
  class NavigatorMixin(CollectionMixin):
139
170
  def _set_slider_lim(self):
@@ -545,6 +576,21 @@ class Chart(BaseMixin, Mixin):
545
576
  self.on_pick(e)
546
577
  return super()._on_pick(e)
547
578
 
579
+ def _set_candle_segments(self, index_start, index_end):
580
+ super()._set_candle_segments(index_start, index_end)
581
+ self.set_segment(index_start, index_end)
582
+ return
583
+
584
+ def _set_wick_segments(self, index_start, index_end, simpler=False):
585
+ super()._set_wick_segments(index_start, index_end, simpler)
586
+ self.set_segment(index_start, index_end, simpler)
587
+ return
588
+
589
+ def _set_line_segments(self, index_start, index_end, simpler=False, set_ma=True):
590
+ super()._set_line_segments(index_start, index_end, simpler, set_ma)
591
+ self.set_segment(index_start, index_end, simpler, set_ma)
592
+ return
593
+
548
594
  def _on_move(self, e):
549
595
  super()._on_move(e)
550
596
  return self.on_move(e)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: seolpyo-mplchart
3
- Version: 1.0.0
3
+ Version: 1.1.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
@@ -42,7 +42,7 @@ Ethereum: 0x1c5fb8a5e0b1153cd4116c91736bd16fabf83520
42
42
 
43
43
  ![tkinter sample gif](https://raw.githubusercontent.com/white-seolpyo/seolpyo-mplchart/refs/heads/main/images/with%20tkinter.gif)
44
44
 
45
- ![english sample](https://raw.githubusercontent.com/white-seolpyo/seolpyo-mplchart/refs/heads/main/images/change%20format.png)
45
+ ![english sample](https://raw.githubusercontent.com/white-seolpyo/seolpyo-mplchart/refs/heads/main/images/change%20color.png)
46
46
 
47
47
  ![korean sample](https://raw.githubusercontent.com/white-seolpyo/seolpyo-mplchart/refs/heads/main/images/sample%20kor.png)
48
48
 
@@ -0,0 +1,13 @@
1
+ seolpyo_mplchart/__init__.py,sha256=nGssywV9mX38RSHQ_IpooDvRJ4e4Vdts_zGUVCg5Fsg,18114
2
+ seolpyo_mplchart/base.py,sha256=0qdImsIMPzTTkkHzPv479BVe_ojrn45FidGE46eT5x4,3797
3
+ seolpyo_mplchart/cursor.py,sha256=eIGOZqBCr7FLBE21dvY6rD4e8gOh2LwDM_AbE2ZZ0iY,20066
4
+ seolpyo_mplchart/draw.py,sha256=VijEN3Hmx6NwuqjBCvGhWojlZfJ2KkDyAOmw_JkgiJs,21528
5
+ seolpyo_mplchart/slider.py,sha256=diTjpCdciEVGP65gqqmSfC9VFUsFdV2RznPZT1N7BBI,22192
6
+ seolpyo_mplchart/test.py,sha256=TFnIXphJsl-B7iIhBh7-PZKUz2Gjh7mwNwrk8aUS4SA,180
7
+ seolpyo_mplchart/utils.py,sha256=a3XycRBTndrsjBw_1VKTxbSvOGpVYXHRK87v7azgRe8,1433
8
+ seolpyo_mplchart/data/apple.txt,sha256=0izAfweu1lLsC0IwVthdVlo9reG8KGbKGTSX5knI5Zc,1380864
9
+ seolpyo_mplchart/data/samsung.txt,sha256=UejaSkbzr4E5K3lkelCT0yJiWUPfmViBEaTyoXyphIs,2476424
10
+ seolpyo_mplchart-1.1.0.dist-info/METADATA,sha256=xnZNFsJUa-kdlYxvC4MDJbO5Xb6g9MJPNduHXtP1_Qo,2352
11
+ seolpyo_mplchart-1.1.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
12
+ seolpyo_mplchart-1.1.0.dist-info/top_level.txt,sha256=KgqFn7rKWize7OjMaTCHxKm9ie6vqnyb5c8fN7y_tSo,17
13
+ seolpyo_mplchart-1.1.0.dist-info/RECORD,,
@@ -1,13 +0,0 @@
1
- seolpyo_mplchart/__init__.py,sha256=4UKWKBXMeax9YwejtLgbCHjjFQ0HEEhNBdQx9v4Ez0w,14476
2
- seolpyo_mplchart/base.py,sha256=ofMDjWMLjPV-G_uJDiiUSR4X5eMPbrZDUg70R2YiPHE,3778
3
- seolpyo_mplchart/cursor.py,sha256=Wm1SDBunQleZgphArJR2bVNPZ3vDAcxNlC5HaQwKMRk,17908
4
- seolpyo_mplchart/draw.py,sha256=uY8W9swTKmNqyzPrhpuiCDNVqYoMEwqRGPJFSdwboRQ,18782
5
- seolpyo_mplchart/slider.py,sha256=0sVzwxiZHZv-f2UhRJUTSz2aJ32BsVyPvrcOpw2hn-U,20635
6
- seolpyo_mplchart/test.py,sha256=TFnIXphJsl-B7iIhBh7-PZKUz2Gjh7mwNwrk8aUS4SA,180
7
- seolpyo_mplchart/utils.py,sha256=a3XycRBTndrsjBw_1VKTxbSvOGpVYXHRK87v7azgRe8,1433
8
- seolpyo_mplchart/data/apple.txt,sha256=0izAfweu1lLsC0IwVthdVlo9reG8KGbKGTSX5knI5Zc,1380864
9
- seolpyo_mplchart/data/samsung.txt,sha256=UejaSkbzr4E5K3lkelCT0yJiWUPfmViBEaTyoXyphIs,2476424
10
- seolpyo_mplchart-1.0.0.dist-info/METADATA,sha256=zz-l83cwx8iT7i4Tt7GEmnNBCoA0yMGJTc3DFvtdZNs,2353
11
- seolpyo_mplchart-1.0.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
12
- seolpyo_mplchart-1.0.0.dist-info/top_level.txt,sha256=KgqFn7rKWize7OjMaTCHxKm9ie6vqnyb5c8fN7y_tSo,17
13
- seolpyo_mplchart-1.0.0.dist-info/RECORD,,