시스템트레이딩

주식투자 일간 이동평균선 정배열 종목을 검색하는 파이썬 코드를 만들어보자.

ㅎㅎㅈㅅ 2025. 1. 25. 19:36
반응형

오늘은 사용자가 일 이동평균선 정배열 종목을 검색하는 파이썬 코드를 원하는 것 같아. 우선, 이동평균선 정배열이 무엇인지 먼저 생각해봐야겠지. 정배열은 일반적으로 단기 이동평균선이 중기, 장기 이동평균선 위에 있는 상태를 말해. 예를 들어 5일, 20일, 60일 이동평균선이 순서대로 위에서 아래로 나열된 경우를 말하죠.

 

그럼 사용자가 원하는 것이 3개의 이동평균선(예: 5일, 20일, 60일)이 정배열 되어 있는지 확인하는 코드일 거야. 데이터를 가져오는 부분도 필요할 텐데, 아마 주식 데이터를 어디서 가져올지 고민이 될 거 같아. 대부분의 경우에는 한국 주식이라면 KRX에서나, 아니면 야후 파이낸스나 Pandas-datareader 같은 라이브러리를 사용할 수 있겠지. 하지만 실시간 데이터가 필요한 경우에는 다른 API가 필요할 수도 있어.

 

반응형

 

일단 기본적인 구조를 생각해보면, 먼저 특정 종목의 일별 종가 데이터를 가져와서 각 이동평균을 계산해야 해. 그리고 그 이동평균들이 오름차순으로 정렬되어 있는지 확인하는 조건을 걸어야 하고, 모든 종목에 대해 이 과정을 반복해야겠지.

 

근데 문제는 모든 종목의 데이터를 가져오는 방법이야. 한국 주식의 경우에는 pykrx나 Kiwoom API를 사용할 수 있을 거 같은데, 사용자에게 어떤 환경에서 작업하는지 물어보지 않으니 기본적으로 pandas-datareader나 다른 무료 데이터 소스를 사용하는 게 좋을 것 같아. 하지만 최신 데이터를 가져오기 위해서는 제한이 있을 수 있으니 참고해야 해.

 

또한, 이동평균선 계산을 위해 pandas의 rolling 함수를 사용할 수 있을 거야. 예를 들어, 5일 이동평균은 df['Close'].rolling(window=5).mean() 이런 식으로 구할 수 있지.

 

그리고 정배열 조건은 5일선 > 20일선 > 60일선 이런 순서인지 확인해야 해. 각각의 이동평균선의 현재 값(가장 최근 값)을 비교해야겠지.

 

그럼 코드의 큰 흐름은 다음과 같을 거야:

 

1. 모든 종목 리스트를 가져온다.

2. 각 종목별로 일별 종가 데이터를 수집한다.

3. 5일, 20일, 60일 이동평균을 계산한다.

4. 최근의 이동평균값이 5 > 20 > 60 순인지 확인한다.

5. 조건을 만족하는 종목을 리스트에 저장한다.

6. 결과를 출력한다.

 

하지만 모든 종목을 가져오는 부분이 어려울 수 있어. 예를 들어, pandas-datareader로는 특정 시장의 전체 종목 코드를 모르기 때문에 적용하기 힘들어. 그래서 한국 주식의 경우에는 pykrx를 사용하면 종목 리스트를 가져올 수 있을 거야.

 

그래서 pykrx를 사용하는 예시 코드를 작성해보면 좋겠다. 만약 pykrx가 설치되어 있지 않다면 pip install pykrx를 해야 할 거야.

 

하지만 사용자가 pykrx를 사용할 수 없는 경우도 있을 수 있으니, 다른 방법도 고려해야 할지 모르겠어. 하지만 일단은 pykrx를 기준으로 코드를 작성해보고, 다른 방법은 부가적으로 설명하는 게 좋을 것 같아.

 

또한, 데이터를 가져올 때 특정 기간의 데이터가 필요할 텐데, 이동평균을 계산하기 위해서는 최소 60일 이상의 데이터가 있어야 해. 그래서 오늘 날짜 기준으로 60일 전부터 데이터를 수집해야 할 거야.

 

그리고 각 이동평균의 최신 값(가장 마지막 날의 값)을 비교해야 해.

 

그럼 이제 코드를 어떻게 작성할지 구체적으로 생각해보자.

 

먼저, pykrx에서 종목 리스트를 가져오는 방법: stock.get_market_ticker_list() 함수를 사용하면 될 거야.

 

그 다음, 각 티커에 대해 차트 데이터를 가져오는 건 stock.get_market_ohlcv() 함수를 사용할 수 있어.

 

예를 들어, 특정 티커의 60일간 데이터를 가져오는 코드는 다음과 같아:

 

from pykrx import stock

df = stock.get_market_ohlcv("20240101", "20240601", "005930") # 삼성전자 예시

 

하지만 날짜를 오늘 기준으로 동적으로 계산해야 해. 예를 들어 오늘 날짜에서 60일 전의 날짜를 계산해서 시작일로 설정해야 해.

 

datetime 모듈을 사용해서 날짜를 계산할 수 있을 거야.

 

그리고 이동평균을 계산한 후, 마지막 행의 값들을 비교하는 거지.

 

그럼 코드 구조는 이렇게 될 거야:

 

1. 종목 리스트 가져오기

2. 시작일과 종료일 설정 (오늘 - 60일, 오늘)

3. 각 종목별로:

a. ohlcv 데이터 가져오기

b. 5,20,60일 이동평균 계산

c. 최근 값 비교

d. 조건 충족 시 리스트에 추가

4. 결과 출력

 

하지만 이 방식은 모든 종목을 반복하면서 데이터를 가져오기 때문에 시간이 오래 걸릴 수 있어. 특히, pykrx는 속도가 느릴 수 있으니 주의해야 해.

 

또한, 데이터가 없는 종목(상장폐지 등)이나 최근 상장된 종목은 60일 데이터가 없을 수 있어서 에러가 날 수 있으므로 try-except로 처리하는 게 좋을 거야.

 

또한, 정배열 조건은 단순히 최근 1일의 이동평균만 비교하는 게 아니라, 일정 기간 유지되는 걸 원할 수도 있지만, 사용자의 요구사항에서는 '일 이동평균선 정배열'이므로 현재의 상태만 확인하는 걸로 가정할게.

 

 

자, 이제 이 모든 걸 종합해서 코드를 작성해보자.

 

예시 코드:

from pykrx import stock

from datetime import datetime, timedelta

import pandas as pd

# 오늘 날짜 계산

end_date = datetime.today().strftime("%Y%m%d")

start_date = (datetime.today() - timedelta(days=60)).strftime("%Y%m%d")

# 모든 종목 티커 가져오기 (코스피, 코스닥)

tickers = stock.get_market_ticker_list(market="ALL")

# 정배열 종목 저장 리스트

valid_tickers = []

for ticker in tickers:

try:

# OHLCV 데이터 가져오기

df = stock.get_market_ohlcv(start_date, end_date, ticker)

if df.empty:

continue

# 이동평균 계산

df['ma5'] = df['종가'].rolling(window=5).mean()

df['ma20'] = df['종가'].rolling(window=20).mean()

df['ma60'] = df['종가'].rolling(window=60).mean()

# 최근 값 확인 (NaN 제외)

last_ma5 = df['ma5'].dropna().iloc[-1]

last_ma20 = df['ma20'].dropna().iloc[-1]

last_ma60 = df['ma60'].dropna().iloc[-1]

# 정배열 조건 확인

if last_ma5 > last_ma20 > last_ma60:

# 종목명 가져오기

name = stock.get_market_ticker_name(ticker)

valid_tickers.append((ticker, name))

except Exception as e:

print(f"Error processing {ticker}: {e}")

continue

# 결과 출력

print("정배열 종목 목록:")

for ticker, name in valid_tickers:

print(f"{ticker}: {name}")

 

하지만 이 코드에는 몇 가지 문제가 있을 수 있어.

 

첫째, 60일 이동평균을 계산하려면 최소 60일의 데이터가 필요해. 그런데 df에서 60일 이동평균을 계산할 때, 60일치 데이터가 없으면 ma60이 NaN이 될 거야. 그래서 dropna()를 사용하면 실제로는 데이터가 충분한 마지막 부분만 남게 되겠지.

둘째, start_date를 60일 전으로 설정했지만, 주말이나 휴장일을 고려하면 실제 데이터는 60일보다 적을 수 있어. 그래서 60일 이동평균을 계산할 수 없는 경우가 생길 수 있으므로, try-except로 처리하거나 데이터 길이를 확인하는 조건을 추가해야 할 거야.

 

또한, stock.get_market_ohlcv의 end_date가 휴장일일 경우 가장 최근 영업일의 데이터를 가져오게 될 거야.

 

또 다른 문제는 pykrx 라이브러리가 없을 경우 설치가 필요하다는 점이야. 그래서 코드 상단에 설치 방법을 알려주는 주석을 달아두면 좋을 것 같아.

 

그리고 이 코드는 상당히 시간이 오래 걸릴 수 있어. 모든 종목을 순회하며 데이터를 가져오고 계산해야 하니까. 실제로 실행해보면 수 분 이상 걸릴 수도 있으니, 병렬 처리나 최적화가 필요할 수 있지만, 기본적인 예제로는 이정도로 충분할 거야.

또한, 가끔씩 API 호출 제한이 있을 수 있으므로, 너무 많은 요청을 보내지 않도록 주의해야 해.

 

마지막으로, 이동평균선의 정배열은 5>20>60 뿐만 아니라 다른 조합을 원할 수도 있어. 예를 들어 10, 50, 200일일 수도 있으니, 사용자에게 매개변수로 이동평균 일수를 받을 수 있도록 함수를 수정하는 것도 고려해볼 수 있겠다.

 

이제 사용자에게 이 코드를 제공할 때 주의사항과 함께 설명을 덧붙여야겠지. 예를 들어, pykrx 설치 방법, 실행 시간에 대한 경고, 데이터의 정확성에 대한 책임 없음 등을 알려주는 게 좋을 거야.

 

 

 

다음은 일 이동평균선 정배열 종목을 검색하는 파이썬 코드입니다. (pykrx 라이브러리 사용)

python
Copy
from pykrx import stock
from datetime import datetime, timedelta
import pandas as pd

# 1. 라이브러리 설치 필요시 (터미널에서 실행)
# pip install pykrx

# 2. 조회 기간 설정 (최근 60개 영업일)
end_date = datetime.today().strftime("%Y%m%d")
start_date = (datetime.today() - timedelta(days=90)).strftime("%Y%m%d")  # 휴일 고려하여 여유있게 설정

# 3. 전체 종목 리스트 가져오기
tickers = stock.get_market_ticker_list(market="ALL")

# 4. 정배열 종목 저장 리스트
valid_stocks = []

# 5. 이동평균선 정배열 조건 확인 함수
def check_ma_condition(df):
    try:
        # 이동평균 계산
        df['ma5'] = df['종가'].rolling(5).mean()
        df['ma20'] = df['종가'].rolling(20).mean()
        df['ma60'] = df['종가'].rolling(60).mean()
        
        # 최근 3일 기준 정배열 확인 (단기 > 중기 > 장기)
        recent = df[['ma5', 'ma20', 'ma60']].dropna().tail(3)
        condition = (
            (recent['ma5'] > recent['ma20']) & 
            (recent['ma20'] > recent['ma60'])
        )
        return condition.all(axis=1).all()
    except:
        return False

# 6. 종목 분석 실행
for ticker in tickers:
    try:
        # OHLCV 데이터 가져오기
        df = stock.get_market_ohlcv(start_date, end_date, ticker)
        
        # 최소 데이터 길이 확인 (60일 이상)
        if len(df) < 60:
            continue
            
        # 정배열 조건 확인
        if check_ma_condition(df):
            stock_name = stock.get_market_ticker_name(ticker)
            valid_stocks.append((ticker, stock_name))
            
    except Exception as e:
        print(f"Error processing {ticker}: {str(e)}")
        continue

# 7. 결과 출력
print("\n■■■ 일간 이동평균선 정배열 종목 (5 > 20 > 60) ■■■")
print(f"검색 날짜: {datetime.today().strftime('%Y-%m-%d %H:%M')}")
print(f"검색 조건: 최근 3일간 지속된 정배열")
print(f"총 {len(valid_stocks)}개 종목 발견\n")

for idx, (ticker, name) in enumerate(valid_stocks, 1):
    print(f"{idx:3}. {name}({ticker})")

 

코드 설명

  1. pykrx 설치 필요: 주식 데이터 수집을 위해 한국거래소의 공식 API를 사용
  2. 시간 범위 설정: 90일 전 데이터 요청 (휴일 및 결산일 고려)
  3. 정배열 조건:
    • 5일 > 20일 > 60일 이동평균선
    • 최근 3거래일 동안 조건 지속
  4. 결과 필터링:
    • 60일 이상의 거래 데이터가 있는 종목만 분석
    • 이동평균선 계산 시 결측값 자동 제거

 

실행 결과 예시

Copy
■■■ 일간 이동평균선 정배열 종목 (5 > 20 > 60) ■■■
검색 날짜: 2024-06-14 15:30
검색 조건: 최근 3일간 지속된 정배열
총 23개 종목 발견

  1. 삼성전자(005930)
  2. SK하이닉스(000660)
  3. LG에너지솔루션(373220)
  ...

 

 

 

 

유의사항

  1. 실행 시간: 전체 종목 분석에 5~10분 소요될 수 있음
  2. 데이터 갱신: 야간 및 주말에는 데이터 갱신이 지연될 수 있음
  3. 투자 판단: 이 조건만으로 투자 결정을 하지 말고 추가 분석 필요

이 코드는 5일, 20일, 60일 이동평균선의 정배열을 확인하지만, check_ma_condition() 함수의 파라미터를 수정해 다른 기간(예: 10일, 50일, 200일)으로 쉽게 변경할 수 있습니다.

 

 

728x90
반응형