seolpyo-mplchart 2.0.0.3__py3-none-any.whl → 2.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.
Files changed (54) hide show
  1. seolpyo_mplchart/__init__.py +17 -133
  2. seolpyo_mplchart/_chart/__init__.py +39 -31
  3. seolpyo_mplchart/_chart/base/__init__.py +111 -0
  4. seolpyo_mplchart/_chart/base/a_canvas.py +250 -0
  5. seolpyo_mplchart/_chart/base/b_artist.py +143 -0
  6. seolpyo_mplchart/_chart/base/c_draw.py +100 -0
  7. seolpyo_mplchart/_chart/base/d_segment.py +262 -0
  8. seolpyo_mplchart/_chart/base/e_axis.py +267 -0
  9. seolpyo_mplchart/_chart/base/f_background.py +62 -0
  10. seolpyo_mplchart/_chart/base/g_event.py +66 -0
  11. seolpyo_mplchart/_chart/base/h_data.py +138 -0
  12. seolpyo_mplchart/_chart/base/test.py +58 -0
  13. seolpyo_mplchart/_chart/cursor/__init__.py +125 -0
  14. seolpyo_mplchart/_chart/cursor/b_artist.py +130 -0
  15. seolpyo_mplchart/_chart/cursor/c_draw.py +96 -0
  16. seolpyo_mplchart/_chart/cursor/d_segment.py +359 -0
  17. seolpyo_mplchart/_chart/cursor/e_axis.py +65 -0
  18. seolpyo_mplchart/_chart/cursor/g_event.py +233 -0
  19. seolpyo_mplchart/_chart/cursor/h_data.py +61 -0
  20. seolpyo_mplchart/_chart/cursor/test.py +69 -0
  21. seolpyo_mplchart/_chart/slider/__init__.py +169 -0
  22. seolpyo_mplchart/_chart/slider/a_canvas.py +260 -0
  23. seolpyo_mplchart/_chart/slider/b_artist.py +91 -0
  24. seolpyo_mplchart/_chart/slider/c_draw.py +54 -0
  25. seolpyo_mplchart/_chart/slider/d_segment.py +166 -0
  26. seolpyo_mplchart/_chart/slider/e_axis.py +70 -0
  27. seolpyo_mplchart/_chart/slider/f_background.py +37 -0
  28. seolpyo_mplchart/_chart/slider/g_event.py +353 -0
  29. seolpyo_mplchart/_chart/slider/h_data.py +102 -0
  30. seolpyo_mplchart/_chart/slider/test.py +71 -0
  31. seolpyo_mplchart/_config/candle.py +1 -0
  32. seolpyo_mplchart/_config/figure.py +3 -4
  33. seolpyo_mplchart/_config/ma.py +2 -0
  34. seolpyo_mplchart/_config/slider/config.py +2 -2
  35. seolpyo_mplchart/_config/slider/figure.py +3 -4
  36. seolpyo_mplchart/_config/slider/nav.py +3 -2
  37. seolpyo_mplchart/_config/volume.py +1 -0
  38. seolpyo_mplchart/_utils/__init__.py +10 -0
  39. seolpyo_mplchart/_utils/nums.py +67 -0
  40. seolpyo_mplchart/_utils/theme/__init__.py +15 -0
  41. seolpyo_mplchart/_utils/theme/dark.py +57 -0
  42. seolpyo_mplchart/_utils/theme/light.py +56 -0
  43. seolpyo_mplchart/_utils/utils.py +28 -0
  44. seolpyo_mplchart/_utils/xl/__init__.py +15 -0
  45. seolpyo_mplchart/_utils/xl/csv.py +46 -0
  46. seolpyo_mplchart/_utils/xl/xlsx.py +49 -0
  47. seolpyo_mplchart/sample/apple.txt +6058 -0
  48. seolpyo_mplchart/sample/samsung.txt +5938 -0
  49. seolpyo_mplchart/test.py +5 -5
  50. {seolpyo_mplchart-2.0.0.3.dist-info → seolpyo_mplchart-2.1.0.dist-info}/METADATA +21 -13
  51. seolpyo_mplchart-2.1.0.dist-info/RECORD +89 -0
  52. seolpyo_mplchart-2.0.0.3.dist-info/RECORD +0 -50
  53. {seolpyo_mplchart-2.0.0.3.dist-info → seolpyo_mplchart-2.1.0.dist-info}/WHEEL +0 -0
  54. {seolpyo_mplchart-2.0.0.3.dist-info → seolpyo_mplchart-2.1.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,15 @@
1
+ from typing import Literal
2
+
3
+ from ..._config import ConfigData, SliderConfigData
4
+
5
+ from . import light, dark
6
+
7
+
8
+ def set_theme(config: ConfigData|SliderConfigData, theme: Literal['light', 'dark']='dark'):
9
+ if theme == 'light':
10
+ config = light.set_theme(config)
11
+ elif theme == 'dark':
12
+ config = dark.set_theme(config)
13
+
14
+ return config
15
+
@@ -0,0 +1,57 @@
1
+ from ..._config import ConfigData, SliderConfigData
2
+
3
+
4
+ def set_theme(config: ConfigData|SliderConfigData):
5
+ # axes
6
+ config.FIGURE.facecolor = '#0f0f0f'
7
+ config.AX.facecolor = '#0f0f0f'
8
+ config.AX.TICK.edgecolor = '#dbdbdb'
9
+ config.AX.TICK.fontcolor = '#dbdbdb'
10
+ config.AX.GRID.color = '#1c1c1c'
11
+
12
+ # candle
13
+ config.CANDLE.line_color = 'w'
14
+ config.CANDLE.FACECOLOR.bull_rise = '#089981'
15
+ config.CANDLE.FACECOLOR.bull_fall = '#0f0f0f'
16
+ config.CANDLE.FACECOLOR.bear_fall = '#f23645'
17
+ config.CANDLE.FACECOLOR.bear_rise = '#0f0f0f'
18
+
19
+ config.CANDLE.EDGECOLOR.bull_rise = '#089981'
20
+ config.CANDLE.EDGECOLOR.bull_fall = '#089981'
21
+ config.CANDLE.EDGECOLOR.bear_fall = '#f23645'
22
+ config.CANDLE.EDGECOLOR.bear_rise = '#f23645'
23
+ config.CANDLE.EDGECOLOR.doji = 'w'
24
+
25
+ # volume
26
+ config.VOLUME.FACECOLOR.rise = '#2A8076'
27
+ config.VOLUME.FACECOLOR.fall = '#BE4F58'
28
+ config.VOLUME.FACECOLOR.doji = '#82828A'
29
+
30
+ config.VOLUME.EDGECOLOR.rise = '#2A8076'
31
+ config.VOLUME.EDGECOLOR.fall = '#BE4F58'
32
+ config.VOLUME.EDGECOLOR.doji = '#82828A'
33
+
34
+ # ma
35
+ config.MA.color_default = 'w'
36
+ config.MA.color_list = ['#FFB300', '#03A9F4', '#AB47BC', '#8BC34A', '#EF5350']
37
+
38
+ # text
39
+ config.CURSOR.TEXT.BBOX.facecolor = '#3d3d3d'
40
+ config.CURSOR.TEXT.BBOX.edgecolor = '#ffffff'
41
+ config.CURSOR.TEXT.color = '#ffffff'
42
+
43
+ # box
44
+ config.CURSOR.BOX.edgecolor = 'w'
45
+
46
+ # line
47
+ config.CURSOR.CROSSLINE.edgecolor = '#9c9c9c'
48
+
49
+ # wartermark
50
+ config.FIGURE.WATERMARK.color = 'w'
51
+
52
+ if getattr(config, 'SLIDER', None):
53
+ config.SLIDER.NAV.edgecolor = "#00A6FF"
54
+ config.SLIDER.NAV.facecolor = '#FFFFFF4D'
55
+
56
+ return config
57
+
@@ -0,0 +1,56 @@
1
+ from ..._config import ConfigData, SliderConfigData
2
+
3
+
4
+ def set_theme(config: ConfigData|SliderConfigData):
5
+ # axes
6
+ config.FIGURE.facecolor = '#fafafa'
7
+ config.AX.facecolor = '#fafafa'
8
+ config.AX.TICK.edgecolor = 'k'
9
+ config.AX.TICK.fontcolor = 'k'
10
+ config.AX.GRID.color = '#d0d0d0'
11
+
12
+ # candle
13
+ config.CANDLE.line_color = 'k'
14
+ config.CANDLE.FACECOLOR.bull_rise = '#FF2400'
15
+ config.CANDLE.FACECOLOR.bull_fall = 'w'
16
+ config.CANDLE.FACECOLOR.bear_fall = '#1E90FF'
17
+ config.CANDLE.FACECOLOR.bear_rise = 'w'
18
+
19
+ config.CANDLE.EDGECOLOR.bull_rise = '#FF2400'
20
+ config.CANDLE.EDGECOLOR.bull_fall = '#FF2400'
21
+ config.CANDLE.EDGECOLOR.bear_fall = '#1E90FF'
22
+ config.CANDLE.EDGECOLOR.bear_rise = '#1E90FF'
23
+ config.CANDLE.EDGECOLOR.doji = 'k'
24
+
25
+ # volume
26
+ config.VOLUME.FACECOLOR.rise = '#F27663'
27
+ config.VOLUME.FACECOLOR.fall = '#70B5F2'
28
+ config.VOLUME.FACECOLOR.doji = '#BEBEBE'
29
+
30
+ config.VOLUME.EDGECOLOR.rise = '#F27663'
31
+ config.VOLUME.EDGECOLOR.fall = '#70B5F2'
32
+ config.VOLUME.EDGECOLOR.doji = '#BEBEBE'
33
+
34
+ # ma
35
+ config.MA.color_default = 'k'
36
+ config.MA.color_list = ['#8B00FF', '#008000', '#A0522D', '#008B8B', '#FF0080']
37
+ # text
38
+ config.CURSOR.TEXT.BBOX.facecolor = 'w'
39
+ config.CURSOR.TEXT.BBOX.edgecolor = 'k'
40
+ config.CURSOR.TEXT.color = 'k'
41
+
42
+ # box
43
+ config.CURSOR.BOX.edgecolor = 'k'
44
+
45
+ # line
46
+ config.CURSOR.CROSSLINE.edgecolor = 'k'
47
+
48
+ # wartermark
49
+ config.FIGURE.WATERMARK.color = 'k'
50
+
51
+ if getattr(config, 'SLIDER', None):
52
+ config.SLIDER.NAV.edgecolor = '#2962FF'
53
+ config.SLIDER.NAV.facecolor = '#0000002E'
54
+
55
+ return config
56
+
@@ -0,0 +1,28 @@
1
+ import matplotlib.pyplot as plt
2
+ import pandas as pd
3
+
4
+
5
+ def switch_backend(newbackend='TkAgg'):
6
+ "call matplotlib.pyplot.switch_backend(newbackend)"
7
+ return plt.switch_backend(newbackend)
8
+
9
+
10
+ def close(fig='all'):
11
+ "call matplotlib.pyplot.close(fig)"
12
+ return plt.close(fig)
13
+
14
+ def show(Close=True):
15
+ """
16
+ call matplotlib.pyplot.show()
17
+ ```if Close``` if True, run matplotlib.pyplot.close('all') after window closee.
18
+ """
19
+ plt.show()
20
+ if Close:
21
+ close()
22
+ return
23
+
24
+
25
+ def list_to_DataFrame(item_list):
26
+ "return pd.DataFrame(item_list)"
27
+ return pd.DataFrame(item_list)
28
+
@@ -0,0 +1,15 @@
1
+ from . import xlsx, csv
2
+
3
+
4
+ def xl_to_dataList(path_file):
5
+ pf = str(path_file)
6
+ if pf.endswith('.xlsx'):
7
+ data = xlsx.convert(path_file)
8
+ elif pf.endswith('.csv'):
9
+ data = csv.convert(path_file)
10
+ else:
11
+ msg = '다음 형식의 파일의 데이터만 변환할 수 있습니다.'
12
+ msg += f' [.xlsx, .csv]'
13
+ raise ValueError(msg)
14
+ return data
15
+
@@ -0,0 +1,46 @@
1
+ from datetime import datetime
2
+ import json
3
+
4
+
5
+ base_date = datetime(1899, 12, 30).date()
6
+
7
+
8
+ def convert(path_file: str, row=1, index_date=0, index_open=1, index_high=2, index_low=3, index_close=4, index_volume=5):
9
+ "csv 파일에서 주가 정보를 추출합니다."
10
+ item_list: list[dict[str, str|float]] = []
11
+
12
+ with open(path_file, 'r', encoding='utf-8') as txt:
13
+ j = json.load(txt)
14
+
15
+ if len(j[1]) < 6:
16
+ index_volume = None
17
+ for i in j[row:]:
18
+ if index_volume:
19
+ dt = i[index_date]
20
+ o = i[index_open]
21
+ h = i[index_high]
22
+ l = i[index_low]
23
+ c = i[index_close]
24
+ v = None
25
+ else:
26
+ dt = i[index_date]
27
+ o = i[index_open]
28
+ h = i[index_high]
29
+ l = i[index_low]
30
+ c = i[index_close]
31
+ v = i[index_volume]
32
+
33
+ o = float(o)
34
+ h = float(h)
35
+ l = float(l)
36
+ c = float(c)
37
+ if v:
38
+ v = float(v)
39
+ item = {'기준일': dt, '시가': o, '고가': h, '저가': l, '종가': c, '거래량': v}
40
+ else:
41
+ item = {'기준일': dt, '시가': o, '고가': h, '저가': l, '종가': c}
42
+
43
+ item_list.append(item)
44
+
45
+ return sorted(item_list, key=lambda x: x['기준일'])
46
+
@@ -0,0 +1,49 @@
1
+ from datetime import datetime, timedelta
2
+ from re import findall
3
+ from zipfile import ZipFile
4
+
5
+
6
+ base_date = datetime(1899, 12, 30).date()
7
+
8
+
9
+ def convert(path_file: str, sheet=1, row=4, date='A', Open='B', high='C', low='D', close='E', volume='F'):
10
+ "xlsx 파일에서 주가 정보를 추출합니다."
11
+ list_price: list[dict[str, str|float]] = []
12
+
13
+ zipfile = ZipFile(path_file)
14
+ # print(f'{zipfile.filelist=}')
15
+ a = zipfile.read(f'xl/worksheets/sheet{sheet}.xml')
16
+ # print(f'{a=}')
17
+ # print(f'{type(a)=}')
18
+ b = a.decode('utf-8')
19
+ for i in findall('<row.+?</row>', b)[row:]:
20
+ # print()
21
+ # print(f'{i=}')
22
+ dt = findall(f'<c r="{date}[0-9].+?<v>([0-9]+)</v>', i)
23
+ c = findall(f'<c r="{close}[0-9].+?<v>([0-9\.]+)</v>', i)
24
+ o = findall(f'<c r="{Open}[0-9].+?<v>([0-9\.]+)</v>', i)
25
+ h = findall(f'<c r="{high}[0-9].+?<v>([0-9\.]+)</v>', i)
26
+ l = findall(f'<c r="{low}[0-9].+?<v>([0-9\.]+)</v>', i)
27
+ v = findall(f'<c r="{volume}[0-9].+?<v>([0-9]+)</v>', i)
28
+ # print(f'{(dt, c, o, h, l, v)=}')
29
+ if not all([dt, o, h, l, c,]):
30
+ continue
31
+ try:
32
+ dt = base_date + timedelta(int(dt[0]))
33
+ c = float(c[0])
34
+ o = float(o[0])
35
+ h = float(h[0])
36
+ l = float(l[0])
37
+ except:
38
+ continue
39
+ try:
40
+ v = float(v[0])
41
+ except:
42
+ v = 0
43
+ # print(f'{(dt, c, o, h, l, v)=}')
44
+ # if 2020 < dt.year and dt.year < 2024: list_price.append({'기준일': f'{dt}', '종가': c, '시가': o, '고가': h, '저가': l, '거래량': v,})
45
+ list_price.append({'기준일': str(dt), '종가': c, '시가': o, '고가': h, '저가': l, '거래량': v,})
46
+ # for i in enumerate(list_price, 1): print(f' {i}')
47
+
48
+ return sorted(list_price, key=lambda x: x['기준일'])
49
+