使用 SQL Server 2014 计算简单移动平均线交叉
Calculate a Simple Moving Average Crossover using SQL Server 2014
如何实现简单移动平均线交叉?我在这里查看了其他一些 example/questions 问题,但是他们似乎都使用 ID 列,我的 table 没有 ID 并使用 TIME 作为唯一字段。
SMA 交叉用于确定股票 and/or 外汇市场的趋势。为了简洁起见,下面建议的查询输出是 10 天和 20 天的移动平均线。然而,在现实世界中,我将使用 60 天和 270 天的平均值。
继 (big thanks to Lucero) 之后,计算平均值有两个答案。第一个 ATR 平均值比第二个快得多。
我有以下数据:
TIME BID-OPEN BID-HIGH BID-LOW BID-CLOSE
28/01/1981 22:00 130.34 130.34 130.34 130.34
29/01/1981 22:00 130.24 130.24 130.24 130.24
02/02/1981 22:00 126.91 126.91 126.91 126.91
03/02/1981 22:00 128.46 128.46 128.46 128.46
04/02/1981 22:00 128.59 128.59 128.59 128.59
05/02/1981 22:00 129.63 129.63 129.63 129.63
09/02/1981 22:00 129.27 129.27 129.27 129.27
10/02/1981 22:00 129.24 129.24 129.24 129.24
11/02/1981 22:00 128.24 128.24 128.24 128.24
12/02/1981 22:00 127.48 127.48 127.48 127.48
17/02/1981 22:00 127.81 127.81 127.81 127.81
18/02/1981 22:00 128.48 128.48 128.48 128.48
19/02/1981 22:00 126.61 126.61 126.61 126.61
23/02/1981 22:00 127.35 127.35 127.35 127.35
24/02/1981 22:00 127.39 127.39 127.39 127.39
25/02/1981 22:00 128.52 128.52 128.52 128.52
26/02/1981 22:00 130.1 130.1 130.1 130.1
02/03/1981 22:00 132.01 132.01 132.01 132.01
03/03/1981 22:00 130.56 130.56 130.56 130.56
04/03/1981 22:00 130.86 130.86 130.86 130.86
05/03/1981 22:00 129.93 129.93 129.93 129.93
09/03/1981 22:00 131.12 131.12 131.12 131.12
10/03/1981 22:00 130.46 130.46 130.46 130.46
11/03/1981 22:00 129.95 129.95 129.95 129.95
12/03/1981 22:00 133.19 133.19 133.19 133.19
16/03/1981 22:00 134.68 134.68 134.68 134.68
17/03/1981 22:00 133.92 133.92 133.92 133.92
18/03/1981 22:00 134.22 134.22 134.22 134.22
19/03/1981 22:00 133.46 133.46 133.46 133.46
23/03/1981 22:00 135.69 135.69 135.69 135.69
24/03/1981 22:00 134.67 134.67 134.67 134.67
下面建议的查询输出,过去 10 天和 20 天的 [BID-CLOSE] 值的平均值,将给出这样的输出:
(四舍五入到小数点后两位)
TIME BID-CLOSE FAST-SMA SLOW-SMA
28/01/1981 22:00 130.34 NULL NULL
29/01/1981 22:00 130.24 NULL NULL
02/02/1981 22:00 126.91 NULL NULL
03/02/1981 22:00 128.46 NULL NULL
04/02/1981 22:00 128.59 NULL NULL
05/02/1981 22:00 129.63 NULL NULL
09/02/1981 22:00 129.27 NULL NULL
10/02/1981 22:00 129.24 NULL NULL
11/02/1981 22:00 128.24 NULL NULL
12/02/1981 22:00 127.48 128.84 NULL
17/02/1981 22:00 127.81 128.59 NULL
18/02/1981 22:00 128.48 128.41 NULL
19/02/1981 22:00 126.61 128.39 NULL
23/02/1981 22:00 127.35 128.27 NULL
24/02/1981 22:00 127.39 128.15 NULL
25/02/1981 22:00 128.52 128.04 NULL
26/02/1981 22:00 130.1 128.12 NULL
02/03/1981 22:00 132.01 128.40 NULL
03/03/1981 22:00 130.56 128.63 NULL
04/03/1981 22:00 130.86 128.97 128.90
05/03/1981 22:00 129.93 129.18 128.89
09/03/1981 22:00 131.12 129.45 128.93
10/03/1981 22:00 130.46 129.83 129.11
11/03/1981 22:00 129.95 130.09 129.18
12/03/1981 22:00 133.19 130.67 129.41
16/03/1981 22:00 134.68 131.29 129.66
17/03/1981 22:00 133.92 131.67 129.90
18/03/1981 22:00 134.22 131.89 130.14
19/03/1981 22:00 133.46 132.18 130.41
23/03/1981 22:00 135.69 132.67 130.82
24/03/1981 22:00 134.67 133.14 131.16
SMA = 简单移动平均线
作为起点,您可能希望使用 avg() over(),如下所示:
select time,
[bid-close],
avg([bid-close]) over (order by time rows 9 preceding) as [fast-sma]
avg([bid-close]) over (order by time rows 19 preceding) as [slow-sma]
from table
您可以通过将 window 函数包装在 ROW_NUMBER()
的条件中来阻止计算前 n 行的 SMA。
要检测正交叉和负交叉,您可以使用 LAG()
函数使用多条件检查当前值和先前值。
这应该能满足您的需求:
WITH sma_table AS
(
SELECT
time,
bid_open,
bid_high,
bid_low,
bid_close,
CASE WHEN ROW_NUMBER() OVER (ORDER BY time) > 9
THEN AVG(bid_close) OVER (ORDER BY time ROWS 9 PRECEDING)
END AS sma_10,
CASE WHEN ROW_NUMBER() OVER (ORDER BY time) > 19
THEN AVG(bid_close) OVER (ORDER BY time ROWS 19 PRECEDING)
END AS sma_20
FROM your_table
)
SELECT
*,
CASE WHEN bid_close > sma_10
AND LAG(bid_close) OVER (ORDER BY time) <= LAG(sma_10) OVER (ORDER BY time)
THEN 1
WHEN bid_close < sma_10
AND LAG(bid_close) OVER (ORDER BY time) >= LAG(sma_10) OVER (ORDER BY time)
THEN -1
END AS sma_10_crossover,
CASE WHEN bid_close > sma_20
AND LAG(bid_close) OVER (ORDER BY time) <= LAG(sma_20) OVER (ORDER BY time)
THEN 1
WHEN bid_close < sma_20
AND LAG(bid_close) OVER (ORDER BY time) >= LAG(sma_20) OVER (ORDER BY time)
THEN -1
END AS sma_20_crossover
FROM sma_table
如何实现简单移动平均线交叉?我在这里查看了其他一些 example/questions 问题,但是他们似乎都使用 ID 列,我的 table 没有 ID 并使用 TIME 作为唯一字段。
SMA 交叉用于确定股票 and/or 外汇市场的趋势。为了简洁起见,下面建议的查询输出是 10 天和 20 天的移动平均线。然而,在现实世界中,我将使用 60 天和 270 天的平均值。
继
我有以下数据:
TIME BID-OPEN BID-HIGH BID-LOW BID-CLOSE
28/01/1981 22:00 130.34 130.34 130.34 130.34
29/01/1981 22:00 130.24 130.24 130.24 130.24
02/02/1981 22:00 126.91 126.91 126.91 126.91
03/02/1981 22:00 128.46 128.46 128.46 128.46
04/02/1981 22:00 128.59 128.59 128.59 128.59
05/02/1981 22:00 129.63 129.63 129.63 129.63
09/02/1981 22:00 129.27 129.27 129.27 129.27
10/02/1981 22:00 129.24 129.24 129.24 129.24
11/02/1981 22:00 128.24 128.24 128.24 128.24
12/02/1981 22:00 127.48 127.48 127.48 127.48
17/02/1981 22:00 127.81 127.81 127.81 127.81
18/02/1981 22:00 128.48 128.48 128.48 128.48
19/02/1981 22:00 126.61 126.61 126.61 126.61
23/02/1981 22:00 127.35 127.35 127.35 127.35
24/02/1981 22:00 127.39 127.39 127.39 127.39
25/02/1981 22:00 128.52 128.52 128.52 128.52
26/02/1981 22:00 130.1 130.1 130.1 130.1
02/03/1981 22:00 132.01 132.01 132.01 132.01
03/03/1981 22:00 130.56 130.56 130.56 130.56
04/03/1981 22:00 130.86 130.86 130.86 130.86
05/03/1981 22:00 129.93 129.93 129.93 129.93
09/03/1981 22:00 131.12 131.12 131.12 131.12
10/03/1981 22:00 130.46 130.46 130.46 130.46
11/03/1981 22:00 129.95 129.95 129.95 129.95
12/03/1981 22:00 133.19 133.19 133.19 133.19
16/03/1981 22:00 134.68 134.68 134.68 134.68
17/03/1981 22:00 133.92 133.92 133.92 133.92
18/03/1981 22:00 134.22 134.22 134.22 134.22
19/03/1981 22:00 133.46 133.46 133.46 133.46
23/03/1981 22:00 135.69 135.69 135.69 135.69
24/03/1981 22:00 134.67 134.67 134.67 134.67
下面建议的查询输出,过去 10 天和 20 天的 [BID-CLOSE] 值的平均值,将给出这样的输出:
(四舍五入到小数点后两位)
TIME BID-CLOSE FAST-SMA SLOW-SMA
28/01/1981 22:00 130.34 NULL NULL
29/01/1981 22:00 130.24 NULL NULL
02/02/1981 22:00 126.91 NULL NULL
03/02/1981 22:00 128.46 NULL NULL
04/02/1981 22:00 128.59 NULL NULL
05/02/1981 22:00 129.63 NULL NULL
09/02/1981 22:00 129.27 NULL NULL
10/02/1981 22:00 129.24 NULL NULL
11/02/1981 22:00 128.24 NULL NULL
12/02/1981 22:00 127.48 128.84 NULL
17/02/1981 22:00 127.81 128.59 NULL
18/02/1981 22:00 128.48 128.41 NULL
19/02/1981 22:00 126.61 128.39 NULL
23/02/1981 22:00 127.35 128.27 NULL
24/02/1981 22:00 127.39 128.15 NULL
25/02/1981 22:00 128.52 128.04 NULL
26/02/1981 22:00 130.1 128.12 NULL
02/03/1981 22:00 132.01 128.40 NULL
03/03/1981 22:00 130.56 128.63 NULL
04/03/1981 22:00 130.86 128.97 128.90
05/03/1981 22:00 129.93 129.18 128.89
09/03/1981 22:00 131.12 129.45 128.93
10/03/1981 22:00 130.46 129.83 129.11
11/03/1981 22:00 129.95 130.09 129.18
12/03/1981 22:00 133.19 130.67 129.41
16/03/1981 22:00 134.68 131.29 129.66
17/03/1981 22:00 133.92 131.67 129.90
18/03/1981 22:00 134.22 131.89 130.14
19/03/1981 22:00 133.46 132.18 130.41
23/03/1981 22:00 135.69 132.67 130.82
24/03/1981 22:00 134.67 133.14 131.16
SMA = 简单移动平均线
作为起点,您可能希望使用 avg() over(),如下所示:
select time,
[bid-close],
avg([bid-close]) over (order by time rows 9 preceding) as [fast-sma]
avg([bid-close]) over (order by time rows 19 preceding) as [slow-sma]
from table
您可以通过将 window 函数包装在 ROW_NUMBER()
的条件中来阻止计算前 n 行的 SMA。
要检测正交叉和负交叉,您可以使用 LAG()
函数使用多条件检查当前值和先前值。
这应该能满足您的需求:
WITH sma_table AS
(
SELECT
time,
bid_open,
bid_high,
bid_low,
bid_close,
CASE WHEN ROW_NUMBER() OVER (ORDER BY time) > 9
THEN AVG(bid_close) OVER (ORDER BY time ROWS 9 PRECEDING)
END AS sma_10,
CASE WHEN ROW_NUMBER() OVER (ORDER BY time) > 19
THEN AVG(bid_close) OVER (ORDER BY time ROWS 19 PRECEDING)
END AS sma_20
FROM your_table
)
SELECT
*,
CASE WHEN bid_close > sma_10
AND LAG(bid_close) OVER (ORDER BY time) <= LAG(sma_10) OVER (ORDER BY time)
THEN 1
WHEN bid_close < sma_10
AND LAG(bid_close) OVER (ORDER BY time) >= LAG(sma_10) OVER (ORDER BY time)
THEN -1
END AS sma_10_crossover,
CASE WHEN bid_close > sma_20
AND LAG(bid_close) OVER (ORDER BY time) <= LAG(sma_20) OVER (ORDER BY time)
THEN 1
WHEN bid_close < sma_20
AND LAG(bid_close) OVER (ORDER BY time) >= LAG(sma_20) OVER (ORDER BY time)
THEN -1
END AS sma_20_crossover
FROM sma_table