seolpyo-mplchart 0.1.3.1__py3-none-any.whl → 2.0.0.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.
Files changed (50) hide show
  1. seolpyo_mplchart/__init__.py +164 -99
  2. seolpyo_mplchart/_base.py +117 -0
  3. seolpyo_mplchart/_chart/__init__.py +137 -0
  4. seolpyo_mplchart/_chart/_base.py +217 -0
  5. seolpyo_mplchart/_chart/_cursor/__init__.py +2 -0
  6. seolpyo_mplchart/_chart/_cursor/_artist.py +217 -0
  7. seolpyo_mplchart/_chart/_cursor/_cursor.py +165 -0
  8. seolpyo_mplchart/_chart/_cursor/_info.py +187 -0
  9. seolpyo_mplchart/_chart/_draw/__init__.py +2 -0
  10. seolpyo_mplchart/_chart/_draw/_artist.py +50 -0
  11. seolpyo_mplchart/_chart/_draw/_data.py +314 -0
  12. seolpyo_mplchart/_chart/_draw/_draw.py +103 -0
  13. seolpyo_mplchart/_chart/_draw/_lim.py +265 -0
  14. seolpyo_mplchart/_chart/_slider/__init__.py +1 -0
  15. seolpyo_mplchart/_chart/_slider/_base.py +268 -0
  16. seolpyo_mplchart/_chart/_slider/_data.py +105 -0
  17. seolpyo_mplchart/_chart/_slider/_mouse.py +176 -0
  18. seolpyo_mplchart/_chart/_slider/_nav.py +204 -0
  19. seolpyo_mplchart/_chart/test.py +121 -0
  20. seolpyo_mplchart/_config/__init__.py +3 -0
  21. seolpyo_mplchart/_config/ax.py +28 -0
  22. seolpyo_mplchart/_config/candle.py +30 -0
  23. seolpyo_mplchart/_config/config.py +21 -0
  24. seolpyo_mplchart/_config/cursor.py +49 -0
  25. seolpyo_mplchart/_config/figure.py +41 -0
  26. seolpyo_mplchart/_config/format.py +51 -0
  27. seolpyo_mplchart/_config/ma.py +15 -0
  28. seolpyo_mplchart/_config/slider/__init__.py +2 -0
  29. seolpyo_mplchart/_config/slider/config.py +24 -0
  30. seolpyo_mplchart/_config/slider/figure.py +20 -0
  31. seolpyo_mplchart/_config/slider/nav.py +9 -0
  32. seolpyo_mplchart/_config/unit.py +19 -0
  33. seolpyo_mplchart/_config/utils.py +67 -0
  34. seolpyo_mplchart/_config/volume.py +26 -0
  35. seolpyo_mplchart/_cursor.py +559 -0
  36. seolpyo_mplchart/_draw.py +634 -0
  37. seolpyo_mplchart/_slider.py +634 -0
  38. seolpyo_mplchart/base.py +70 -67
  39. seolpyo_mplchart/cursor.py +308 -271
  40. seolpyo_mplchart/draw.py +449 -237
  41. seolpyo_mplchart/slider.py +451 -396
  42. seolpyo_mplchart/test.py +173 -24
  43. seolpyo_mplchart/utils.py +15 -4
  44. seolpyo_mplchart/xl_to_dict.py +47 -0
  45. seolpyo_mplchart-2.0.0.3.dist-info/METADATA +710 -0
  46. seolpyo_mplchart-2.0.0.3.dist-info/RECORD +50 -0
  47. {seolpyo_mplchart-0.1.3.1.dist-info → seolpyo_mplchart-2.0.0.3.dist-info}/WHEEL +1 -1
  48. seolpyo_mplchart-0.1.3.1.dist-info/METADATA +0 -49
  49. seolpyo_mplchart-0.1.3.1.dist-info/RECORD +0 -13
  50. {seolpyo_mplchart-0.1.3.1.dist-info → seolpyo_mplchart-2.0.0.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,176 @@
1
+ from matplotlib.backend_bases import MouseEvent, MouseButton, cursors
2
+
3
+ from ._data import BaseMixin as Base
4
+
5
+
6
+ class MouseMoveMixin(Base):
7
+ in_slider = False
8
+ is_click_slider = False
9
+
10
+ def _erase_crossline(self):
11
+ boolen = super()._erase_crossline()
12
+ if boolen:
13
+ return boolen
14
+
15
+ seg = self.collection_slider_vline.get_segments()
16
+ if seg:
17
+ self.collection_slider_vline.set_segments([])
18
+ return True
19
+ return False
20
+
21
+ def _on_move_action(self, e):
22
+ super()._on_move_action(e)
23
+
24
+ if self.in_slider:
25
+ self._restore_region(self.is_click_slider)
26
+ self._on_move_slider(e)
27
+ self.figure.canvas.blit()
28
+ elif self.in_price_chart or self.in_volume_chart:
29
+ self._restore_region()
30
+ self._draw_crossline(e)
31
+ self.figure.canvas.blit()
32
+ else:
33
+ if self._erase_crossline():
34
+ self._restore_region()
35
+ self.figure.canvas.blit()
36
+ return
37
+
38
+ def _on_move_action(self, e: MouseEvent):
39
+ self._check_ax(e)
40
+
41
+ self.intx = None
42
+ if self.in_slider or self.in_price_chart or self.in_volume_chart:
43
+ self._get_x(e)
44
+
45
+ self._set_cursor(e)
46
+ return
47
+
48
+ def _set_cursor(self, e: MouseEvent):
49
+ # 마우스 커서 변경
50
+ if self.is_click_slider:
51
+ return
52
+ elif not self.in_slider:
53
+ self.figure.canvas.set_cursor(cursors.POINTER)
54
+ return
55
+
56
+ navleft, navright = self.navcoordinate
57
+ if navleft == navright:
58
+ return
59
+
60
+ x = e.xdata.__round__()
61
+
62
+ leftmin = navleft - self._navLineWidth
63
+ leftmax = navleft + self._navLineWidth_half
64
+ rightmin = navright - self._navLineWidth_half
65
+ rightmax = navright + self._navLineWidth
66
+ if x < leftmin:
67
+ self.figure.canvas.set_cursor(cursors.POINTER)
68
+ elif x <= leftmax:
69
+ self.figure.canvas.set_cursor(cursors.RESIZE_HORIZONTAL)
70
+ elif x < rightmin:
71
+ self.figure.canvas.set_cursor(cursors.MOVE)
72
+ elif x <= rightmax:
73
+ self.figure.canvas.set_cursor(cursors.RESIZE_HORIZONTAL)
74
+ else:
75
+ self.figure.canvas.set_cursor(cursors.POINTER)
76
+ return
77
+
78
+ def _check_ax(self, e: MouseEvent):
79
+ ax = e.inaxes
80
+ if not ax or e.xdata is None or e.ydata is None:
81
+ self.in_slider, self.in_price_chart, self.in_volume_chart = (False, False, False)
82
+ else:
83
+ if ax is self.ax_slider:
84
+ self.in_slider = True
85
+ self.in_price_chart = False
86
+ self.in_volume_chart = False
87
+ elif ax is self.ax_price:
88
+ self.in_slider = False
89
+ self.in_price_chart = True
90
+ self.in_volume_chart = False
91
+ elif ax is self.ax_volume:
92
+ self.in_slider = False
93
+ self.in_price_chart = False
94
+ self.in_volume_chart = True
95
+ else:
96
+ self.in_slider = False
97
+ self.in_price_chart = False
98
+ self.in_volume_chart = False
99
+ return
100
+
101
+ def _on_move_slider(self, e: MouseEvent):
102
+ x = e.xdata
103
+ if self.intx is not None:
104
+ renderer = self.figure.canvas.renderer
105
+ seg = [((x, self.slider_ymin), (x, self.slider_ymax))]
106
+ self.collection_slider_vline.set_segments(seg)
107
+ self.collection_slider_vline.draw(renderer)
108
+
109
+ if self.in_slider:
110
+ self.artist_text_slider.set_text(f'{self.df["date"][self.intx]}')
111
+ self.artist_text_slider.set_x(x)
112
+ self.artist_text_slider.draw(renderer)
113
+ return
114
+
115
+ def _draw_crossline(self, e: MouseEvent):
116
+ x = e.xdata
117
+ self.collection_slider_vline.set_segments([((x-0.5, self.slider_ymin), (x-0.5, self.slider_ymax))])
118
+ self.collection_slider_vline.draw(self.figure.canvas.renderer)
119
+ return super()._draw_crossline(e)
120
+
121
+
122
+ class ClickMixin(MouseMoveMixin):
123
+ x_click = None
124
+ is_move = False
125
+ click_navleft, click_navright = (False, False)
126
+
127
+ def _connect_events(self):
128
+ super()._connect_events()
129
+
130
+ self.figure.canvas.mpl_connect('button_press_event', lambda x: self.on_click(x))
131
+ return
132
+
133
+ def on_click(self, e: MouseEvent):
134
+ self._on_click(e)
135
+ return
136
+
137
+ def _on_click(self, e: MouseEvent):
138
+ if self.in_slider and not self.is_click_slider:
139
+ if e.button == MouseButton.LEFT:
140
+ self._on_click_slider(e)
141
+ return
142
+
143
+ def _on_click_slider(self, e: MouseEvent):
144
+ self.background_with_nav_pre = self.background_with_nav
145
+
146
+ self.is_click_slider = True
147
+ self.figure.canvas.set_cursor(cursors.RESIZE_HORIZONTAL)
148
+
149
+ navleft, navright = self.navcoordinate
150
+ x = e.xdata.__round__()
151
+
152
+ leftmax = navleft + self._navLineWidth_half
153
+ rightmin = navright - self._navLineWidth_half
154
+
155
+ grater_than_left = leftmax < x
156
+ less_then_right = x < rightmin
157
+ if grater_than_left and less_then_right:
158
+ self.is_move = True
159
+ self.x_click = x
160
+ else:
161
+ leftmin = navleft - self._navLineWidth
162
+ rightmax = navright + self._navLineWidth
163
+ if not grater_than_left and leftmin <= x:
164
+ self.click_navleft = True
165
+ self.x_click = navright
166
+ elif not less_then_right and x <= rightmax:
167
+ self.click_navright = True
168
+ self.x_click = navleft
169
+ else:
170
+ self.x_click = x
171
+ return
172
+
173
+
174
+ class BaseMixin(ClickMixin):
175
+ pass
176
+
@@ -0,0 +1,204 @@
1
+ from matplotlib.backend_bases import MouseEvent, MouseButton, cursors
2
+
3
+ from ._mouse import BaseMixin as Base
4
+
5
+
6
+ class SliderSelectMixin(Base):
7
+ limit_ma = 8_000
8
+
9
+ def _on_move_slider(self, e):
10
+ if self.is_click_slider:
11
+ self._set_navcoordinate(e)
12
+ return super()._on_move_slider(e)
13
+
14
+ def _set_navcoordinate(self, e: MouseEvent):
15
+ navmin, navmax = self.navcoordinate
16
+
17
+ x = e.xdata.__int__()
18
+ if self.is_move:
19
+ xsub = self.x_click - x
20
+ navmin, navmax = (navmin-xsub, navmax-xsub)
21
+
22
+ # 값 보정
23
+ if navmax < 0:
24
+ navmin, navmax = (navmin-navmax, 0)
25
+ if self.index_list[-1] < navmin:
26
+ navmin, navmax = (self.index_list[-1], self.index_list[-1] + (navmax-navmin))
27
+
28
+ self.navcoordinate = (navmin, navmax)
29
+ self.x_click = x
30
+
31
+ self.axis(navmin, xmax=navmax+1, simpler=True, draw_ma=(navmax-navmin < self.limit_ma))
32
+
33
+ self._axis_navigator(navmin, navmax)
34
+ self.collection_navigator.draw(self.figure.canvas.renderer)
35
+
36
+ self.draw_artists()
37
+ self.background_with_nav = self.figure.canvas.renderer.copy_from_bbox(self.figure.bbox)
38
+ self._restore_region()
39
+ else:
40
+ navmin, navmax = (x, self.x_click) if x < self.x_click else (self.x_click, x)
41
+
42
+ # 슬라이더가 차트를 벗어나지 않도록 선택 영역 제한
43
+ if navmax < 0 or self.index_list[-1] < navmin:
44
+ seg = self.collection_navigator.get_segments()
45
+ navmin, navmax = (int(seg[1][0][0]), int(seg[3][0][0]))
46
+
47
+ nsub = navmax - navmin
48
+ min_distance = 5 if not self.min_distance or self.min_distance < 5 else self.min_distance
49
+ if nsub < min_distance:
50
+ self._restore_region(False, False)
51
+ self._axis_navigator(navmin, navmax)
52
+ self.collection_navigator.draw(self.figure.canvas.renderer)
53
+ else:
54
+ self.axis(navmin, xmax=navmax+1, simpler=True, draw_ma=(nsub < self.limit_ma))
55
+ self._axis_navigator(navmin, navmax)
56
+
57
+ self.collection_navigator.draw(self.figure.canvas.renderer)
58
+
59
+ self.draw_artists()
60
+ self.background_with_nav = self.figure.canvas.renderer.copy_from_bbox(self.figure.bbox)
61
+ self._restore_region(False, True)
62
+ return
63
+
64
+
65
+ class ReleaseMixin(SliderSelectMixin):
66
+ def _connect_events(self):
67
+ super()._connect_events()
68
+
69
+ self.figure.canvas.mpl_connect('button_release_event', lambda x: self.on_release(x))
70
+ return
71
+
72
+ def on_release(self, e: MouseEvent):
73
+ self._on_release(e)
74
+ return
75
+
76
+ def _on_release(self, e: MouseEvent):
77
+ if self.in_slider and self.is_click_slider:
78
+ if e.button == MouseButton.LEFT:
79
+ self._on_release_slider(e)
80
+ self.axis(self.vxmin, xmax=self.vxmax, simpler=False, draw_ma=True)
81
+ self.figure.canvas.draw()
82
+ return
83
+
84
+ def _on_release_slider(self, e: MouseEvent):
85
+ if not self.is_move:
86
+ seg = self.collection_navigator.get_segments()
87
+ navmin, navmax = (int(seg[1][0][0]), int(seg[3][0][0]))
88
+ nsub = navmax - navmin
89
+ min_distance = 5 if not self.min_distance or self.min_distance < 5 else self.min_distance
90
+ if min_distance <= nsub:
91
+ self.navcoordinate = (navmin, navmax)
92
+ else:
93
+ self.background_with_nav = self.background_with_nav_pre
94
+ navmin, navmax = self.navcoordinate
95
+ self.axis(navmin, xmax=navmax+1, simpler=False, draw_ma=True)
96
+ self._restore_region(False, True)
97
+ self.figure.canvas.blit()
98
+ self._axis_navigator(*self.navcoordinate)
99
+
100
+ self.is_click_slider = False
101
+ self.is_move = False
102
+ self.click_navleft, self.click_navright = (False, False)
103
+
104
+ # self.figure.canvas.draw()
105
+ return
106
+
107
+
108
+ class ChartClickMixin(ReleaseMixin):
109
+ is_click_chart = False
110
+
111
+ def _on_click(self, e: MouseEvent):
112
+ if e.button == MouseButton.LEFT:
113
+ if (
114
+ not self.is_click_chart
115
+ and (self.in_price_chart or self.in_volume_chart)
116
+ ):
117
+ self._on_click_chart(e)
118
+ elif not self.is_click_slider and self.in_slider:
119
+ self._on_click_slider(e)
120
+ return
121
+
122
+ def _on_click_chart(self, e: MouseEvent):
123
+ self.is_click_chart = True
124
+ x = e.xdata.__int__()
125
+ self.x_click = x - self.navcoordinate[0]
126
+ self.figure.canvas.set_cursor(cursors.RESIZE_HORIZONTAL)
127
+ return
128
+
129
+ def _on_release(self, e):
130
+ if e.button == MouseButton.LEFT:
131
+ if (
132
+ self.is_click_chart
133
+ and (self.in_price_chart or self.in_volume_chart)
134
+ ):
135
+ self._on_release_chart(e)
136
+ self.axis(self.vxmin, xmax=self.vxmax, simpler=False, draw_ma=True)
137
+ self.figure.canvas.draw()
138
+ elif self.is_click_slider and self.in_slider:
139
+ self._on_release_slider(e)
140
+ self.axis(self.vxmin, xmax=self.vxmax, simpler=False, draw_ma=True)
141
+ self.figure.canvas.draw()
142
+ return
143
+
144
+ def _on_release_chart(self, e):
145
+ self.is_click_chart = False
146
+ self.figure.canvas.set_cursor(cursors.POINTER)
147
+ return
148
+
149
+ def _set_cursor(self, e):
150
+ if self.is_click_chart:
151
+ return
152
+ return super()._set_cursor(e)
153
+
154
+ def _on_move_action(self, e):
155
+ super()._on_move_action(e)
156
+
157
+ if self.in_slider:
158
+ self._restore_region(self.is_click_slider)
159
+ self._on_move_slider(e)
160
+ self.figure.canvas.blit()
161
+ elif self.in_price_chart or self.in_volume_chart:
162
+ self._restore_region(self.is_click_chart)
163
+ if not self.is_click_chart:
164
+ self._draw_crossline(e)
165
+ else:
166
+ self._move_chart(e)
167
+ self.figure.canvas.blit()
168
+ else:
169
+ if self._erase_crossline():
170
+ self._restore_region()
171
+ self.figure.canvas.blit()
172
+ return
173
+
174
+ def _move_chart(self, e: MouseEvent):
175
+ left, right = self.navcoordinate
176
+ x = e.xdata.__int__() - left
177
+ xsub = x - self.x_click
178
+ if not xsub:
179
+ self.collection_navigator.draw(self.figure.canvas.renderer)
180
+ self.draw_artists()
181
+ else:
182
+ left, right = (left-xsub, right-xsub)
183
+ if right < 0 or self.df.index[-1] < left:
184
+ self._restore_region()
185
+ else:
186
+ self.x_click = x
187
+ self.navcoordinate = (left, right)
188
+ self.axis(left, xmax=right+1, simpler=True, draw_ma=(right-left < self.limit_ma))
189
+ self._axis_navigator(left, right)
190
+ self.collection_navigator.draw(self.figure.canvas.renderer)
191
+
192
+ self.draw_artists()
193
+ self.background_with_nav = self.figure.canvas.renderer.copy_from_bbox(self.figure.bbox)
194
+ self._restore_region()
195
+ return
196
+
197
+
198
+ class BaseMixin(ChartClickMixin):
199
+ pass
200
+
201
+
202
+ class Chart(BaseMixin):
203
+ pass
204
+
@@ -0,0 +1,121 @@
1
+ import sys
2
+ from pathlib import Path
3
+ name_pkg = 'seolpyo_mplchart'
4
+ path_pkg = Path(__file__)
5
+ while path_pkg.name != name_pkg:
6
+ path_pkg = path_pkg.parent
7
+ sys.path = [path_pkg.parent.__str__()] + sys.path
8
+
9
+ import json
10
+
11
+ import pandas as pd
12
+ import matplotlib.pyplot as plt
13
+
14
+
15
+ path_file = path_pkg / 'sample' / 'samsung.txt'
16
+ with open(path_file, 'r', encoding='utf-8') as txt:
17
+ data = json.load(txt)
18
+ df = pd.DataFrame(data[:100])
19
+
20
+ def test_base():
21
+ from seolpyo_mplchart._chart._base import Base
22
+ Base()
23
+ plt.show()
24
+ return
25
+
26
+ def test_draw():
27
+ from seolpyo_mplchart._chart._draw import Chart
28
+ c = Chart()
29
+ # c.CONFIG.CANDLE.FACECOLOR.bull_fall = 'y'
30
+ # c.CONFIG.CANDLE.EDGECOLOR.bull_fall = 'k'
31
+ # c.CONFIG.CANDLE.FACECOLOR.bear_rise = 'k'
32
+ # c.CONFIG.CANDLE.EDGECOLOR.bear_rise = 'pink'
33
+ # c.CONFIG.VOLUME.EDGECOLOR.rise = 'k'
34
+ # c.CONFIG.AX.facecolor = 'k'
35
+ # c.CONFIG.AX.TICK.edgecolor = 'yellow'
36
+ # c.CONFIG.AX.TICK.fontcolor = 'pink'
37
+ # c.set_color()
38
+ # c.volume = None
39
+ c.set_data(df)
40
+ plt.show()
41
+ return
42
+
43
+
44
+ def test_cursor():
45
+ from seolpyo_mplchart._chart._cursor._info import Chart
46
+ from seolpyo_mplchart._config import DEFAULTCONFIG_EN
47
+ c = Chart()
48
+ # c.CONFIG = DEFAULTCONFIG_EN
49
+ c.refresh()
50
+ c.fraction = True
51
+ c.set_data(df)
52
+ plt.show()
53
+ return
54
+
55
+ def test_slider():
56
+ from seolpyo_mplchart._chart._slider import Chart
57
+ c = Chart()
58
+ c.set_data(df)
59
+ plt.show()
60
+ return
61
+
62
+
63
+ if __name__ == '__main__':
64
+ # test_base()
65
+ # test_draw()
66
+ # test_cursor()
67
+ test_slider()
68
+
69
+
70
+ import seolpyo_mplchart as mc
71
+
72
+
73
+ # class Chart(mc.SliderChart):
74
+ # format_candleinfo = mc.format_candleinfo_ko + '\nCustom info: {ci}'
75
+ # format_volumeinfo = mc.format_volumeinfo_ko
76
+ # min_distance = 2
77
+
78
+ # def __init__(self, *args, **kwargs):
79
+ # super().__init__(*args, **kwargs)
80
+ # self.collection_candle.set_linewidth(1.5)
81
+ # return
82
+
83
+ # def get_info_kwargs(self, is_price, **kwargs):
84
+ # if is_price:
85
+ # kwargs['ci'] = 'You can add Custom text Info or Change text info.'
86
+ # kwargs['close'] = 'You can Change close price info.'
87
+ # return kwargs
88
+
89
+ # def get_candle_segment(self, *, x, left, right, top, bottom, is_up, high, low):
90
+ # if is_up:
91
+ # return (
92
+ # (x, top), (right, top), (x, top),
93
+ # (x, high),
94
+ # (x, low),
95
+ # (x, bottom), (left, bottom), (x, bottom),
96
+ # )
97
+ # else:
98
+ # return (
99
+ # (x, bottom), (right, bottom), (x, bottom),
100
+ # (x, high),
101
+ # (x, low),
102
+ # (x, top), (left, top), (x, top),
103
+ # )
104
+
105
+
106
+
107
+ # C = Chart()
108
+ # path_file = Path(__file__).parent / 'sample/samsung.txt'
109
+ # # C.format_candleinfo = mc.format_candleinfo_ko
110
+ # # C.format_volumeinfo = mc.format_volumeinfo_ko
111
+ # # C.volume = None
112
+
113
+
114
+ # with open(path_file, 'r', encoding='utf-8') as txt:
115
+ # data = json.load(txt)
116
+ # df = pd.DataFrame(data[:100])
117
+
118
+ # C.set_data(df)
119
+
120
+ # mc.show()
121
+ # mc.close()
@@ -0,0 +1,3 @@
1
+ from .config import DEFAULTCONFIG, DEFAULTCONFIG_EN, ConfigData
2
+ from .slider import SLIDERCONFIG, SLIDERCONFIG_EN, SliderConfigData
3
+
@@ -0,0 +1,28 @@
1
+
2
+
3
+ class Grid:
4
+ def __init__(self):
5
+ self.visible = True
6
+ self.linewidth = 0.7
7
+ self.color: str|tuple[float, float, float, float] = '#d0d0d0'
8
+ self.linestyle = '-'
9
+ self.dashes = (1, 0)
10
+ self.axis = 'both'
11
+
12
+ GRID = Grid()
13
+
14
+ class TickData:
15
+ def __init__(self):
16
+ self.edgecolor: str|tuple[float, float, float, float] = 'k'
17
+ self.fontcolor: str|tuple[float, float, float, float] = 'k'
18
+
19
+ TICK = TickData()
20
+
21
+ class AxData:
22
+ def __init__(self):
23
+ self.facecolor: str|tuple[float, float, float, float] = '#fafafa'
24
+ self.GRID = GRID
25
+ self.TICK = TICK
26
+
27
+ AX = AxData()
28
+
@@ -0,0 +1,30 @@
1
+
2
+
3
+ class CandleFaceColorData:
4
+ def __init__(self):
5
+ self.bull_rise: str|tuple[float, float, float, float] = '#FF2400'
6
+ self.bull_fall: str|tuple[float, float, float, float] = 'w'
7
+ self.bear_fall: str|tuple[float, float, float, float] = '#1E90FF'
8
+ self.bear_rise: str|tuple[float, float, float, float] = 'w'
9
+
10
+ CANDLEFACECOLOR = CandleFaceColorData()
11
+
12
+ class CandleEdgeColorData:
13
+ def __init__(self):
14
+ self.bull_rise: str|tuple[float, float, float, float] = '#FF2400'
15
+ self.bull_fall: str|tuple[float, float, float, float] = '#FF2400'
16
+ self.bear_fall: str|tuple[float, float, float, float] = '#1E90FF'
17
+ self.bear_rise: str|tuple[float, float, float, float] = '#1E90FF'
18
+ self.doji: str|tuple[float, float, float, float] = 'k'
19
+
20
+ CANDLEEDGECOLOR = CandleEdgeColorData()
21
+
22
+ class CandleData:
23
+ def __init__(self):
24
+ self.half_width = 0.24
25
+ self.line_color: str|tuple[float, float, float, float] = 'k'
26
+ self.FACECOLOR = CANDLEFACECOLOR
27
+ self.EDGECOLOR = CANDLEEDGECOLOR
28
+
29
+ CANDLE = CandleData()
30
+
@@ -0,0 +1,21 @@
1
+ from . import figure, ax, candle, volume, ma, unit, cursor, format
2
+
3
+
4
+ class ConfigData:
5
+ def __init__(self):
6
+ self.FIGURE = figure.FIGURE
7
+ self.UNIT = unit.UNIT
8
+ self.AX = ax.AX
9
+ self.CANDLE = candle.CANDLE
10
+ self.VOLUME = volume.VOLUME
11
+ self.MA = ma.MA
12
+ self.CURSOR = cursor.CURSOR
13
+ self.FORMAT = format.FORMAT
14
+
15
+ DEFAULTCONFIG = ConfigData()
16
+
17
+ DEFAULTCONFIG_EN = ConfigData()
18
+ DEFAULTCONFIG_EN.UNIT = unit.UNIT_EN
19
+ DEFAULTCONFIG_EN.MA = ma.MA_EN
20
+ DEFAULTCONFIG_EN.FORMAT = format.FORMAT_EN
21
+
@@ -0,0 +1,49 @@
1
+
2
+
3
+ class CrossLineData:
4
+ def __init__(self):
5
+ self.edgecolor = 'k'
6
+ self.linewidth = 1
7
+ self.linestyle = '-'
8
+
9
+ CROSSLINE = CrossLineData()
10
+
11
+ class BBoxData:
12
+ def __init__(self):
13
+ self.boxstyle = 'round'
14
+ self.facecolor = 'w'
15
+ self.edgecolor = 'k'
16
+
17
+ BBOX = BBoxData()
18
+
19
+ class Text:
20
+ def __init__(self):
21
+ self.color = 'k'
22
+ self.BBOX = BBOX
23
+
24
+ def to_dict(self):
25
+ data = {}
26
+ for k, v in self.__dict__.items():
27
+ if k == 'BBOX':
28
+ k = k.lower()
29
+ v = self.BBOX.__dict__
30
+ data[k] = v
31
+ return data
32
+
33
+ TEXT = Text()
34
+
35
+ class Box:
36
+ def __init__(self):
37
+ self.edgecolor = 'k'
38
+ self.linewidth = 1.2
39
+
40
+ BOX = Box()
41
+
42
+ class Cursor:
43
+ def __init__(self):
44
+ self.CROSSLINE = CROSSLINE
45
+ self.TEXT = TEXT
46
+ self.BOX = BOX
47
+
48
+ CURSOR = Cursor()
49
+
@@ -0,0 +1,41 @@
1
+
2
+
3
+ class RatioData:
4
+ def __init__(self):
5
+ self.legend = 2
6
+ self.price = 18
7
+ self.volume = 5
8
+
9
+ RATIO = RatioData()
10
+
11
+ class WatermarkData:
12
+ def __init__(self):
13
+ self.alpha = 0.2
14
+ self.color = 'k'
15
+ self.fontsize = 20
16
+
17
+ WATERMARK = WatermarkData()
18
+
19
+ class AdjustData:
20
+ def __init__(self):
21
+ # 여백
22
+ self.top = 0.95
23
+ self.bottom = 0.05
24
+ self.left = 0.01
25
+ self.right = 0.93
26
+ # 플롯간 간격
27
+ self.wspace = 0
28
+ self.hspace = 0
29
+
30
+ ADJUST = AdjustData()
31
+
32
+ class FigureData:
33
+ def __init__(self):
34
+ self.facecolor: str|tuple[float, float, float, float] = 'w'
35
+ self.figsize = (14, 7)
36
+ self.RATIO = RATIO
37
+ self.ADJUST = ADJUST
38
+ self.WATERMARK = WATERMARK
39
+
40
+ FIGURE = FigureData()
41
+