seolpyo-mplchart 0.1.3.1__tar.gz
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-0.1.3.1/MANIFEST.in +1 -0
- seolpyo_mplchart-0.1.3.1/PKG-INFO +49 -0
- seolpyo_mplchart-0.1.3.1/README.md +22 -0
- seolpyo_mplchart-0.1.3.1/pyproject.toml +54 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart/__init__.py +120 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart/base.py +111 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart/cursor.py +448 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart/data/apple.txt +64187 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart/data/samsung.txt +120002 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart/draw.py +371 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart/slider.py +550 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart/test.py +38 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart/utils.py +45 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart.egg-info/PKG-INFO +49 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart.egg-info/SOURCES.txt +17 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart.egg-info/dependency_links.txt +1 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart.egg-info/requires.txt +2 -0
- seolpyo_mplchart-0.1.3.1/seolpyo_mplchart.egg-info/top_level.txt +1 -0
- seolpyo_mplchart-0.1.3.1/setup.cfg +4 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
recursive-include seolpyo_mplchart/data *
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: seolpyo-mplchart
|
|
3
|
+
Version: 0.1.3.1
|
|
4
|
+
Summary: Fast candlestick chart using Python. Includes navigator, slider, navigation, and text information display functions
|
|
5
|
+
Author-email: white-seolpyo <white-seolpyo@naver.com>
|
|
6
|
+
License: MIT License
|
|
7
|
+
Project-URL: Homepage, https://white.seolpyo.com/
|
|
8
|
+
Project-URL: Documentation(English), https://white.seolpyo.com/entry/148/
|
|
9
|
+
Project-URL: Documentation(한글), https://white.seolpyo.com/entry/147/
|
|
10
|
+
Project-URL: repository, https://github.com/white-seolpyo/seolpyo-mplchart
|
|
11
|
+
Project-URL: Issues, https://github.com/white-seolpyo/seolpyo-mplchart/issues
|
|
12
|
+
Keywords: chart,차트,stock,주식,invest,투자,finance,파이낸스,candle,캔들,candlestick,캔들스틱,matplotlib,mplfinance,pyqtgraph,finplot,virtual currency,가상화폐,coin,코인,bitcoin,비트코인,ethereum,이더리움
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Classifier: Framework :: Matplotlib
|
|
16
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
17
|
+
Classifier: Intended Audience :: Developers
|
|
18
|
+
Classifier: Programming Language :: Python
|
|
19
|
+
Classifier: Programming Language :: Python :: 3
|
|
20
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
23
|
+
Requires-Python: >=3.11
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
Requires-Dist: matplotlib>=3.7.0
|
|
26
|
+
Requires-Dist: pandas>=2.0.0
|
|
27
|
+
|
|
28
|
+
# Donation
|
|
29
|
+
Bitcoin: 1MKCHW8smDZv5DFMiVkA5G3DeXcMn871ZX
|
|
30
|
+
|
|
31
|
+
Ethereum: 0x1c5fb8a5e0b1153cd4116c91736bd16fabf83520
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
# Document
|
|
35
|
+
[English](https://white.seolpyo.com/entry/148/)
|
|
36
|
+
|
|
37
|
+
[한글](https://white.seolpyo.com/entry/147/)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
# Sample
|
|
41
|
+

|
|
42
|
+
|
|
43
|
+
<img alt="tkinter sample gif" src="https://github.com/white-seolpyo/seolpyo-mplchart/blob/main/images/with%20tkinter.gif?raw=true">
|
|
44
|
+
|
|
45
|
+

|
|
46
|
+
|
|
47
|
+

|
|
48
|
+
|
|
49
|
+
<img alt="40,000 sample" src="https://github.com/white-seolpyo/seolpyo-mplchart/blob/main/images/40000.gif?raw=true">
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Donation
|
|
2
|
+
Bitcoin: 1MKCHW8smDZv5DFMiVkA5G3DeXcMn871ZX
|
|
3
|
+
|
|
4
|
+
Ethereum: 0x1c5fb8a5e0b1153cd4116c91736bd16fabf83520
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
# Document
|
|
8
|
+
[English](https://white.seolpyo.com/entry/148/)
|
|
9
|
+
|
|
10
|
+
[한글](https://white.seolpyo.com/entry/147/)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
# Sample
|
|
14
|
+

|
|
15
|
+
|
|
16
|
+
<img alt="tkinter sample gif" src="https://github.com/white-seolpyo/seolpyo-mplchart/blob/main/images/with%20tkinter.gif?raw=true">
|
|
17
|
+
|
|
18
|
+

|
|
19
|
+
|
|
20
|
+

|
|
21
|
+
|
|
22
|
+
<img alt="40,000 sample" src="https://github.com/white-seolpyo/seolpyo-mplchart/blob/main/images/40000.gif?raw=true">
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = [
|
|
3
|
+
"setuptools >= 65.0",
|
|
4
|
+
"matplotlib >= 3.7.0",
|
|
5
|
+
"pandas >= 2.0.0",
|
|
6
|
+
]
|
|
7
|
+
build-backend = "setuptools.build_meta"
|
|
8
|
+
|
|
9
|
+
[project]
|
|
10
|
+
name = "seolpyo-mplchart"
|
|
11
|
+
version = "0.1.3.1"
|
|
12
|
+
dependencies = [
|
|
13
|
+
"matplotlib >= 3.7.0",
|
|
14
|
+
"pandas >= 2.0.0",
|
|
15
|
+
]
|
|
16
|
+
license = {text = "MIT License"}
|
|
17
|
+
description = "Fast candlestick chart using Python. Includes navigator, slider, navigation, and text information display functions"
|
|
18
|
+
readme = "README.md"
|
|
19
|
+
requires-python = ">= 3.11"
|
|
20
|
+
authors = [
|
|
21
|
+
{name="white-seolpyo", email="white-seolpyo@naver.com"},
|
|
22
|
+
]
|
|
23
|
+
classifiers = [
|
|
24
|
+
"License :: OSI Approved :: MIT License",
|
|
25
|
+
"Development Status :: 5 - Production/Stable",
|
|
26
|
+
"Framework :: Matplotlib",
|
|
27
|
+
"Operating System :: Microsoft :: Windows",
|
|
28
|
+
"Intended Audience :: Developers",
|
|
29
|
+
"Programming Language :: Python",
|
|
30
|
+
"Programming Language :: Python :: 3",
|
|
31
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
32
|
+
"Programming Language :: Python :: 3.11",
|
|
33
|
+
"Programming Language :: Python :: 3.12",
|
|
34
|
+
]
|
|
35
|
+
keywords = [
|
|
36
|
+
"chart", "차트", "stock", "주식", "invest", "투자", "finance", "파이낸스",
|
|
37
|
+
"candle", "캔들", "candlestick", "캔들스틱", "matplotlib", "mplfinance",
|
|
38
|
+
"pyqtgraph", "finplot", "virtual currency", "가상화폐", "coin", "코인",
|
|
39
|
+
"bitcoin", "비트코인", "ethereum", "이더리움",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.urls]
|
|
43
|
+
Homepage = "https://white.seolpyo.com/"
|
|
44
|
+
"Documentation(English)" = "https://white.seolpyo.com/entry/148/"
|
|
45
|
+
"Documentation(한글)" = "https://white.seolpyo.com/entry/147/"
|
|
46
|
+
repository = "https://github.com/white-seolpyo/seolpyo-mplchart"
|
|
47
|
+
Issues = "https://github.com/white-seolpyo/seolpyo-mplchart/issues"
|
|
48
|
+
|
|
49
|
+
[tool.setuptools]
|
|
50
|
+
packages = [
|
|
51
|
+
"seolpyo_mplchart",
|
|
52
|
+
"seolpyo_mplchart.data",
|
|
53
|
+
]
|
|
54
|
+
|
|
@@ -0,0 +1,120 @@
|
|
|
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
|
+
import json
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Literal
|
|
11
|
+
|
|
12
|
+
import matplotlib.pyplot as plt
|
|
13
|
+
from matplotlib.figure import Figure
|
|
14
|
+
import pandas as pd
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
from .slider import Chart as CM
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
'pd',
|
|
22
|
+
'plt',
|
|
23
|
+
|
|
24
|
+
'Chart',
|
|
25
|
+
|
|
26
|
+
'sample',
|
|
27
|
+
'show',
|
|
28
|
+
'close',
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class Chart(CM):
|
|
33
|
+
r"""
|
|
34
|
+
You can see the guidance document:
|
|
35
|
+
Korean: https://white.seolpyo.com/entry/147/
|
|
36
|
+
English: https://white.seolpyo.com/entry/148/
|
|
37
|
+
|
|
38
|
+
Variables:
|
|
39
|
+
unit_price, unit_volume: unit for price and volume. default ('원', '주').
|
|
40
|
+
|
|
41
|
+
figsize: figure size if you use plt.show(). default (12, 6).
|
|
42
|
+
ratio_ax_slider, ratio_ax_legend, ratio_ax_price, ratio_ax_volume: Axes ratio. default (3, 2, 18, 5).
|
|
43
|
+
adjust: figure adjust. default dict(top=0.95, bottom=0.05, left=0.01, right=0.93, wspace=0, hspace=0).
|
|
44
|
+
slider_top: ax_slider is located at the top or bottom. default True.
|
|
45
|
+
color_background: color of background. default '#fafafa'.
|
|
46
|
+
color_grid: color of grid. default '#d0d0d0'.
|
|
47
|
+
|
|
48
|
+
df: stock data.
|
|
49
|
+
date: date column key. default 'date'
|
|
50
|
+
Open, high, low, close: price column key. default ('open', 'high', 'low', 'close')
|
|
51
|
+
volume: volume column key. default 'volume'
|
|
52
|
+
|
|
53
|
+
label_ma: moving average legend label format. default '{}일선'
|
|
54
|
+
list_ma: Decide how many days to draw the moving average line. default (5, 20, 60, 120, 240)
|
|
55
|
+
list_macolor: Color the moving average line. If the number of colors is greater than the moving average line, black is applied. default ('darkred', 'fuchsia', 'olive', 'orange', 'navy', 'darkmagenta', 'limegreen', 'darkcyan',)
|
|
56
|
+
|
|
57
|
+
candle_on_ma: Decide whether to draw candles on the moving average line. default True
|
|
58
|
+
color_sliderline: Color of closing price line in ax_slider. default 'k'
|
|
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:
|
|
91
|
+
data = json.load(txt)
|
|
92
|
+
data = data
|
|
93
|
+
df = pd.DataFrame(data)
|
|
94
|
+
|
|
95
|
+
c = Chart()
|
|
96
|
+
if name == 'apple':
|
|
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)
|
|
104
|
+
show()
|
|
105
|
+
close()
|
|
106
|
+
return
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def show():
|
|
110
|
+
return plt.show()
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
def close(fig: int|str|Figure|None='all'):
|
|
114
|
+
return plt.close(fig)
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
if __name__ == '__main__':
|
|
118
|
+
sample('apple')
|
|
119
|
+
|
|
120
|
+
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import matplotlib.pyplot as plt
|
|
2
|
+
import matplotlib.style as mplstyle
|
|
3
|
+
from matplotlib.axes import Axes
|
|
4
|
+
from matplotlib.backends.backend_agg import FigureCanvasAgg
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
from .utils import convert_unit
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
try: plt.switch_backend('TkAgg')
|
|
11
|
+
except: pass
|
|
12
|
+
|
|
13
|
+
# 한글 깨짐 문제 방지
|
|
14
|
+
try: plt.rcParams['font.family'] ='Malgun Gothic'
|
|
15
|
+
except: pass
|
|
16
|
+
|
|
17
|
+
mplstyle.use('fast')
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class Base:
|
|
21
|
+
canvas: FigureCanvasAgg
|
|
22
|
+
unit_price, unit_volume = ('원', '주')
|
|
23
|
+
|
|
24
|
+
figsize = (12, 6)
|
|
25
|
+
ratio_ax_slider, ratio_ax_legend, ratio_ax_price, ratio_ax_volume = (3, 2, 18, 5)
|
|
26
|
+
adjust = dict(
|
|
27
|
+
top=0.95, bottom=0.05, left=0.01, right=0.93, # 여백
|
|
28
|
+
wspace=0, hspace=0 # 플롯간 간격
|
|
29
|
+
)
|
|
30
|
+
color_grid = '#d0d0d0'
|
|
31
|
+
color_background = '#fafafa'
|
|
32
|
+
|
|
33
|
+
slider_top = True
|
|
34
|
+
title = 'seolpyo mplchart'
|
|
35
|
+
|
|
36
|
+
def __init__(self, *args, **kwargs):
|
|
37
|
+
# 기본 툴바 비활성화
|
|
38
|
+
plt.rcParams['toolbar'] = 'None'
|
|
39
|
+
|
|
40
|
+
self._set_plot()
|
|
41
|
+
return
|
|
42
|
+
|
|
43
|
+
def _set_plot(self):
|
|
44
|
+
if self.slider_top:
|
|
45
|
+
fig, ax = plt.subplots(
|
|
46
|
+
4, # row 수
|
|
47
|
+
figsize=self.figsize, # 기본 크기
|
|
48
|
+
height_ratios=(self.ratio_ax_slider, self.ratio_ax_legend, self.ratio_ax_price, self.ratio_ax_volume) # row 크기 비율
|
|
49
|
+
)
|
|
50
|
+
ax: list[Axes]
|
|
51
|
+
ax_slider, ax_legend, ax_price, ax_volume = ax
|
|
52
|
+
else:
|
|
53
|
+
fig, ax = plt.subplots(
|
|
54
|
+
5, # row 수
|
|
55
|
+
figsize=self.figsize, # 기본 크기
|
|
56
|
+
height_ratios=(self.ratio_ax_legend, self.ratio_ax_price, self.ratio_ax_volume, self.ratio_ax_legend, self.ratio_ax_slider) # row 크기 비율
|
|
57
|
+
)
|
|
58
|
+
ax: list[Axes]
|
|
59
|
+
ax_legend, ax_price, ax_volume, ax_none, ax_slider = ax
|
|
60
|
+
# 사용하지 않는 axes 숨기기
|
|
61
|
+
ax_none.axis('off')
|
|
62
|
+
ax_legend.axis('off')
|
|
63
|
+
|
|
64
|
+
ax_slider.xaxis.set_animated(True)
|
|
65
|
+
ax_slider.yaxis.set_animated(True)
|
|
66
|
+
|
|
67
|
+
ax_price.xaxis.set_animated(True)
|
|
68
|
+
ax_price.yaxis.set_animated(True)
|
|
69
|
+
|
|
70
|
+
ax_volume.xaxis.set_animated(True)
|
|
71
|
+
ax_volume.yaxis.set_animated(True)
|
|
72
|
+
|
|
73
|
+
fig.canvas.manager.set_window_title(f'{self.title}')
|
|
74
|
+
|
|
75
|
+
# 플롯간 간격 제거(Configure subplots)
|
|
76
|
+
fig.subplots_adjust(**self.adjust)
|
|
77
|
+
|
|
78
|
+
# y ticklabel foramt 설정
|
|
79
|
+
ax_slider.yaxis.set_major_formatter(lambda x, _: convert_unit(x, word=self.unit_price))
|
|
80
|
+
ax_price.yaxis.set_major_formatter(lambda x, _: convert_unit(x, word=self.unit_price))
|
|
81
|
+
ax_volume.yaxis.set_major_formatter(lambda x, _: convert_unit(x, word=self.unit_volume))
|
|
82
|
+
|
|
83
|
+
# 공통 설정
|
|
84
|
+
for a in [ax_slider, ax_price, ax_volume]:
|
|
85
|
+
# y tick 우측으로 이동
|
|
86
|
+
a.tick_params(left=False, right=True, labelleft=False, labelright=True)
|
|
87
|
+
# 차트 영역 배경 색상
|
|
88
|
+
a.set_facecolor(self.color_background)
|
|
89
|
+
# grid(구분선, 격자) 그리기
|
|
90
|
+
a.grid(True, color=self.color_grid, linewidth=1)
|
|
91
|
+
# x tick 제거
|
|
92
|
+
a.set_xticklabels([])
|
|
93
|
+
|
|
94
|
+
self.fig, self.canvas = (fig, fig.canvas)
|
|
95
|
+
self.ax_slider, self.ax_legend, self.ax_price, self.ax_volume = (ax_slider, ax_legend, ax_price, ax_volume)
|
|
96
|
+
|
|
97
|
+
return self.set_plot()
|
|
98
|
+
|
|
99
|
+
def set_plot(self):
|
|
100
|
+
"This function works after set plot process is done."
|
|
101
|
+
return
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
class Chart(Base):
|
|
105
|
+
pass
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
if __name__ == '__main__':
|
|
109
|
+
Base()
|
|
110
|
+
|
|
111
|
+
plt.show()
|