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.
- seolpyo_mplchart/__init__.py +164 -99
- seolpyo_mplchart/_base.py +117 -0
- seolpyo_mplchart/_chart/__init__.py +137 -0
- seolpyo_mplchart/_chart/_base.py +217 -0
- seolpyo_mplchart/_chart/_cursor/__init__.py +2 -0
- seolpyo_mplchart/_chart/_cursor/_artist.py +217 -0
- seolpyo_mplchart/_chart/_cursor/_cursor.py +165 -0
- seolpyo_mplchart/_chart/_cursor/_info.py +187 -0
- seolpyo_mplchart/_chart/_draw/__init__.py +2 -0
- seolpyo_mplchart/_chart/_draw/_artist.py +50 -0
- seolpyo_mplchart/_chart/_draw/_data.py +314 -0
- seolpyo_mplchart/_chart/_draw/_draw.py +103 -0
- seolpyo_mplchart/_chart/_draw/_lim.py +265 -0
- seolpyo_mplchart/_chart/_slider/__init__.py +1 -0
- seolpyo_mplchart/_chart/_slider/_base.py +268 -0
- seolpyo_mplchart/_chart/_slider/_data.py +105 -0
- seolpyo_mplchart/_chart/_slider/_mouse.py +176 -0
- seolpyo_mplchart/_chart/_slider/_nav.py +204 -0
- seolpyo_mplchart/_chart/test.py +121 -0
- seolpyo_mplchart/_config/__init__.py +3 -0
- seolpyo_mplchart/_config/ax.py +28 -0
- seolpyo_mplchart/_config/candle.py +30 -0
- seolpyo_mplchart/_config/config.py +21 -0
- seolpyo_mplchart/_config/cursor.py +49 -0
- seolpyo_mplchart/_config/figure.py +41 -0
- seolpyo_mplchart/_config/format.py +51 -0
- seolpyo_mplchart/_config/ma.py +15 -0
- seolpyo_mplchart/_config/slider/__init__.py +2 -0
- seolpyo_mplchart/_config/slider/config.py +24 -0
- seolpyo_mplchart/_config/slider/figure.py +20 -0
- seolpyo_mplchart/_config/slider/nav.py +9 -0
- seolpyo_mplchart/_config/unit.py +19 -0
- seolpyo_mplchart/_config/utils.py +67 -0
- seolpyo_mplchart/_config/volume.py +26 -0
- seolpyo_mplchart/_cursor.py +559 -0
- seolpyo_mplchart/_draw.py +634 -0
- seolpyo_mplchart/_slider.py +634 -0
- seolpyo_mplchart/base.py +70 -67
- seolpyo_mplchart/cursor.py +308 -271
- seolpyo_mplchart/draw.py +449 -237
- seolpyo_mplchart/slider.py +451 -396
- seolpyo_mplchart/test.py +173 -24
- seolpyo_mplchart/utils.py +15 -4
- seolpyo_mplchart/xl_to_dict.py +47 -0
- seolpyo_mplchart-2.0.0.3.dist-info/METADATA +710 -0
- seolpyo_mplchart-2.0.0.3.dist-info/RECORD +50 -0
- {seolpyo_mplchart-0.1.3.1.dist-info → seolpyo_mplchart-2.0.0.3.dist-info}/WHEEL +1 -1
- seolpyo_mplchart-0.1.3.1.dist-info/METADATA +0 -49
- seolpyo_mplchart-0.1.3.1.dist-info/RECORD +0 -13
- {seolpyo_mplchart-0.1.3.1.dist-info → seolpyo_mplchart-2.0.0.3.dist-info}/top_level.txt +0 -0
seolpyo_mplchart/__init__.py
CHANGED
|
@@ -1,120 +1,185 @@
|
|
|
1
|
-
"""
|
|
2
|
-
This software includes Matplotlib, which is licensed under the BSD License.
|
|
3
|
-
Matplotlib Copyright (c) 2012- Matplotlib Development Team.
|
|
4
|
-
Full license can be found in the LICENSE file or at https://matplotlib.org/stable/users/license.html
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
|
|
8
1
|
import json
|
|
9
|
-
from pathlib import Path
|
|
10
2
|
from typing import Literal
|
|
3
|
+
from pathlib import Path
|
|
11
4
|
|
|
12
5
|
import matplotlib.pyplot as plt
|
|
13
|
-
from matplotlib.figure import Figure
|
|
14
6
|
import pandas as pd
|
|
15
7
|
|
|
16
|
-
|
|
17
|
-
from .
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
__all__ = [
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
color_navigatorline: Color of left and right dividing lines in selected area. default '#1e78ff'
|
|
60
|
-
color_navigator: Color of unselected area. default 'k'
|
|
61
|
-
|
|
62
|
-
color_up: The color of the candle. When the closing price is greater than the opening price. default '#fe3032'
|
|
63
|
-
color_down: The color of the candle. When the opening price is greater than the opening price. default '#0095ff'
|
|
64
|
-
color_flat: The color of the candle. WWhen the closing price is the same as the opening price. default 'k'
|
|
65
|
-
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'
|
|
66
|
-
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'
|
|
67
|
-
colors_volume: The color of the volume bar. default '#1f77b4'
|
|
68
|
-
|
|
69
|
-
lineKwargs: Options applied to horizontal and vertical lines drawn along the mouse position. default dict(edgecolor='k', linewidth=1, linestyle='-')
|
|
70
|
-
textboxKwargs: Options that apply to the information text box. dufault dict(boxstyle='round', facecolor='w')
|
|
71
|
-
|
|
72
|
-
fraction: Decide whether to express information as a fraction. default False
|
|
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
|
-
digit_price, digit_volume: Number of decimal places expressed in informational text. default (0, 0)
|
|
76
|
-
|
|
77
|
-
min_distance: Minimum number of candles that can be selected with the slider. default 30
|
|
78
|
-
simpler: Decide whether to display candles simply when moving the chart. default False
|
|
79
|
-
limit_volume: Maximum number of volume bars drawn when moving the chart. default 2_000
|
|
80
|
-
"""
|
|
81
|
-
pass
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
_name = {'samsung', 'apple'}
|
|
85
|
-
def sample(name: Literal['samsung', 'apple']='samsung'):
|
|
86
|
-
if name not in _name:
|
|
87
|
-
print('name should be either samsung or apple.')
|
|
88
|
-
return
|
|
89
|
-
file = Path(__file__).parent / f'data/{name}.txt'
|
|
90
|
-
with open(file, 'r', encoding='utf-8') as txt:
|
|
8
|
+
from ._chart import OnlyChart, CursorChart, SliderChart
|
|
9
|
+
from ._config import DEFAULTCONFIG, DEFAULTCONFIG_EN, SLIDERCONFIG, SLIDERCONFIG_EN, ConfigData, SliderConfigData
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
# __all__ = [
|
|
13
|
+
# 'path_samsung', 'path_apple',
|
|
14
|
+
# 'format_candleinfo_ko', 'format_volumeinfo_ko',
|
|
15
|
+
# 'format_candleinfo_en', 'format_volumeinfo_en',
|
|
16
|
+
# 'sample', 'switch_backend', 'show', 'close',
|
|
17
|
+
# 'OnlyChart', 'CursorChart', 'SliderChart',
|
|
18
|
+
# 'set_theme',
|
|
19
|
+
# ]
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
pkg_name = 'seolpyo_mplchart'
|
|
23
|
+
path_pkg = Path(__file__)
|
|
24
|
+
while path_pkg.name != pkg_name:
|
|
25
|
+
path_pkg = path_pkg.parent
|
|
26
|
+
path_samsung = path_pkg / 'sample' / 'samsung.txt'
|
|
27
|
+
path_apple = path_pkg / 'sample' / 'apple.txt'
|
|
28
|
+
|
|
29
|
+
def sample(stock: Literal['samsung', 'apple']='samsung', chart: Literal['Chart', 'CursorChart', 'SliderChart']='SliderChart'):
|
|
30
|
+
d = {
|
|
31
|
+
'Chart': OnlyChart,
|
|
32
|
+
'CursorChart': CursorChart,
|
|
33
|
+
'SliderChart': SliderChart,
|
|
34
|
+
}
|
|
35
|
+
C = d[chart]
|
|
36
|
+
path_file = path_samsung if stock == 'samsung' else path_apple
|
|
37
|
+
if stock == 'samsung':
|
|
38
|
+
if chart == 'SliderChart':
|
|
39
|
+
config = SLIDERCONFIG
|
|
40
|
+
else:
|
|
41
|
+
config = DEFAULTCONFIG
|
|
42
|
+
else:
|
|
43
|
+
if chart == 'SliderChart':
|
|
44
|
+
config = SLIDERCONFIG_EN
|
|
45
|
+
else:
|
|
46
|
+
config = DEFAULTCONFIG_EN
|
|
47
|
+
|
|
48
|
+
CHART: SliderChart = C(config)
|
|
49
|
+
|
|
50
|
+
with open(path_file, 'r', encoding='utf-8') as txt:
|
|
91
51
|
data = json.load(txt)
|
|
92
|
-
data = data
|
|
93
52
|
df = pd.DataFrame(data)
|
|
94
53
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
c.unit_price = '$'
|
|
98
|
-
c.unit_volume = ' vol'
|
|
99
|
-
c.digit_price = 3
|
|
100
|
-
c.label_ma = 'ma{}'
|
|
101
|
-
c.candleformat = '{}\n\nend: {}\nrate: {}\ncompare: {}\nopen: {}({})\nhigh: {}({})\nlow: {}({})\nvolume: {}({})'
|
|
102
|
-
c.volumeformat = '{}\n\nvolume: {}\nvolume rate: {}'
|
|
103
|
-
c.set_data(df)
|
|
54
|
+
CHART.set_data(df)
|
|
55
|
+
|
|
104
56
|
show()
|
|
105
57
|
close()
|
|
106
58
|
return
|
|
107
59
|
|
|
108
60
|
|
|
109
|
-
def
|
|
110
|
-
|
|
61
|
+
def switch_backend(newbackend='TkAgg'):
|
|
62
|
+
"call matplotlib.pyplot.switch_backend(newbackend)"
|
|
63
|
+
return plt.switch_backend(newbackend)
|
|
111
64
|
|
|
112
65
|
|
|
113
|
-
def close(fig
|
|
66
|
+
def close(fig='all'):
|
|
67
|
+
"call matplotlib.pyplot.close(fig)"
|
|
114
68
|
return plt.close(fig)
|
|
115
69
|
|
|
70
|
+
def show(Close=True):
|
|
71
|
+
"""
|
|
72
|
+
call matplotlib.pyplot.show()
|
|
73
|
+
```if Close``` if True, run matplotlib.pyplot.close('all') after window closee.
|
|
74
|
+
"""
|
|
75
|
+
plt.show()
|
|
76
|
+
if Close:
|
|
77
|
+
close()
|
|
78
|
+
return
|
|
116
79
|
|
|
117
|
-
if __name__ == '__main__':
|
|
118
|
-
sample('apple')
|
|
119
80
|
|
|
81
|
+
def set_theme(config: ConfigData|SliderConfigData, theme: Literal['light', 'dark']='dark'):
|
|
82
|
+
if theme == 'light':
|
|
83
|
+
# axes
|
|
84
|
+
config.FIGURE.facecolor = '#fafafa'
|
|
85
|
+
config.AX.facecolor = '#fafafa'
|
|
86
|
+
config.AX.TICK.edgecolor = 'k'
|
|
87
|
+
config.AX.TICK.fontcolor = 'k'
|
|
88
|
+
config.AX.GRID.color = '#d0d0d0'
|
|
89
|
+
|
|
90
|
+
# candle
|
|
91
|
+
config.CANDLE.line_color = 'k'
|
|
92
|
+
config.CANDLE.FACECOLOR.bull_rise = '#FF2400'
|
|
93
|
+
config.CANDLE.FACECOLOR.bull_fall = 'w'
|
|
94
|
+
config.CANDLE.FACECOLOR.bear_fall = '#1E90FF'
|
|
95
|
+
config.CANDLE.FACECOLOR.bear_rise = 'w'
|
|
96
|
+
|
|
97
|
+
config.CANDLE.EDGECOLOR.bull_rise = '#FF2400'
|
|
98
|
+
config.CANDLE.EDGECOLOR.bull_fall = '#FF2400'
|
|
99
|
+
config.CANDLE.EDGECOLOR.bear_fall = '#1E90FF'
|
|
100
|
+
config.CANDLE.EDGECOLOR.bear_rise = '#1E90FF'
|
|
101
|
+
config.CANDLE.EDGECOLOR.doji = 'k'
|
|
102
|
+
|
|
103
|
+
# volume
|
|
104
|
+
config.VOLUME.FACECOLOR.rise = '#F27663'
|
|
105
|
+
config.VOLUME.FACECOLOR.fall = '#70B5F2'
|
|
106
|
+
config.VOLUME.FACECOLOR.doji = '#BEBEBE'
|
|
107
|
+
|
|
108
|
+
config.VOLUME.EDGECOLOR.rise = '#F27663'
|
|
109
|
+
config.VOLUME.EDGECOLOR.fall = '#70B5F2'
|
|
110
|
+
config.VOLUME.EDGECOLOR.doji = '#BEBEBE'
|
|
111
|
+
|
|
112
|
+
# ma
|
|
113
|
+
config.MA.color_default = 'k'
|
|
114
|
+
config.MA.color_list = ['#8B00FF', '#008000', '#A0522D', '#008B8B', '#FF0080']
|
|
115
|
+
# text
|
|
116
|
+
config.CURSOR.TEXT.BBOX.facecolor = 'w'
|
|
117
|
+
config.CURSOR.TEXT.BBOX.edgecolor = 'k'
|
|
118
|
+
config.CURSOR.TEXT.color = 'k'
|
|
119
|
+
|
|
120
|
+
# box
|
|
121
|
+
config.CURSOR.BOX.edgecolor = 'k'
|
|
122
|
+
|
|
123
|
+
# line
|
|
124
|
+
config.CURSOR.CROSSLINE.edgecolor = 'k'
|
|
125
|
+
|
|
126
|
+
# wartermark
|
|
127
|
+
config.FIGURE.WATERMARK.color = 'k'
|
|
128
|
+
|
|
129
|
+
if getattr(config, 'SLIDER', None):
|
|
130
|
+
config.SLIDER.NAVIGATOR.edgecolor = '#2962FF'
|
|
131
|
+
config.SLIDER.NAVIGATOR.facecolor = '#0000002E'
|
|
132
|
+
elif theme == 'dark':
|
|
133
|
+
# axes
|
|
134
|
+
config.FIGURE.facecolor = '#0f0f0f'
|
|
135
|
+
config.AX.facecolor = '#0f0f0f'
|
|
136
|
+
config.AX.TICK.edgecolor = '#dbdbdb'
|
|
137
|
+
config.AX.TICK.fontcolor = '#dbdbdb'
|
|
138
|
+
config.AX.GRID.color = '#1c1c1c'
|
|
139
|
+
|
|
140
|
+
# candle
|
|
141
|
+
config.CANDLE.line_color = 'w'
|
|
142
|
+
config.CANDLE.FACECOLOR.bull_rise = '#089981'
|
|
143
|
+
config.CANDLE.FACECOLOR.bull_fall = '#0f0f0f'
|
|
144
|
+
config.CANDLE.FACECOLOR.bear_fall = '#f23645'
|
|
145
|
+
config.CANDLE.FACECOLOR.bear_rise = '#0f0f0f'
|
|
146
|
+
|
|
147
|
+
config.CANDLE.EDGECOLOR.bull_rise = '#089981'
|
|
148
|
+
config.CANDLE.EDGECOLOR.bull_fall = '#089981'
|
|
149
|
+
config.CANDLE.EDGECOLOR.bear_fall = '#f23645'
|
|
150
|
+
config.CANDLE.EDGECOLOR.bear_rise = '#f23645'
|
|
151
|
+
config.CANDLE.EDGECOLOR.doji = 'w'
|
|
152
|
+
|
|
153
|
+
# volume
|
|
154
|
+
config.VOLUME.FACECOLOR.rise = '#2A8076'
|
|
155
|
+
config.VOLUME.FACECOLOR.fall = '#BE4F58'
|
|
156
|
+
config.VOLUME.FACECOLOR.doji = '#82828A'
|
|
157
|
+
|
|
158
|
+
config.VOLUME.EDGECOLOR.rise = '#2A8076'
|
|
159
|
+
config.VOLUME.EDGECOLOR.fall = '#BE4F58'
|
|
160
|
+
config.VOLUME.EDGECOLOR.doji = '#82828A'
|
|
161
|
+
|
|
162
|
+
# ma
|
|
163
|
+
config.MA.color_default = 'w'
|
|
164
|
+
config.MA.color_list = ['#FFB300', '#03A9F4', '#AB47BC', '#8BC34A', '#EF5350']
|
|
165
|
+
|
|
166
|
+
# text
|
|
167
|
+
config.CURSOR.TEXT.BBOX.facecolor = '#3d3d3d'
|
|
168
|
+
config.CURSOR.TEXT.BBOX.edgecolor = '#ffffff'
|
|
169
|
+
config.CURSOR.TEXT.color = '#ffffff'
|
|
170
|
+
|
|
171
|
+
# box
|
|
172
|
+
config.CURSOR.BOX.edgecolor = 'w'
|
|
173
|
+
|
|
174
|
+
# line
|
|
175
|
+
config.CURSOR.CROSSLINE.edgecolor = '#9c9c9c'
|
|
176
|
+
|
|
177
|
+
# wartermark
|
|
178
|
+
config.FIGURE.WATERMARK.color = 'w'
|
|
179
|
+
|
|
180
|
+
if getattr(config, 'SLIDER', None):
|
|
181
|
+
config.SLIDER.NAVIGATOR.edgecolor = "#00A6FF"
|
|
182
|
+
config.SLIDER.NAVIGATOR.facecolor = '#FFFFFF4D'
|
|
183
|
+
|
|
184
|
+
return config
|
|
120
185
|
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
from re import search
|
|
2
|
+
|
|
3
|
+
import matplotlib.pyplot as plt
|
|
4
|
+
import matplotlib.style as mplstyle
|
|
5
|
+
from matplotlib.axes import Axes
|
|
6
|
+
from matplotlib.backends.backend_agg import FigureCanvasAgg
|
|
7
|
+
from matplotlib.figure import Figure as Fig
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
from .utils import dict_unit, dict_unit_en
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
try: plt.switch_backend('TkAgg')
|
|
14
|
+
except: pass
|
|
15
|
+
|
|
16
|
+
# 한글 깨짐 문제 방지
|
|
17
|
+
try: plt.rcParams['font.family'] ='Malgun Gothic'
|
|
18
|
+
except: pass
|
|
19
|
+
|
|
20
|
+
mplstyle.use('fast')
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def convert_unit(value: float, digit=0, word='원'):
|
|
24
|
+
v = value.__abs__()
|
|
25
|
+
du = dict_unit if search('[가-힣]', word) else dict_unit_en
|
|
26
|
+
for unit, n in du.items():
|
|
27
|
+
if n <= v:
|
|
28
|
+
num = (value / n).__round__(digit)
|
|
29
|
+
if not num % 1: num = int(num)
|
|
30
|
+
return f'{num:,}{unit} {word}'
|
|
31
|
+
value = value.__round__(digit)
|
|
32
|
+
if not value % 1: value = int(value)
|
|
33
|
+
elif value < 10: digit = 2
|
|
34
|
+
text = f'{value:,}{word}'
|
|
35
|
+
return text
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class Figure(Fig):
|
|
39
|
+
canvas: FigureCanvasAgg
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
class Base:
|
|
43
|
+
figure: Figure
|
|
44
|
+
|
|
45
|
+
figsize = (14, 7)
|
|
46
|
+
ratio_ax_legend, ratio_ax_price, ratio_ax_volume = (2, 18, 5)
|
|
47
|
+
adjust = dict(
|
|
48
|
+
top=0.95, bottom=0.05, left=0.01, right=0.93, # 여백
|
|
49
|
+
wspace=0, hspace=0 # 플롯간 간격
|
|
50
|
+
)
|
|
51
|
+
|
|
52
|
+
title = 'seolpyo mplchart'
|
|
53
|
+
color_background = '#fafafa'
|
|
54
|
+
gridKwargs = {}
|
|
55
|
+
color_tick, color_tick_label = ('k', 'k')
|
|
56
|
+
|
|
57
|
+
unit_price, unit_volume = ('원', '주')
|
|
58
|
+
|
|
59
|
+
def draw_canvas(self): return self.figure.canvas.draw()
|
|
60
|
+
def blit_canvas(self): return self.figure.canvas.blit()
|
|
61
|
+
|
|
62
|
+
def __init__(self, *args, **kwargs):
|
|
63
|
+
# 기본 툴바 비활성화
|
|
64
|
+
plt.rcParams['toolbar'] = 'None'
|
|
65
|
+
# plt.rcParams['figure.dpi'] = 600
|
|
66
|
+
|
|
67
|
+
self._get_plot()
|
|
68
|
+
return
|
|
69
|
+
|
|
70
|
+
def _get_plot(self):
|
|
71
|
+
self.figure, axes = plt.subplots(
|
|
72
|
+
3, # row 수
|
|
73
|
+
figsize=self.figsize, # 기본 크기
|
|
74
|
+
height_ratios=(self.ratio_ax_legend, self.ratio_ax_price, self.ratio_ax_volume) # row 크기 비율
|
|
75
|
+
)
|
|
76
|
+
axes: list[Axes]
|
|
77
|
+
self.ax_legend, self.ax_price, self.ax_volume = axes
|
|
78
|
+
self.ax_legend.set_label('legend ax')
|
|
79
|
+
self.ax_price.set_label('price ax')
|
|
80
|
+
self.ax_volume.set_label('volume ax')
|
|
81
|
+
|
|
82
|
+
self.figure.canvas.manager.set_window_title(f'{self.title}')
|
|
83
|
+
self.figure.set_facecolor(self.color_background)
|
|
84
|
+
|
|
85
|
+
# 플롯간 간격 제거(Configure subplots)
|
|
86
|
+
self.figure.subplots_adjust(**self.adjust)
|
|
87
|
+
|
|
88
|
+
self.ax_legend.set_axis_off()
|
|
89
|
+
|
|
90
|
+
# y ticklabel foramt 설정
|
|
91
|
+
self.ax_price.yaxis.set_major_formatter(lambda x, _: convert_unit(x, word=self.unit_price, digit=2))
|
|
92
|
+
self.ax_volume.yaxis.set_major_formatter(lambda x, _: convert_unit(x, word=self.unit_volume, digit=2))
|
|
93
|
+
|
|
94
|
+
gridKwargs = {'visible': True, 'linewidth': 0.7, 'color': '#d0d0d0', 'linestyle': '-', 'dashes': (1, 0)}
|
|
95
|
+
gridKwargs.update(self.gridKwargs)
|
|
96
|
+
# 공통 설정
|
|
97
|
+
for ax in (self.ax_price, self.ax_volume):
|
|
98
|
+
ax.xaxis.set_animated(True)
|
|
99
|
+
ax.yaxis.set_animated(True)
|
|
100
|
+
|
|
101
|
+
# x tick 외부 눈금 표시하지 않기
|
|
102
|
+
ax.xaxis.set_ticks_position('none')
|
|
103
|
+
# x tick label 제거
|
|
104
|
+
ax.set_xticklabels([])
|
|
105
|
+
# y tick 우측으로 이동
|
|
106
|
+
ax.tick_params(left=False, right=True, labelleft=False, labelright=True, colors=self.color_tick_label)
|
|
107
|
+
# Axes 외곽선 색 변경
|
|
108
|
+
for i in ['top', 'bottom', 'left', 'right']: ax.spines[i].set_color(self.color_tick)
|
|
109
|
+
|
|
110
|
+
# 차트 영역 배경 색상
|
|
111
|
+
ax.set_facecolor(self.color_background)
|
|
112
|
+
|
|
113
|
+
# grid(구분선, 격자) 그리기
|
|
114
|
+
# 어째서인지 grid의 zorder 값을 선언해도 1.6을 값으로 한다.
|
|
115
|
+
ax.grid(**gridKwargs)
|
|
116
|
+
return
|
|
117
|
+
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
from ._draw import Chart as _OC
|
|
2
|
+
from ._cursor import Chart as _CC
|
|
3
|
+
from ._slider import Chart as _SC
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class OnlyChart(_OC):
|
|
8
|
+
r"""
|
|
9
|
+
You can see the guidance document:
|
|
10
|
+
Korean: https://white.seolpyo.com/entry/147/?from=package
|
|
11
|
+
English: https://github.com/white-seolpyo/seolpyo-mplchart/blob/main/README.md
|
|
12
|
+
|
|
13
|
+
Quick Start:
|
|
14
|
+
```
|
|
15
|
+
import seolpyo_mplchart as mc
|
|
16
|
+
chart = mc.SliderChart() # Create instance
|
|
17
|
+
chart.set_data(df) # set stock price data
|
|
18
|
+
mc.show() # show chart(run ```matplotlib.pyplot.show()```)
|
|
19
|
+
mc.close() # run ```matplotlib.pyplot.close('close')```
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Class Variables:
|
|
23
|
+
watermark: watermark text.
|
|
24
|
+
|
|
25
|
+
df: stock data DataFrame.
|
|
26
|
+
key_date: date column key. default 'date'
|
|
27
|
+
key_open, key_high, key_low, key_close: price column key. default ('open', 'high', 'low', 'close')
|
|
28
|
+
key_volume: volume column key. default 'volume'. If ```if config.VOLUME.EDGECOLOR.volume``` is ```False```, the volume chart is not drawn.
|
|
29
|
+
|
|
30
|
+
cnadle_on_ma: if True: draw candle above ma. else: draw candle below ma lines.
|
|
31
|
+
limit_candle: If (`the number of candles to draw < limit_candle or not limit_candle`): draw candles, else: draw wicks.
|
|
32
|
+
limit_wick: If (`the number of candles to draw < limit_wick or not limit_wick`): draw wicks, else: draw line.
|
|
33
|
+
limit_volume: If (`the number of candles to draw < limit_volume or not limit_volume`): draw volumebar, else: draw wicks.
|
|
34
|
+
limit_ma: If (`the number of candles to draw < limit_ma or not limit_ma`): draw ma lines, else: don't draw ma lines.
|
|
35
|
+
fraction: if True and number has a fractional part, display it as a fraction.
|
|
36
|
+
"""
|
|
37
|
+
key_date = 'date'
|
|
38
|
+
key_open, key_high, key_low, key_close = ('open', 'high', 'low', 'close')
|
|
39
|
+
key_volume = 'volume'
|
|
40
|
+
|
|
41
|
+
candle_on_ma = True
|
|
42
|
+
limit_candle = 400
|
|
43
|
+
limit_wick = 2_000
|
|
44
|
+
limit_volume = 200
|
|
45
|
+
limit_ma = None
|
|
46
|
+
watermark = 'seolpyo mplchart'
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
class CursorChart(_CC):
|
|
50
|
+
r"""
|
|
51
|
+
You can see the guidance document:
|
|
52
|
+
Korean: https://white.seolpyo.com/entry/147/?from=package
|
|
53
|
+
English: https://github.com/white-seolpyo/seolpyo-mplchart/blob/main/README.md
|
|
54
|
+
|
|
55
|
+
Quick Start:
|
|
56
|
+
```
|
|
57
|
+
import seolpyo_mplchart as mc
|
|
58
|
+
chart = mc.SliderChart() # Create instance
|
|
59
|
+
chart.set_data(df) # set stock price data
|
|
60
|
+
mc.show() # show chart(run ```matplotlib.pyplot.show()```)
|
|
61
|
+
mc.close() # run ```matplotlib.pyplot.close('close')```
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
Class Variables:
|
|
65
|
+
watermark: watermark
|
|
66
|
+
|
|
67
|
+
df: stock data DataFrame.
|
|
68
|
+
key_date: date column key. default 'date'
|
|
69
|
+
key_open, key_high, key_low, key_close: price column key. default ('open', 'high', 'low', 'close')
|
|
70
|
+
key_volume: volume column key. default 'volume'. If ```if config.VOLUME.EDGECOLOR.volume``` is ```False```, the volume chart is not drawn.
|
|
71
|
+
|
|
72
|
+
cnadle_on_ma: if True: draw candle above ma. else: draw candle below ma lines.
|
|
73
|
+
limit_candle: If (`the number of candles to draw < limit_candle or not limit_candle`): draw candles, else: draw wicks.
|
|
74
|
+
limit_wick: If (`the number of candles to draw < limit_wick or not limit_wick`): draw wicks, else: draw line.
|
|
75
|
+
limit_volume: If (`the number of candles to draw < limit_volume or not limit_volume`): draw volumebar, else: draw wicks.
|
|
76
|
+
limit_ma: If (`the number of candles to draw < limit_ma or not limit_ma`): draw ma lines, else: don't draw ma lines.
|
|
77
|
+
fraction: if True and number has a fractional part, display it as a fraction.
|
|
78
|
+
"""
|
|
79
|
+
key_date = 'date'
|
|
80
|
+
key_open, key_high, key_low, key_close = ('open', 'high', 'low', 'close')
|
|
81
|
+
key_volume = 'volume'
|
|
82
|
+
|
|
83
|
+
candle_on_ma = True
|
|
84
|
+
limit_candle = 400
|
|
85
|
+
limit_wick = 2_000
|
|
86
|
+
limit_volume = 200
|
|
87
|
+
limit_ma = None
|
|
88
|
+
watermark = 'seolpyo mplchart'
|
|
89
|
+
fraction = False
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
class SliderChart(_SC):
|
|
93
|
+
r"""
|
|
94
|
+
You can see the guidance document:
|
|
95
|
+
Korean: https://white.seolpyo.com/entry/147/?from=package
|
|
96
|
+
English: https://github.com/white-seolpyo/seolpyo-mplchart/blob/main/README.md
|
|
97
|
+
|
|
98
|
+
Quick Start:
|
|
99
|
+
```
|
|
100
|
+
import seolpyo_mplchart as mc
|
|
101
|
+
chart = mc.SliderChart() # Create instance
|
|
102
|
+
chart.set_data(df) # set stock price data
|
|
103
|
+
mc.show() # show chart(run ```matplotlib.pyplot.show()```)
|
|
104
|
+
mc.close() # run ```matplotlib.pyplot.close('close')```
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Class Variables:
|
|
108
|
+
watermark: watermark text.
|
|
109
|
+
|
|
110
|
+
df: stock data DataFrame.
|
|
111
|
+
key_date: date column key. default 'date'
|
|
112
|
+
key_open, key_high, key_low, key_close: price column key. default ('open', 'high', 'low', 'close')
|
|
113
|
+
key_volume: volume column key. default 'volume'. If ```if config.VOLUME.EDGECOLOR.volume``` is ```False```, the volume chart is not drawn.
|
|
114
|
+
|
|
115
|
+
cnadle_on_ma: if True: draw candle above ma. else: draw candle below ma lines.
|
|
116
|
+
limit_candle: If (`the number of candles to draw < limit_candle or not limit_candle`): draw candles, else: draw wicks.
|
|
117
|
+
limit_wick: If (`the number of candles to draw < limit_wick or not limit_wick`): draw wicks, else: draw line.
|
|
118
|
+
limit_volume: If (`the number of candles to draw < limit_volume or not limit_volume`): draw volumebar, else: draw wicks.
|
|
119
|
+
limit_ma: If (`the number of candles to draw < limit_ma or not limit_ma`): draw ma lines, else: don't draw ma lines.
|
|
120
|
+
fraction: if True and number has a fractional part, display it as a fraction.
|
|
121
|
+
slider_top: set slider position. if True: slider top. else: bottom
|
|
122
|
+
min_distance: the minimum number of candles displayed on the screen.
|
|
123
|
+
"""
|
|
124
|
+
key_date = 'date'
|
|
125
|
+
key_open, key_high, key_low, key_close = ('open', 'high', 'low', 'close')
|
|
126
|
+
key_volume = 'volume'
|
|
127
|
+
|
|
128
|
+
candle_on_ma = True
|
|
129
|
+
limit_candle = 400
|
|
130
|
+
limit_wick = 2_000
|
|
131
|
+
limit_volume = 200
|
|
132
|
+
limit_ma = 8_000
|
|
133
|
+
watermark = 'seolpyo mplchart'
|
|
134
|
+
fraction = False
|
|
135
|
+
slider_top = True
|
|
136
|
+
min_distance = 5
|
|
137
|
+
|