使用SQL Server 2014计算平均真实范围

时间:2016-03-13 11:08:36

标签: sql-server

我想使用MS SQL Server 2014计算平均真实范围。

主表如下所示:

TIME                   BID-OPEN BID-HIGH BID-LOW BID-CLOSE
1993-05-09 21:00:00.000 1.5786  1.5786  1.5311  1.5346
1993-05-10 21:00:00.000 1.5346  1.5551  1.5326  1.5391
1993-05-11 21:00:00.000 1.5391  1.5521  1.5299  1.5306
1993-05-12 21:00:00.000 1.5306  1.5451  1.5106  1.5256
1993-05-13 21:00:00.000 1.5256  1.5416  1.5211  1.5361
1993-05-16 21:00:00.000 1.5361  1.5534  1.5318  1.5361
1993-05-17 21:00:00.000 1.5361  1.5451  1.5243  1.5361
1993-05-18 21:00:00.000 1.5361  1.5506  1.5316  1.5431
1993-05-19 21:00:00.000 1.5431  1.5686  1.5391  1.5566
1993-05-20 21:00:00.000 1.5566  1.5665  1.5401  1.5481
1993-05-23 21:00:00.000 1.5481  1.5481  1.5221  1.5356
1993-05-24 21:00:00.000 1.5356  1.5491  1.5341  1.5436
1993-05-25 21:00:00.000 1.5436  1.5567  1.5421  1.5476
1993-05-26 21:00:00.000 1.5476  1.5656  1.5421  1.5621
1993-05-27 21:00:00.000 1.5621  1.5714  1.5546  1.5621
1993-05-30 21:00:00.000 1.5621  1.5631  1.5571  1.5621
1993-05-31 21:00:00.000 1.5621  1.5706  1.5421  1.5611
1993-06-01 21:00:00.000 1.5611  1.5611  1.5341  1.5341
1993-06-02 21:00:00.000 1.5341  1.5526  1.5341  1.5411
1993-06-03 21:00:00.000 1.5411  1.5566  1.5071  1.5081
1993-06-06 21:00:00.000 1.5081  1.5306  1.5071  1.5246
1993-06-07 21:00:00.000 1.5246  1.5306  1.5142  1.5221
1993-06-08 21:00:00.000 1.5221  1.5271  1.5076  1.5148
1993-06-09 21:00:00.000 1.5148  1.5326  1.5016  1.5301
1993-06-10 21:00:00.000 1.5301  1.5401  1.5056  1.5231
1993-06-13 21:00:00.000 1.5231  1.5331  1.5226  1.5281
1993-06-14 21:00:00.000 1.5281  1.5391  1.5151  1.5171
1993-06-15 21:00:00.000 1.5171  1.5283  1.4991  1.5063
1993-06-16 21:00:00.000 1.5063  1.5186  1.4994  1.5153
1993-06-17 21:00:00.000 1.5153  1.5171  1.4901  1.4941
1993-06-20 21:00:00.000 1.4941  1.4988  1.4808  1.4888
1993-06-21 21:00:00.000 1.4888  1.4911  1.4751  1.4788
1993-06-22 21:00:00.000 1.4788  1.4846  1.4681  1.4715
1993-06-23 21:00:00.000 1.4715  1.4776  1.4645  1.4704
1993-06-24 21:00:00.000 1.4704  1.4886  1.4661  1.4806

计算真实范围的当前查询输出为:

Time                    H-L     H-Cp    L-Cp    TR
1993-05-09 21:00:00.000 0.0475  NULL    NULL    0.0475
1993-05-10 21:00:00.000 0.0225  0.0205  0.002   0.0225
1993-05-11 21:00:00.000 0.0222  0.013   0.0092  0.0222
1993-05-12 21:00:00.000 0.0345  0.0145  0.02    0.0345
1993-05-13 21:00:00.000 0.0205  0.016   0.0045  0.0205
1993-05-16 21:00:00.000 0.0216  0.0173  0.0043  0.0216
1993-05-17 21:00:00.000 0.0208  0.009   0.0118  0.0208
1993-05-18 21:00:00.000 0.019   0.0145  0.0045  0.019
1993-05-19 21:00:00.000 0.0295  0.0255  0.004   0.0295
1993-05-20 21:00:00.000 0.0264  0.0099  0.0165  0.0264
1993-05-23 21:00:00.000 0.026   0       0.026   0.026
1993-05-24 21:00:00.000 0.015   0.0135  0.0015  0.015
1993-05-25 21:00:00.000 0.0146  0.0131  0.0015  0.0146
1993-05-26 21:00:00.000 0.0235  0.018   0.0055  0.0235
1993-05-27 21:00:00.000 0.0168  0.0093  0.0075  0.0168
1993-05-30 21:00:00.000 0.006   0.001   0.005   0.006
1993-05-31 21:00:00.000 0.0285  0.0085  0.02    0.0285
1993-06-01 21:00:00.000 0.027   0       0.027   0.027
1993-06-02 21:00:00.000 0.0185  0.0185  0       0.0185
1993-06-03 21:00:00.000 0.0495  0.0155  0.034   0.0495
1993-06-06 21:00:00.000 0.0235  0.0225  0.001   0.0235
1993-06-07 21:00:00.000 0.0164  0.006   0.0104  0.0164
1993-06-08 21:00:00.000 0.0195  0.005   0.0145  0.0195
1993-06-09 21:00:00.000 0.031   0.0178  0.0132  0.031
1993-06-10 21:00:00.000 0.0345  0.01    0.0245  0.0345
1993-06-13 21:00:00.000 0.0105  0.01    0.0005  0.0105
1993-06-14 21:00:00.000 0.024   0.011   0.013   0.024
1993-06-15 21:00:00.000 0.0292  0.0112  0.018   0.0292
1993-06-16 21:00:00.000 0.0192  0.0123  0.0069  0.0192
1993-06-17 21:00:00.000 0.027   0.0018  0.0252  0.027
1993-06-20 21:00:00.000 0.018   0.0047  0.0133  0.018
1993-06-21 21:00:00.000 0.016   0.0023  0.0137  0.016
1993-06-22 21:00:00.000 0.0165  0.0058  0.0107  0.0165
1993-06-23 21:00:00.000 0.0131  0.0061  0.007   0.0131
1993-06-24 21:00:00.000 0.0225  0.0182  0.0043  0.0225

使用此SQL查询:(感谢Lad2025)

WITH cte AS
(
  SELECT 
    t.[Time]
   ,[H-L]    = Round([BID-HIGH]-[BID-LOW],5) 
   ,[H-Cp]   = Abs(Round([BID-HIGH]-[prev_BID-CLOSE],5)) 
   ,[L-Cp]   = Abs(Round([BID-LOW]-[prev_BID-CLOSE],5))
  FROM (SELECT *, 
               [prev_BID-CLOSE]  = LAG([BID-CLOSE]) OVER(ORDER BY [Time])
        FROM [#tbl_GBP-USD_1-Day]) AS t
)
SELECT *
FROM cte
CROSS APPLY (SELECT MAX(v) AS v
             FROM ( VALUES ([H-L]),([H-Cp]),([L-Cp])) AS value(v)
) AS sub([TR]);

以下示例ATR查询是10天ATR(平均真实范围)。

正如您所看到的,前9行是空白的,因为这些数据需要计算前10天的平均值[TR]。然后,第一次ATR计算后的每一行是最后[TR] 10天的平均值,依此类推。

TIME                    H-L     H-Cp    L-Cp    TR      ATR
1993/05/09 21:00:00.000 0.0475  NULL    NULL    0.0475
1993/05/10 21:00:00.000 0.0225  0.0205  0.002   0.0225  
1993/05/11 21:00:00.000 0.0222  0.013   0.0092  0.0222  
1993/05/12 21:00:00.000 0.0345  0.0145  0.02    0.0345  
1993/05/13 21:00:00.000 0.0205  0.016   0.0045  0.0205  
1993/05/16 21:00:00.000 0.0216  0.0173  0.0043  0.0216  
1993/05/17 21:00:00.000 0.0208  0.009   0.0118  0.0208  
1993/05/18 21:00:00.000 0.019   0.0145  0.0045  0.019   
1993/05/19 21:00:00.000 0.0295  0.0255  0.004   0.0295  
1993/05/20 21:00:00.000 0.0264  0.0099  0.0165  0.0264  0.02645
1993/05/23 21:00:00.000 0.026   0       0.026   0.026   0.0243
1993/05/24 21:00:00.000 0.015   0.0135  0.0015  0.015   0.02355
1993/05/25 21:00:00.000 0.0146  0.0131  0.0015  0.0146  0.02279
1993/05/26 21:00:00.000 0.0235  0.018   0.0055  0.0235  0.02169
1993/05/27 21:00:00.000 0.0168  0.0093  0.0075  0.0168  0.02132
1993/05/30 21:00:00.000 0.006   0.001   0.005   0.006   0.01976
1993/05/31 21:00:00.000 0.0285  0.0085  0.02    0.0285  0.02053
1993/06/01 21:00:00.000 0.027   0       0.027   0.027   0.02133
1993/06/02 21:00:00.000 0.0185  0.0185  0       0.0185  0.02023
1993/06/03 21:00:00.000 0.0495  0.0155  0.034   0.0495  0.02254
1993/06/06 21:00:00.000 0.0235  0.0225  0.001   0.0235  0.02229
1993/06/07 21:00:00.000 0.0164  0.006   0.0104  0.0164  0.02243
1993/06/08 21:00:00.000 0.0195  0.005   0.0145  0.0195  0.02292
1993/06/09 21:00:00.000 0.031   0.0178  0.0132  0.031   0.02367
1993/06/10 21:00:00.000 0.0345  0.01    0.0245  0.0345  0.02544
1993/06/13 21:00:00.000 0.0105  0.01    0.0005  0.0105  0.02589
1993/06/14 21:00:00.000 0.024   0.011   0.013   0.024   0.02544
1993/06/15 21:00:00.000 0.0292  0.0112  0.018   0.0292  0.02566
1993/06/16 21:00:00.000 0.0192  0.0123  0.0069  0.0192  0.02573
1993/06/17 21:00:00.000 0.027   0.0018  0.0252  0.027   0.02348
1993/06/20 21:00:00.000 0.018   0.0047  0.0133  0.018   0.02293
1993/06/21 21:00:00.000 0.016   0.0023  0.0137  0.016   0.02289
1993/06/22 21:00:00.000 0.0165  0.0058  0.0107  0.0165  0.02259
1993/06/23 21:00:00.000 0.0131  0.0061  0.007   0.0131  0.0208
1993/06/24 21:00:00.000 0.0225  0.0182  0.0043  0.0225  0.0196

进一步扩大。

[H-L] = High (minus) Low, 
[H-Cp] = High (Minus) Previous Day Close, 
[L-Cp] = Low (Minus) Previous Day Close
[TR] = MAX Value of [H-L],[H-Cp],[L-Cp]
[ATR] = Average of TR over X amount of days

X in this case is 10 days

我需要一些SQL语句添加到上面的当前TR查询代码中。

谢谢你的帮助!

2 个答案:

答案 0 :(得分:1)

这样的事情可能会这样做,使用与TR相同的方法:

WITH cteRange AS (
    SELECT 
        t.[Time],
        Round(t.[BID-HIGH]-t.[BID-LOW],5) AS [H-L],
        Abs(Round(t.[BID-HIGH]-t.[prev_BID-CLOSE],5)) AS [H-Cp],
        Abs(Round(t.[BID-LOW]-t.[prev_BID-CLOSE],5)) AS [L-Cp]
    FROM (
        SELECT *, [prev_BID-CLOSE]  = LAG([BID-CLOSE]) OVER (ORDER BY [Time])
        FROM [#tbl_GBP-USD_1-Day]
    ) AS t
), cteTrueRange AS (
    SELECT *
    FROM cteRange
    CROSS APPLY (
        SELECT MAX(v) AS v
        FROM (VALUES ([H-L]), ([H-Cp]), ([L-Cp])) AS value(v)
    ) AS sub([TR])
), cteTrueRange10 AS (
    SELECT
        *,
        LAG([TR], 1) OVER (ORDER BY [Time]) AS [TR1],
        LAG([TR], 2) OVER (ORDER BY [Time]) AS [TR2],
        LAG([TR], 3) OVER (ORDER BY [Time]) AS [TR3],
        LAG([TR], 4) OVER (ORDER BY [Time]) AS [TR4],
        LAG([TR], 5) OVER (ORDER BY [Time]) AS [TR5],
        LAG([TR], 6) OVER (ORDER BY [Time]) AS [TR6],
        LAG([TR], 7) OVER (ORDER BY [Time]) AS [TR7],
        LAG([TR], 8) OVER (ORDER BY [Time]) AS [TR8],
        LAG([TR], 9) OVER (ORDER BY [Time]) AS [TR9]
    FROM cteTrueRange
)
SELECT [Time], [H-L], [H-Cp], [L-Cp], [TR], [TRA]
    FROM cteTrueRange10
    CROSS APPLY (
        SELECT CASE WHEN [TR9] IS NOT NULL THEN AVG(v) END AS v
        FROM (VALUES ([TR]), ([TR1]), ([TR2]), ([TR3]), ([TR4]), ([TR5]), ([TR6]), ([TR7]), ([TR8]), ([TR9])) AS value(v)
    ) AS sub([TRA]);

在这里,评论中解释了另一个解决方案,你可以在任何天数内平均得分(在这种情况下为100):

WITH cteRange AS (
    SELECT 
        t.[Time],
        ROUND(t.[BID-HIGH]-t.[BID-LOW],5) AS [H-L],
        ABS(ROUND(t.[BID-HIGH]-t.[prev_BID-CLOSE],5)) AS [H-Cp],
        ABS(ROUND(t.[BID-LOW]-t.[prev_BID-CLOSE],5)) AS [L-Cp]
    FROM (
        SELECT *, [prev_BID-CLOSE]  = LAG(u.[BID-CLOSE]) OVER (ORDER BY u.[Time])
        FROM [#tbl_GBP-USD_1-Day] u
    ) AS t
), cteTrueRange AS (
    SELECT *, ROW_NUMBER() OVER (ORDER BY [time]) AS ix
    FROM cteRange
    CROSS APPLY (
        SELECT MAX(v) AS v
        FROM (VALUES ([H-L]), ([H-Cp]), ([L-Cp])) AS value(v)
    ) AS sub([TR])
)
SELECT t.[Time], t.[H-L], t.[H-Cp], t.[L-Cp], t.[TR], CASE WHEN LAG(t.[TR], 100) OVER (ORDER BY t.[time]) IS NOT NULL THEN (
        SELECT ROUND(AVG([TR]), 5) FROM cteTrueRange t2 WHERE (t2.ix > t.ix-100) AND (t2.ix <= t.ix)
    ) END AS [TRA]
    FROM cteTrueRange t;

这里的LAG([TR], 100)调用用于阻止平均值忽略NULL - AVG()的正常行为只是忽略空值,这不符合您为此返回null的要求前n-1天。

答案 1 :(得分:0)

以上答案是正确的。但是,此处计算 ATR 的方式不正确。真实范围计算很好,但 ATR 的公式(在本例中为 14 天)是:

ATR = [(之前的 ATR* x 13) + 当前的 TR] / 14

*第一个 ATR 使用过去 14 天“真实范围”的简单移动平均线 (SMA))

如您所见,它有点复杂。

我知道这是旧的,但我想我会在任何人(其他人)使用它进行分析之前更正计算。