예제) mplfinance 사용 방법

작성자: [관리자] 하얀설표 2024.12.01 작성됨 | 2024.11.24 공개됨






(01.07) 수정됨.

mplfinance란?

matplotlib을 기반으로 하는 패키지로, 데이터 시각화를 위해 사용되는 패키지인 matplotlib을 주식 데이터(주가 차트) 전용으로 사용하기 위해 만들어진 패키지다.

mplfinance 깃헙: https://github.com/matplotlib/mplfinance

 

설치방법

pip install mplfinance 명령으로 설치가 가능하다.

pip install --upgrade mplfinance

 

설치하기 전에

mplfinance는 스크롤 기능이 없다. 만약 스크롤 기능이 필요하다면 내가 만든 mplchart 패키지를 사용해보는 것을 권한다.

https://white.seolpyo.com/entry/147/

 

사용 방법

기초적인 사용 방법은 다음과 같다.
mplfinance는 데이터 형식을 pandas로 사용하고 시가, 고가, 저가, 종가, 거래량 키값을 각각 Open, High, Low, End, Volume으로 지정해주어야 한다.

import mplfinance as mpf
import pandas as pd

list_price = {주가 데이터}

# 데이터 불러오기
# 데이터는 'Date', 'Open', 'High', 'Low', 'Close', 'Volume' 컬럼을 포함해야 함
a = []
for d in list_price:
    i = {}
    for k, key in [
        ('기준일', 'Date'),
        ('종가', 'Close'),
        ('시가', 'Open'),
        ('고가', 'High'),
        ('저가', 'Low'),
        ('거래량', 'Volume'),
    ]:
        i[key] = d[k]
    a.append(i)

df = pd.DataFrame(a)
df.index = pd.DatetimeIndex(df['Date']) # Date를 인덱스로 선언

marketcolor: dict[str, float|bool|dict[str, str]] = mpf.make_marketcolors(
    up='#fe3032', # 양봉 몸통 색
    down='#0095ff', # 음봉 몸통 색
    edge={'up': '#fe3032', 'down': '#0095ff'}, # 캔들 테두리 색
    wick={'up': '#fe3032', 'down': '#0095ff'}, # 양봉과 음봉의 윗꼬리, 아랫꼬리 색
    volume={'up': '#1f77b4', 'down': '#1f77b4'}, # 거래량 차트 색
    vcdopcod= False, # 양봉, 음봉에 따라 거래량 차트의 색상 변경 여부
)
style: dict[str, str|None|dict[str, float|bool|dict[str, str]]] = mpf.make_mpf_style(
    base_mpl_style='default', # 기초가 되는 base 스타일(패키지 내장)
    marketcolors=marketcolor, # 차트 색
    # mavcolors=None, # 가격이동평균선 색
    facecolor='#fafafa', # 배경색
    gridcolor='#d0d0d0', # 구분선 색
    gridstyle='-', # 그리드 스타일
    y_on_right=True, # y축 라벨 우측에 표시
    rc={
        'axes.labelcolor'   : '#101010',
        'axes.edgecolor'    : 'f0f0f0',
        'axes.grid.axis'    : 'y',
        'ytick.color'       : '#101010', # y축 색
        # 'ytick.labelcolor'  : '#101010', # y축 라벨 색
        'xtick.color'       : '#101010', # x축 색
        # 'xtick.labelcolor'  : '#101010', # x축 라벨 색
        'figure.titlesize'  : 'x-large',
        'figure.titleweight':'semibold',
    },
)

# 차트 그리기
mpf.plot(
    df,
    type='candle', # 차트 형식
    style=style, # 차트 스타일
    title='주가 차트', # 이름
    ylabel='가격[원]', # 주가 y축 라벨
    volume=True, # 거래량 표시
    ylabel_lower='거래량[주]', # 거래량 y축 라벨
    mav=(5, 10, 20, 60, 120), # 가격이동평균선
)

 

 

한글 깨짐 문제 해결방법

label을 한글로 설정하면 폰트가 깨진다.
한글이 지원되지 않는 폰트가 사용되기 때문인데, 다음과 같이 임의로 작성한 style variable에 한글을 지원하는 폰트를 선언하면 문제가 해결된다.

style variable 임의 설정 방법은 밑에서 확인하도록 하자.

# mplfinace 한글 깨짐 문제 해결 방법

style['rc']['font.family'] = 'Malgun Gothic'

 

제공되는 차트 형식

mplfinance는 총 3개의 차트 형식을 제공하며, candle, ohlc, line, renko, pnf, hollow_and_filled가 그것이다.
mpf.plot() 함수 사용시 type arg로 원하는 차트 형식을 선언해야 하며, 각각의 차트 형식을 호출하는 명령어는 _arg_validators.py의 def __get_valid_plot_types(plottype=None) 함수의 _valid_types variable에서 확인할 수 있다.

https://github.com/matplotlib/mplfinance/blob/master/src/mplfinance/_arg_validators.py#L111

 

차트 형식별 샘플(이미지)

candle

직역하면 양초 차트로, 우리나라에서 일반적으로 사용하는 차트 형식이다.
캔들 차트는 일본식 차트라고 부르기도 하는데, 이런 차트 형태가 고안된 곳이 일본이라고 하는 듯 하다.

 

hollow_and_filled

캔들 차트와 비슷한데, 차트를 그리는 방식에 약간 차이가 있는 것 같다.

관심이 있다면 mplfinance에서 제공하는 다음 도움말을 읽어보도록 하자.

https://github.com/matplotlib/mplfinance/blob/master/examples/hollow_and_filled_candles.ipynb

 

캔들 차트(좌)와 할로우 앤 필 차트(우)

 

ohlc

과거 미국에서 자주 사용되었 차트로 알고 있다. 캔들 차트보다 단순화된 차트다.

 

line

선형 차트로, 시가, 고가, 저가, 종가 중 1개의 값을 선으로 잇는 차트다.
우리나라의 경우 가격이동편균선에 사용된다.

 

renko

 

pnf

 

 

 

style

mplfinance는 사용자가 임의로 설정한 스타일을 적용할 수 있다.

 

내장 style

패키지에 내장되어있는 기본 스타일은 총 16개로, 각각의 명칭은 default, nightclouds, classic, mike, charles, blueskies, starsandstripes, sas, brasil, yahoo, checkers, binance, kenan, ibd, binancedark, tradingview이다.

기본 스타일에 관심이 있다면 다음 문서를 확인하도록 하자.

https://github.com/matplotlib/mplfinance/blob/master/examples/styles.ipynb

 

style 임의설정하기

방금 전 mpf.make_mpf_style() 함수를 통해 생성한 style variable을 print해보면 다음과 같이 dict object인 것을 확인할 수 있다.

# style variable

{
    'base_mpf_style': None,
    'base_mpl_style': 'default',
    'marketcolors': {
        'candle': {'up': '#fe3032', 'down': '#0095ff'},
        'edge': {'up': '#fe3032', 'down': '#0095ff'},
        'wick': {'up': '#fe3032', 'down': '#0095ff'},
        'ohlc': {'up': 'k', 'down': 'k'},
        'volume': {'up': '#1f77b4', 'down': '#1f77b4'},
        'vcedge': {'up': '#1f77b4', 'down': '#1f77b4'},
        'vcdopcod': False,
        'alpha': 0.9,
    },
    'mavcolors': None,
    'facecolor': '#fafafa',
    'edgecolor': None,
    'figcolor': None,
    'gridcolor': '#d0d0d0',
    'gridstyle': '-',
    'gridaxis': None,
    'y_on_right': True,
    'rc': {
        'axes.labelcolor': '#101010',
        'axes.edgecolor': 'f0f0f0',
        'axes.grid.axis': 'y',
        'ytick.color': '#101010',
        'xtick.color': '#101010',
        'figure.titlesize': 'x-large',
        'figure.titleweight': 'semibold',
        'font.family': 'Malgun Gothic',
    },
    'legacy_rc': None,
    'style_name': None,
}

 

여기서 차트의 색상을 결정하는 것은 "marketcolors"의 내용물인데, 앞서 mpf.make_marketcolors() 함수를 통해 생성한 variable이 이것이다.
style variable과 마찬가지로 dict object이며, print해보면 다음과 같은 내용을 확인할 수 있다.

# marketcolor variable

{
    # 캔들차트 스타일
    'candle': {
        'up': '#fe3032', # 양봉 몸통 색
        'down': '#0095ff', # 음봉 몸통 색
    },
    'edge': {
        'up': '#fe3032', # 양봉 테두리 색
        'down': '#0095ff', # 음봉 테두리 색
    },
    'wick': {
        'up': '#fe3032', # 양봉의 윗꼬리, 아랫꼬리 색
        'down': '#0095ff', # 음봉의 윗꼬리, 아랫꼬리 색
    },
    # ohlc 차트 스타일
    'ohlc': {
        'up': 'k', # 양봉 색
        'down': 'k', # 음봉 색
    },
    # 거래량 차트 스타일
    'volume': {
        'up': '#1f77b4', # 양봉의 거래량 차트 몸통 색
        'down': '#1f77b4', # 음봉의 거래량 차트 몸통 색
    },
    'vcedge': {
        'up': '#1f77b4', # 양봉의 거래량 차트 테두리 색
        'down': '#1f77b4', # 음봉의 거래량 차트 테두리 색
    },
    'vcdopcod': False, # 양봉/음봉에 따라 거래량 차트의 색상 적용 여부
    'alpha': 0.9, # 투명도 0.0 ~ 1.0
}

 

위 내용들을 참고하여 임의로 작성한 style variable을 mpf.plot() 함수에 style arg로 전달하면 임의 스타일을 적용할 수 있다.

 

일부 캔들의 색상 변경하는 방법

개인적으로 양봉이더라도 주가가 하락한 경우에는 몸통이 하얀색인 양봉을, 음봉이지만 주가가 상승한 경우에는 몸통이 하얀색인 음봉을 설정해서 사용하는 것을 좋아한다.
나와 같은 사람들을 위한 옵션이 존재하고, 안내 문서도 존재하지만.. 문서대로 따라하면 에러만 발생할 뿐, 실제 적용이 되지 않는다.
(dict style이 아닌 str 색상 지정은 정상 작동한다.)

 

문서 : https://github.com/matplotlib/mplfinance/blob/master/examples/marketcolor_overrides.ipynb

 

str이 아닌 dict 형식의 스타일 오브젝트 적용을 시도했다면 아마도 다음과 같은 에러를 맞이하게 될 것이다.

Traceback (most recent call last):
  File "c:\seolpyo\mplfinance\test.py", line 159, in <module>
    fig, ax = mpf.plot(
              ^^^^^^^^^
  File "C:\seolpyo\site-packages\mplfinance\plotting.py", line 412, in plot
    config = _process_kwargs(kwargs, _valid_plot_kwargs())
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\seolpyo\site-packages\mplfinance\_arg_validators.py", line 350, in _process_kwargs
    raise TypeError('kwarg "'+key+'" validator returned False for value: "'+str(value)+'"\n    '+v)
TypeError: kwarg "marketcolor_overrides" validator returned False for value: "[None, None, {style variable}, None, None]"
    def _mco_validator(value):        # marketcolor overrides validator
    if isinstance(value,dict):    # not yet supported, but maybe we will have other
        if 'colors' not in value: # kwargs related to mktcolor overrides (ex: `mco_faceonly`)
            raise ValueError('`marketcolor_overrides` as dict must contain `colors` key.')
        colors = value['colors']
    else:
        colors = value
    if not isinstance(colors,(list,tuple,np.ndarray)):
        return False
    return all([(c is None or
                 _mpf_is_color_like(c) or
                 _is_marketcolor_object(c) ) for c in colors])

 

이것을 해결하기 위해 상당히 많은 시간을 들여야 했는데, 문제는 깃헙에서 잘못된 방식을 가르쳐주고 있는 것이 원인이었다.
아마도 패키지 업데이트 과정에서 적용 방식이 변경된 것으로 인한 것으로 생각된다.

영어 문서에서는 이 해결방법을 찾을 수 없고, 중국어로 된 문서에서 문제 해결 방법을 찾을 수 있었다.

참고 링크 : https://blog.csdn.net/aobulaien001/article/details/135277426

 

다음과 같이 개별로 적용할 style variable(list)을 생성한 다음, 개별 스타일을 적용하지 않는 index에는 None을, 개별 스타일을 적용할 index에는 dict 형식으로 작성된 style variable을 넣어준다.
그리고 이렇게 생성한 mco variable을 marketcolor_overrides arg로 전달해주면 된다.

...

mco = [None] * len(df)
style_empty = {k: {'up': 'w', 'down': 'w'} if k in {'candle'} else v for k, v in marketcolor.items()}
# 색상 override
for n, (index, v) in enumerate(df.iterrows()):
    # 양봉 and 종가 < 전일종가
    if v['Open'] < v['Close'] and v['Close'] < pre: mco[n] = [style_empty]
    # 음봉 and 전일종가 < 종가
    if v['Close'] < v['Open'] and pre < v['Close']: mco[n] = [style_empty]
    pre = v['Close']

# 캔들스틱 차트 생성
mpf.plot(
    df,
    type='candle', # 차트 형식
    style=style, # 차트 스타일
    title='주가 차트', # 이름
    ylabel='가격[원]', # 주가 y축 라벨
    volume=True, # 거래량 표시
    ylabel_lower='거래량[주]', # 거래량 y축 라벨
    mav=(5, 10, 20, 60, 120), # 가격이동평균선
    marketcolor_overrides=mco, # 캔들 색상 덮어쓰기
)

 

marketcolor overrides 적용 전후 비교

언뜻 보기엔 차이가 없는 것 같으나, 적용 후 차트를 보면 전일 종가보가 당일 종가가 높기 때문에 비어있는 몸통으로 표현된 음봉이 존재하는 것을 찾아볼 수 있다.

marketcolor_overrides 옵션 설정 전후(좌: 설정 전, 우: 설정 후)





추천 (0)


글 목록

댓글을 달 수 없는 게시물입니다.