미국 공학박사 아빠의 코딩 연구소

주식 분석의 기본인 이동 평균선 만들기

이번 강의에서는 Function(함수)라는 새로운 Python의 코딩 기법에 대해서 알아볼거랍니다.
조금 더 실감나는 Function의 공부를 위해서 이동 평균이라는 예를 이용해서 코딩해 보도록 하지요. 이동 평균에 대한 공학적/경제적인 소양 하나 쌓기는 덤이구요.


강의들은 모두 무료입니다. 단, 저작권은 키클 코딩랩 에 있으며, 무단 복제 및 배포를 엄금합니다.
이를 어길 시, 본 사이트의 서버가 미국에 있으므로, 미국법에 의해 처벌될 수도 있습니다.




평균 함수 만들기

혹시, 경제 뉴스나 주식 분석해 주는 방송을 보면서 이동 평균(Moving Average)라는 용어를 들어보셨나요?
이번 강의에서는 이동 평균을 Function이라는 새로운 방법으로 코딩을 해볼거랍니다.
참고로, 이동 평균은 공학적으로는 신호 처리(Signal Processing) 분야에서 기초적으로 사용되는 여과(Filtering)기법 중 하나예요. 자세한 내용은 강의 말미에 설명할게요.

자, 원하는 폴더에 새로운 Python파일을 만들고, "lec8_moving_avg.py"라고 파일 이름을 지어 보지요.
언제나처럼, 먼저 어떤 라이브러리들부터 사용할지 선언해야 겠죠? 아래 줄1~2와 같이 Matplotlib의 pyplot객체와 Numpy를 각각 plt와 np라는 별명으로 import해 보지요.

그리고, 곧장 함수(Function)에 대한 설명으로 들어가 볼까요?
사실 우리는 함수를 사용해 오고 있었지요? Numpy의 array()나 출력하기 위한 print() 등도 모두 전달인자를 받아서 일정한 임무를 수행한 함수들이랍니다.
그렇다면, 이런 함수들을 어떻게 정의하고 코딩하는지 알아볼까요?

[문법] Function

함수를 어떻게 작성하는지 감이 잡혔나요? 그럼, 리스트(List)로 전달된 여러 수들의 평균을 구하는 함수를 작성해 볼까요?
아래 줄4~줄11에서 ip_list라는 이름의 리스트를 전달받아, 그 안에 있는 수들의 평균(Average)을 구하는 calcAvg라는 함수의 코드를 작성했어요.

줄4에서는 함수의 이름과 전달인자의 이름을 정의하였지요.
줄5에서는 len()함수를 이용하여 ip_list에 얼마나 많은 값들이 포함되어 있는지 알아내어 변수 n에 저장하였답니다. 함수 len()에 대해서 잠깐 알아볼까요?

[문법] List - len()

줄6과 줄7에서는 변수 sum과 avg를 0으로 초기화하면서 선언했어요.
줄8에서는 ip_list의 크기만큼 반복하는 for 루프를 시작하였지요.
줄9에서는 sum에 ip_list의 요소 하나를 더해서 그 값을 다시 sum에 저장하였고, 이 과정을 ip_list의 첫 번째 요소부터 마지막까지 반복했답니다. 즉, ip_list에 있는 모든 요소들의 총합을 구해서 sum에 저장한 것이지요.
줄10에서는 sum을 n으로 나누면서 평균값을 구하고 avg에 저장하고 있어요.
줄11은 return키워드를 이용해 avg를 리턴하고 있어요. 즉, 이 함수가 호출한 곳에 avg에 저장된 값을 돌려 주는 것이지요.




이동 평균 구하기

평균을 구하는 함수를 코딩했으니, 이제는 이동 평균을 코딩해 보지요.
이동 평균(Moving Average)는 사실 어려운 개념은 아니랍니다.
연속적으로 주어진 N개의 값들이 있을때, 처음부터 끝까지 "이동"하면서 n개의 요소들로만 평균을 구하는 것이지요. 예를 들어, n=5이라면, 처음에는 요소1~요소5들을 가지고 평균을 구하고, 그 다음에는 요소2~요소6으로 평균을 구하고, 그 다음에는 요소3~요소7들로 평균을 구하는 방식으로 끝까지 이동해 가는 것이예요.
자, 그럼 이동 평균을 계산하는 경우를 아래와 같이 코딩해 볼게요.

줄13은 별것 아니고, 그저 구분선으로 해 놓은 것이예요. "#" 뒤에 있는 내용은 주석처리되서, 실행이 안된다는 것 알고 있지요?
그럼, 왜 구분선을 그어놓았느냐?
함수는 호출될 때만 실행된다고 했지요? 그래서 구분선 위의 평균 구하는 함수는, 나중에 터미널에서 이 Python 파일을 실행했을때, 코드에서 호출하는 부분이 없으면 실행이 전혀 되지 않아요. 반면에, 구분선 아래 부분은 터미널에서 실행했을때, 지금까지 해왔던 것처럼 당연히 실행이 된답니다. 다시 말해, 구분선 아래 부분이 이 Python 파일이 실행될 때 처리되는 주(main)부분이라고 할 수 있답니다. 그리고, 그 main부분을 명확히 보이게 하려고 구분선을 그었답니다.

줄15는 연속된 값들의 갯수를 100개로 정하고 N에 저장하는 것이죠.
줄16은 uniform()을 이용하여, [0.0, 4.0) 범위에 있는 균등분포의 난수 100개를 생성하여 ip에 저장하는 것이지요. 단, 난수의 갯수를 100 대신 이미 저장해 놓은 변수 N로 전달했다는 것 잊지마세요.
줄17은 빈 리스트 op를 선언하고 있어요.

줄19에서부터는, 위에서 생성한 100개의 연속된 값들을 가지고 이동 평균을 구해 볼거예요.
줄19에서는 연속된 값들을 차례로 훑어가기 위해서 for loop를 선언하고 있어요. 그런데, range(10, N)을 사용하고 있지요? 즉, 반복 처리를 10에서 N-1까지 하겠다는 의미인데요. 왜 10에서 시작할까요? 바로, 우리는 10개의 요소들로만 평균을 구해나갈 것이기 때문이지요. 즉, 인덱스 번호로 생각하면, 처음에는 0~9의 요소들로 평균을 구하고, 그 다음은 1~10의 요소들로 구하고, 그 다음은 2~11의 요소들로 평균을 구하는 방식으로 이동 평균을 구현할 거랍니다.
줄20에서 평균을 구할 요소들을 뽑아내고 있는 것이랍니다. ip[i-10:i]는 ip의 (i-10)번째부터 (i-1)까지의 요소들을 의미하는 것이죠? 그리고, 그 갯수는 10개 이구요. 즉, 인덱스 번호 i를 기준으로 그 이전 10개의 값들을 뽑아내어 movingIp에 저장하는 것이랍니다.
줄21에서는 뽑아낸 10개의 값들, 즉, movingIp로 평균을 구하고 그것을 op에 쌓아 넣는 것이예요.
calcAvg(movingIp)는 movingIp를 전달인자로 부여하면서 calcAvg함수를 호출하는 것이지요. 그러면, calcAvg는 movingIp에 있는 값들로 평균을 구하고, 줄11에서 코딩한대로 그 평균값을 되돌려 주지요. 그리고, 그 리턴된 평균값은 리스트 op의 append()함수에 전달인자로 부여되고, op리스트에 쌓이게 되는 거랍니다. 리스트의 append()에 대해서 잠깐 알아보지요.

[문법] List - append()

이제, 원래 데이터인 생성된 100개의 난수들과 이를 기반으로 구해진 이동 평균값들을 그래프에 그려볼까요?
아래 줄23~26처럼 코딩해 보아요.

줄23은 figure을 생성하는 것이죠.
줄24는 원래 데이터인 N=100개의 난수를 파란선으로 그리고 있어요. 주목할 점은 x축 데이터로 난수들의 인덱스 번호를 주고자 했고, 이를 위해서 range(0, N)을 이용하여 0부터 N-1까지의 연속된 수들을 만들었다는 것이예요.
줄25는 이동 평균값들을 빨간선으로 그리고 있어요. 마찬가지로, x축 데이터로 인덱스 번호를 주고자 해요. 그런데, 이동 평균을 구할 때, 10개의 요소만 뽑으면서 이동했기 때문에, range(10, N)을 이용하여 10부터 N-1까지의 연속된 수들을 만들었지요.
줄26에서는 생성된 그래프를 보여주고 있지요.

이제 Python파일을 저장하고, 터미널에서 "python3 lec8_moving_avg.py"로 실행해 보세요. 실행하는 방법에 대해서 복습이 필요하면 여기로 가보세요.
실행 결과는 아래와 같답니다.




공학적/경제적 의미 알아보기

위 그래프를 보면, 파란선과 빨간선 사이에 어떤 차이점이 보이나요?
파란선은 생성된 난수를 보여주고 있어요. 난수, 즉, 무작위로 선택된 수들이다 보니, 컸다가 작았다가 정신없이 위아래로 왔다갔다 하지요.

공학적인 관점에서 이렇게 정신없이 진동하는 데이터를 보면, "데이터가 높은 주파수(Frequency)의 성분을 가졌다"라고 말해요. 주파수는 일정 시간동안 진동하는 횟수를 의미하니, 진동이 많은 난수 데이터의 경우에는 주파수가 높은 것이죠.
그런데, 이동 평균값들인 빨간선은 어떤가요? 진동 횟수가 현저히 적어진 것을 볼 수 있지요? 이런 데이터를 보면, "낮은 주파수의 성분을 가졌다"라고 말한답니다.
다시 말해서, 높은 주파수의 성분을 가진 데이터를 "이동 평균"이라는 신호 처리 기법에 통과시키니 낮은 주파수의 성분을 가진 데이터가 나온 것이죠. 한마디로,"이동 평균(Moving Average)"는 주어진 데이터의 높은 주파수의 성분을 제거하는 필터링(Filtering) 기능을 한답니다. 그래서, 공학에서는, 특히, 신호 처리(Signal Processing) 분야에서는, 이동 평균 필터(Moving Average Filter)라고 부른답니다.

경제적인 관점에서 한 번 볼까요?
경제 뉴스에서는 빨간선을 이동 평균선이라고 부르기도 하는데요. 위에서 설명했듯이, 이동 평균선은 높은 주파수 성분을 제거하는 필터링 기능이 있지요. 다시 말하면, 어떤 중요한 흐름이나 추세에 붙어 있는 단기적인 변동 성분들을 제거해 주는 것이지요. 그래서, 경제적으로는 단기적인 변화를 없애고, 장기적인 관점에서 큰 흐름이나 추세를 보고자 할 때 이동 평균을 사용한답니다.
예로, 어떤 주식 종목이 매일 오르락 내리락 해서 이 종목이 당최 상승 중인지 하락 중인지 혼란스러우면, 이동 평균선을 이용해 그 안에 있는 큰 흐름을 확인한답니다.

강의에서 작성된 소스 코드 (source code)를 다운받으려면, 다음 링크를 클릭하세요: 소스 코드 다운로드
혹시, 이해가 잘 안되는 부분에 대한 질문이 있거나 다루어 줬으면 하는 주제가 있으면, 화면 오르쪽 하단에 "질문하기" 버튼을 이용해 주세요.






발자취

2019-09-11 "키클 코딩랩 - 미국 공학박사 아빠의 코딩 연구소"로 이름 변경
2019-06-28 코딩 교실 공개
2019-03-18 코딩 교실 제작 시작

바로가기
About
Contact
Privacy Policy
강의목록
질문하기
처음으로