SQLを使って株にテクニカル指標を出す④ MACD

SQLを使って株にテクニカル指標を出す④ MACD

Twitter LINEで送る Facebook はてなブログ

株のテクニカル指標をまとめる

SQLを使って株にテクニカル指標を出す③に続き4個目 今回は、MACD(Moving Average Convergence/Divergence Trading Method)を解説 MACDはテクニカルでよく使われるものですがあんまり計算を実際に試すことがないと思います。 この計算には指数移動平均の計算が必須となるため上記の「SQLを使って株にテクニカル指標を出す③」を 確認された上で見る事をお勧めいたします。

参照するデータは前回同様、2023年の日経平均を利用します。
  利用するデータは こちらにSQLを準備 2023年分の情報を出すのに2022年のデータが必要ですので入れています。

MACD(Moving Average Convergence/Divergence Trading Method)

MACDは3つの値を使った手法となり以下のようなものであれわせます。

MACD(マックディ線):n日EMA-m日EMA
シグナル:MACDのk日EMA
ヒストグラム:MACD - シグナル
※EMA:指数移動平均の略

nは短期期間、mは長期期間,kはシグナル期間と言われ値としては n = 12, m = 26, k = 9が主に使われることが一般的な値です。 今回もこれを基準にします。

MACDをSQLで求める

WITH句を4つ使って求めています。 色々試してみてみましたが自分の力では4つまでに絞るのが限界でした。

WITH RECURSIVE
-- 初項を生成するWITH句
wr_select_ema(i, date, close, exponent12, exponent26) AS (
SELECT
	ROW_NUMBER() OVER (ORDER BY date) AS i,
	date,
	close AS close,
	CASE WHEN COUNT(close) OVER w1 = 12 THEN
		ROUND(AVG(close) OVER w1, 10)
	ELSE
		NULL
	END AS exponent12,
	CASE WHEN COUNT(close) OVER w2 = 26 THEN
		ROUND(AVG(close) OVER w2, 10)
	ELSE
		NULL
	END AS exponent26
FROM
	nikkei225
WINDOW
	w1 AS (ORDER BY date ASC ROWS BETWEEN 11 PRECEDING AND current ROW),
	w2 AS (ORDER BY date ASC ROWS BETWEEN 25 PRECEDING AND current ROW)
),
-- 指数移動平均を計算するWITH句
wr_calc_ema AS  (
	SELECT 
		i,
		date,
		close,
		exponent12,
		exponent26
		-- 試験用に3/11日を基準日とした初項を強制代入
		-- 25783.35 AS exponent12,
		-- 26596.25 AS exponent26
	FROM
		wr_select_ema
	WHERE
		i = (SELECT MIN(i) FROM wr_select_ema WHERE exponent26 IS NOT NULL)
		-- 試験用に3/11日を基準日とした初項を強制代入
		-- i = 46
UNION ALL
	SELECT 
		T2.i,
		T2.date, T2.close, 
		CASE WHEN T1.exponent12 IS NOT NULL THEN
			ROUND(T1.exponent12 + (0.153846153846154) * (T2.close-T1.exponent12), 10)
		ELSE
			NULL
		END AS exponent12,
		CASE WHEN T1.exponent26 IS NOT NULL THEN
			ROUND(T1.exponent26 + (0.074074074074074) * (T2.close-T1.exponent26), 10)
		ELSE
			NULL
		END AS exponent26
	FROM
		wr_calc_ema AS T1, wr_select_ema AS T2
	WHERE
		T1.i + 1 = T2.i
),
-- シグナルの初項を計算するWITH句
wr_select_macd(i, date, macd, signal) AS (
	SELECT
		i,
		date,
		exponent12 - exponent26 AS macd,
		CASE WHEN COUNT(close) OVER w = 9 THEN
			ROUND(AVG(exponent12 - exponent26) OVER w, 10)
		ELSE
			NULL
		END AS signal
	FROM
		wr_calc_ema
	WINDOW
		w AS (ORDER BY date ASC ROWS BETWEEN 8 PRECEDING AND current ROW)	
),
-- MACDの計算と、シグナル、ヒストグラムの計算
wr_select_macd_all(i, date, macd, signal, histogram) AS (
	SELECT
		i,
		date,
		ROUND(macd, 2),
		ROUND(signal, 2),
		ROUND(macd - signal, 2) AS histogram
	FROM
		wr_select_macd
	WHERE
		i = (SELECT MIN(i) FROM wr_select_macd WHERE signal IS NOT NULL)
UNION ALL
	SELECT 
		T2.i,
		T2.date,  
		ROUND(T2.macd, 2) AS macd,
		ROUND(T1.signal + (0.2) * (T2.macd - T1.signal), 2) AS signal,
		ROUND(T2.macd - ROUND(T1.signal + (0.2) * (T2.macd - T1.signal), 2), 2) AS histogram
    FROM
		wr_select_macd_all AS T1, wr_select_macd AS T2
	WHERE
		T1.i + 1 = T2.i
) 
SELECT * FROM wr_select_macd_all;

wr_select_ema

ここでは、行番号の割り当てと12日と26日、単純移動平均の値を算出しています。 その際に、12日や26日に満たない場合はNULLを出力することで計算できない部分をNULLにしています。

wr_calc_ema

ここでは、12日、26日の指数移動平均を求めています。 デバッグ用に初項を固定する事で、他のツールと値が同じになるかを確認する方法を取ったので コメントアウト部分がそれに該当する形です。

12日の指数が (2 / (1 + 12)) = 0.153846153846154
26日の指数が (2 / (1 + 26)) = 0.074074074074074

このように計算された結果を利用しています。

wr_select_macd

ここでは、MACDの値とシグナルの初項を計算しています。 MACDの値だけだとここで終わるのですがシグナル自身も指数移動平均のため 次の四季で最終完成となります。

wr_select_macd_all

最後に、シグナルの計算を行うとヒストグラムも合わせて計算を行い 必要な値ができます。

まとめ

思っている以上に面倒ですが、SQLを組み合わせれば色々なことができることがわかる内容かと思います。
よくMACDは見ているので実際に計算してみてこうなっているのかということが理解できてよかったです。