이동 평균선은 일정 기간에 주가를 산술 평균한 값을 모두 연결해 선으로 표현한 것이다.
보통 5일, 20일, 60일, 120일 범위로 이동 평균선을 보여준다.
01. 현재 날짜로부터 5일, 20일 이동 평균값 구하기
stock 테이블에서 symbol = 'MSFT"인 일별 주가 데이터에서 현재 날짜로부터 5일 이동 평균값과 20일 이동 평균값을 구한다. a 테이블 기준으로 5일 범위의 b 테이블과 20일 범위의 c 테이블을 LEFT OUTER JOIN한다. 구체적인 조건은 a 테이블을 기준으로 b 테이블에서는 5일 이전의 a 테이블의 현재 날짜까지의 평균값을 계산하고, c테이블에서는 20일 날짜 이전부터 a 테이블의 현재까지의 평균값을 계산한다. SELECT 문에는 기준이 되는 a 테이블에서 date, symbol, close 값을 가져오고, b와 c 테이블에서는 구간의 최소 날짜, 최대 날짜와 평균가를 표시한다.
SELECT
a.date,
a.symbol,
a.[close],
'' AS '---',
MIN(b.date) AS day5_start,
MAX(b.date) AS day5_end,
AVG(b.[close]) AS day5_close,
'' AS '---',
MIN(c.date) AS day20_start,
MAX(c.date) AS day20_end,
AVG(c.[close]) AS day20_close
FROM stock AS a
LEFT OUTER JOIN stock AS b ON a.symbol = b.symbol AND a.date <= dateadd(day, 5, b.date) AND a.date >=b.date
LEFT OUTER JOIN stock AS c ON a.symbol = c.symbol AND a.date <= dateadd(day, 20, c.date) AND a.date >=c.date
WHERE a.symbol ='MSFT'
GROUP BY a.date, a.symbol, a.[close]
ORDER BY a.date
결과를 보면 5일, 20일 평균값을 계산하므로 기준 테이블 a에서 최소 5일 이상의 데이터를 가지는 행부터 살펴봐야 정상인지 판단할 수 있다.
LEFT OUTER JOIN의 ON 조건에서 a.date <= dateadd(day, 5, b.date) AND a.date >=b.date는
a일부터 a+5일 사이의 날짜를 검색하는 조건을 의미한다.
02. 데이터 오차 방지를 위해 일별 순위를 부여하고 평균 검색하기
위 결과는 정확할까? 전일 대비 상승한 종목을 검색하거나 N일 이상 상승한 종목을 검색할 때 주말이나 공휴일이 포함되면 -1일로 조인할 경우 조인 조건에 맞지 않아 데이터 누락이 발생할 수 있다. 이럴 때는 데이터에 순위를 부여해 누락 없이 전일 데이터를 비교하는 방법을 사용해야 한다.
WITH cte_avg AS (
SELECT
ROW_NUMBER() OVER(PARTITION BY symbol ORDER BY date ASC) AS num,
CONVERT(nvarchar(10), date, 120) AS date,
symbol,
CONVERT(DECIMAL(18,2), [close]) AS [close]
FROM stock
WHERE symbol = 'MSFT'
GROUP BY date, symbol, [close]
)
SELECT
a.date,
a.symbol,
a.[close],
'' AS '---',
MIN(b.date) AS day5_start,
MAX(b.date) AS day5_end,
AVG(b.[close]) AS day5_close,
'' AS '---',
MIN(c.date) AS day20_start,
MAX(c.date) AS day20_end,
AVG(c.[close]) AS day20_close
FROM cte_avg AS a
LEFT OUTER JOIN cte_avg AS b ON a.symbol = b.symbol AND a.num <= (b.num + 5) AND a.num >=b.num
LEFT OUTER JOIN cte_avg AS c ON a.symbol = c.symbol AND a.num <= (c.num + 20) AND a.num >=c.num
WHERE a.symbol ='MSFT'
GROUP BY a.date, a.symbol, a.[close]
ORDER BY a.date
CTE 테이블을 만들 때 ROW_NUMBER()를 사용해 우선 순위를 부여했고 이때 symbol 그룹별로 순위를 부여하기 위해 PARTITION BY문을 함께 사용했다. CTE 테이블 밖의 SELECT 문에 a 테이블을 기준으로 LEFT OUTER JOIN을 했다. 이번에는 조인 조건이 ROW_NUMBER에 부여된 num이다.
03. 엑셀에 데이터를 옮긴 뒤 이동 평균선 확인하기
'IT Story > SQL Story' 카테고리의 다른 글
국가 통계 데이터 분석하기: 연도별 인구 증감 분석하기 (0) | 2022.12.08 |
---|---|
국가 통계 데이터 분석하기: 행정 구역별 인구 분석하기 (0) | 2022.12.08 |
보유 주식 수익 증감액 구하기 (0) | 2022.12.08 |
특정 기간 주가 하락했다가 회복한 종목의 증감률 구하기 (0) | 2022.12.08 |
주가가 연속 상승한 종목 분석하기 (0) | 2022.12.07 |