2016-03-13 1 views
0

Я хотел бы вычислить Average True Range с использованием MS SQL Server 2014.Вычислить Average True Range с помощью 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 

Токовый выход запроса, который вычисляет True Range заключается в следующем:

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..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..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 запроса выше.

Благодарим вас за помощь!

+0

Возможно, объясните, что действительно должен иметь True Range - это действительно просто макс 'H-L',' H-Cp' и 'L-Cp'? – Lucero

+0

Здравствуйте, Lucero, Да TR - это максимум [H-L], [H-Cp], [L-Cp]. ATR - среднее значение TR за последние X дней, в этом случае 10 дней. Это следует из http://stackoverflow.com/questions/35956703/calculate-the-true-range-using-sql-server-2014/35957111?noredirect=1#comment59569936_35957111 – James

ответ

0

Нечто подобное может сделать, используя тот же подход, как с 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() является просто игнорировать аннулирует, которые не удовлетворили бы ваше требование вернуть нуль для первого п-1 д AYS.

+0

Msg 207, уровень 16, состояние 1, Строка 37 Недопустимое имя столбца 'TR1'. – James

+0

Это сообщение об ошибке, которое я получаю для каждого TR1-TR9 – James

+0

Msg 207, уровень 16, состояние 1, строка 37 Недопустимое имя столбца 'TR2'. Msg 207, уровень 16, состояние 1, строка 37 Недопустимое имя столбца 'TR3'. Msg 207, уровень 16, состояние 1, строка 37 Недопустимое имя столбца 'TR4'. Msg 207, уровень 16, состояние 1, строка 37 Неверное имя столбца 'TR5'. Msg 207, уровень 16, состояние 1, строка 37 Недопустимое имя столбца 'TR6'. Msg 207, уровень 16, состояние 1, строка 37 Неверное имя столбца 'TR7'. Msg 207, уровень 16, состояние 1, строка 37 Неверное имя столбца 'TR8'. Msg 207, уровень 16, состояние 1, строка 37 Недопустимое имя столбца 'TR9'. Msg 207, уровень 16, состояние 1, строка 36 Неверное имя столбца 'TR9'. – James