SQLを使って株にテクニカル指標を出す① 単純移動平均線 / ボリンジャーバンド

SQLを使って株にテクニカル指標を出す① 単純移動平均線 / ボリンジャーバンド

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

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

色々なテクニカル指標があるので、改めて勉強の意味もあり
MACDやRSI、移動平均などなどのテクニカル指標の計算式をSQLで行ってみます。 今回の環境はPostgres 15.2を利用しています。

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

5日、25日、75日の単純移動平均を出す。

SELECT * FROM (
SELECT
 date,
 close,
 ROUND(AVG(close) OVER (ORDER BY date ASC ROWS BETWEEN 4 PRECEDING AND current ROW), 2) as _5moving_average,
 ROUND(AVG(close) OVER (ORDER BY date ASC ROWS BETWEEN 24 PRECEDING AND current ROW), 2) as _25moving_average,
 ROUND(AVG(close) OVER (ORDER BY date ASC ROWS BETWEEN 74 PRECEDING AND current ROW), 2) as _75moving_average
FROM
  nikkei225
ORDER BY
 date DESC) AS T1 WHERE date >= '2023-01-01';

単純移動平均線は自分の終値と計算する日数分の過去を平均する方法ですのでシンプルなWINDOW関数でできます。 WINDOW関数の部分でBETWEEN部分で必要な日数の-1日をする必要があるのが注意点となります。

RSIの計算

SELECT 
    date,
    ROUND(CASE WHEN a + b > 0 THEN a / (a + b) ELSE 0 END * 100, 2) AS rsi9,
    ROUND(CASE WHEN c + d > 0 THEN c / (c + d) ELSE 0 END * 100, 2) AS rsi14
FROM (
    SELECT 
        date, 
        ABS(SUM(CASE WHEN close > 0 THEN close ELSE 0 END) OVER w2 / 9) AS a,
        ABS(SUM(CASE WHEN close > 0 THEN 0 ELSE close END) OVER w2 / 9) AS b,
        ABS(SUM(CASE WHEN close > 0 THEN close ELSE 0 END) OVER w3 / 14) AS c,
        ABS(SUM(CASE WHEN close > 0 THEN 0 ELSE close END) OVER w3 / 14) AS d
    FROM (
        SELECT
            date, close - last_value(close) OVER w1 AS close
        FROM
            nikkei225 
        WINDOW
            w1 AS (ORDER BY date DESC ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) 
    ) AS S1
        WINDOW w2 AS (ORDER BY date DESC ROWS BETWEEN 0 PRECEDING AND 8 FOLLOWING),
        w3 AS (ORDER BY date DESC ROWS BETWEEN 0 PRECEDING AND 13 FOLLOWING)
) AS T2;

RSIの計算方法は以下のような形となる ① RS=(n日間の終値の上昇幅の平均)÷(n日間の終値の下落幅の平均) ② RSI= 100 - (100 ÷ (RS+1)) これをSQLで表現するとサブクエリを用いて行い複雑化していくことになるがしょうがないです。

ボリンジャーバンドの±1〜3σを計算

SELECT 
    date,
    ROUND(_25moving_average, 2) AS ma,
    ROUND(_25moving_average + _25stddev, 2) AS plus1sigma,
    ROUND(_25moving_average - _25stddev, 2) AS minus1sigma,
    ROUND(_25moving_average + _25stddev * 2, 2) AS plus2sigma,
    ROUND(_25moving_average - _25stddev * 2, 2) AS minus2sigma,
    ROUND(_25moving_average + _25stddev * 3, 2) AS plus3sigma,
    ROUND(_25moving_average - _25stddev * 3, 2) AS minus3sigma
FROM (
SELECT
 date,
 STDDEV_POP(close) OVER w _25stddev,
 AVG(close) OVER w as _25moving_average
FROM
  nikkei225
WINDOW
   w AS (ORDER BY date ASC ROWS BETWEEN 24 PRECEDING AND current ROW)
ORDER BY
 date DESC) AS T1;

ボリンジャーバンドは、移動平均と標準偏差の計算で求められるのでSQLとしては結構シンプルだと思います。 ただ、標準偏差を求める際に、母標準偏差を基準に計算するためSTDDEV_POP関数を利用しています。

まとめ

3指標をまとめましたがSQLとしてはまだ計算しやすいところをまとめました。 指数移動平均や、加重移動平均などのWITH句を駆使する感じもできないか模索中ですのでできたら上げます。