es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Máximo en los últimos 52 semanas

Tengo una base de datos de acciones en SQL Server y estoy tratando de calcular los precios de cierre máximo y mínimo de las acciones en los últimos 52 periodos semanales continuos.

Al usar la función de ventana MAX() y tratar de particionar los periodos de los últimos 52 semanas, ¿cómo puedo limitar la partición solo a los últimos 52 semanas (o un periodo de 1 año)?

Creo que lo que estoy haciendo (captura de pantalla) producirá el máximo móvil para las 365 observaciones móviles. Pero debido a que los mercados están cerrados los fines de semana y los días festivos, esto puede no ser realmente el mismo que los 52 semanas:

SELECT
symbol,
fechas,
[close],

MAX( [close] ) OVER(PARTITION BY symbol
ORDER BY fechas
ROWS BETWEEN 364 PRECEDING AND CURRENT ROW) AS [52_semanas_alto]

FROM dbo.adj_daily_prices

WHERE
fechas BETWEEN CAST(‘2019-01-01’ AS DATE) AND CAST(‘2021-10-15’ AS DATE)
AND
symbol = ‘CLR’
AND
es_ultimo = 1

ORDER BY
fechas DESC

Imagino que hay una forma ingeniosa de hacer esto con una expresión CASE WHEN?

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Para limitar la partición solo al período de 52 semanas anteriores, teniendo en cuenta los fines de semana y días festivos, se puede utilizar una combinación de funciones y expresiones. Un enfoque es utilizar la función DATEDIFF para calcular el número de días laborales entre la fila actual y la fila que se encuentra 52 semanas atrás. Luego se puede utilizar este valor en la expresión ROWS BETWEEN para limitar la partición al período de 52 semanas anteriores, excluyendo fines de semana y días festivos. Aquí tienes un ejemplo:

    SELECT 
      symbol, 
      dates, 
      [close],
    
      MAX( [close] ) OVER(PARTITION BY symbol 
        ORDER BY dates
        ROWS BETWEEN 
          UNBOUNDED PRECEDING 
          AND 
          CASE 
            -- calcular el número de días laborales entre la fila actual y la fila que se encuentra 52 semanas atrás
            WHEN DATEDIFF(WEEK, dates, lag(dates, 52) OVER (PARTITION BY symbol ORDER BY dates)) * 2 < 52 
              -- si hay menos de 52 días laborales, utilizar el número real de días laborales
              THEN DATEDIFF(WEEKDAY, lag(dates, 52) OVER (PARTITION BY symbol ORDER BY dates), dates) 
              -- de lo contrario, utilizar 52 días laborales
              ELSE 52 * 2 - DATEDIFF(WEEKDAY, lag(dates, 52) OVER (PARTITION BY symbol ORDER BY dates), dates) 
            END 
          PRECEDING) AS [52_week_high]
    
    FROM dbo.adj_daily_prices
    
    WHERE 
      dates BETWEEN CAST('2019-01-01' AS DATE) AND CAST('2021-10-15' AS DATE)
      AND
      symbol = 'CLR'
      AND
      is_last = 1
    
    ORDER BY
      dates DESC
    

    En este ejemplo, primero utilizamos la función lag para obtener la fecha que se encuentra 52 semanas atrás. Luego utilizamos la función DATEDIFF para calcular el número de semanas entre la fila actual y esta fecha. Esto nos proporciona el número de días laborales entre las dos fechas, excluyendo fines de semana y días festivos. Luego utilizamos una declaración CASE para comprobar si este valor es menor que 52. Si es así, utilizamos el número real de días laborales como límite superior para la expresión ROWS BETWEEN. De lo contrario, utilizamos 52 días laborales. Esto asegura que la partición siempre esté limitada al período de 52 semanas anteriores, teniendo en cuenta los fines de semana y días festivos.

Comments are closed.