2010-10-28 8 views
1

Pour trouver le maximum d'un graphique du cours de l'action en fonction du temps, vous devez d'abord trouver tous les maxima locaux (sommets) et minima locaux pour un ensemble de prix donné et jours. Comment feriez-vous cela dans SQL Server 2005?trouver les maximums locaux et les minimums locaux dans SQL

edit: Il existe une façon de faire de la force brute avec les curseurs: comparez le sommet du premier jour au sommet du jour suivant. si le point haut du premier jour est supérieur au point haut du jour suivant, le point haut du premier jour est un maximum local.

effectivement, j'ai besoin de trouver chaque point où la tendance du graphique des prix change de direction.

Edit2: Je dois souligner que la table de base de données pour travailler à partir a les colonnes suivantes:

stockid int
Date jour
salut int --Ce est en centimes
bas int --also en centimes
donc pour une période donnée, vous verrez le même stock tous les jours pour cette plage de dates.

+0

Copie possible de: [calcul de "Max Draw Down" dans SQL] (http://stackoverflow.com/questions/4045177/calculating-max-draw-down- en-sql) –

+0

plus d'un compliment qu'un duplicata je pense. – Ramy

+0

plus d'un complément que d'un compliment, je pense. ;) –

Répondre

0

Admitedly pas testé à fond - mais comment sur l'utilisation d'un CTE et ROWNUMBER() pour faire en deux étapes

1) Identifier tous les hi hi suivants pour chaque ligne 2) toute rangée dont la rangée suivante immédiate a une hauteur inférieure à la ligne courante - alors la ligne courante doit être un maximum local.

ou quelque chose comme ça:

begin 
    DECLARE @highTable as table (high bigint, day date) 

    declare @securityid int, 
    @start datetime, 
    @end datetime 

    set @start = '1-1-2010' 
    set @end = '2-1-2010' 
    select @securityid = id from security where riccode = 'MSFT.OQ' ; 

    with highsandlows_cte as (
     SELECT 
      ROW_NUMBER() over (order by day) i 
      , high 
      , day 
      , (select top 1 day from quotes nextHi where nextHi.high > today.high and nextHi.day >= today.day and nextHi.securityId = today.securityId order by day asc) nextHighestDay 

     FROM 
      quotes today 
     WHERE 
      today.securityid = @securityid) 

    select 
     * 
     , (Coalesce((select 1 from highsandlows_cte t2 where t1.i + 1 = t2.i and t1.nextHighestDay > t2.nextHighestDay),0)) as isHigh 
    from 
     highsandlows_cte t1 

    order by 
     day 
end 

ok ce qui précède est faux - cela semble être plus sur la bonne voie:

begin 
     DECLARE @highTable as table (high bigint, day date) 

     declare @securityid int, 
    @start datetime, 
    @end datetime 

     set @start = '1-1-2010' 
     set @end = '2-1-2010' 
     select @securityid = id from security where riccode = 'MSFT.OQ' ; 



     with highsandlows_cte as (
      SELECT 
        ROW_NUMBER() over (order by day) i 
        , high 
        , day 
        , low 
      FROM 
        quote today 
      WHERE 
        today.securityid = @securityid and today.day > convert(varchar(10), @start, 111) and convert(varchar(10), @end, 111) >today.day) 



select 
      cur.day 
      , cur.high 
      , cur.low 
     , case when ((cur.high > prv.high or prv.high IS null)and(cur.high > nxt.high or nxt.high is null)) then 1 else 0 end as isLocalMax 
     , case when ((cur.low < prv.low or prv.low IS null)and(cur.low < nxt.low or nxt.low is null)) then 1 else 0 end as isLocalMin 
    from 
     highsandlows_cte cur left outer join highsandlows_cte nxt 
       on cur.i + 1 = nxt.i 
      left outer join highsandlows_cte prv 
       on cur.i - 1 = prv.i 
    order by 
     cur.day 
end 

Obtenez des problèmes avec les doublons (Highs/bas), bien que ...

1

OK, étape par étape ici est ce que je pense:

1 - Retrouvez tous vos "pics" qui sont des valeurs max avec des valeurs inférieures max le jour suivant:

DECLARE @HiTable (hi int, day date) 

INSERT INTO @HiTable 
SELECT hi, day 
FROM table t1 
WHERE EXISTS (
SELECT t2.hi 
FROM Table t2 
WHERE t1.hi > t2.hi AND t1.day < t2.day and StockID = X) 

2 - Retrouvez tous vos « vallées » qui sont les valeurs min avec des valeurs supérieures min le jour suivant:

DECLARE @LowTable (low int, day date) 

INSERT INTO @LowTable 
SELECT low, day 
FROM table t1 
WHERE EXISTS (
SELECT t2.low 
FROM Table t2 
WHERE t1.low < t2.low AND t1.day < t2.day and StockID = X) 

3 - combiner en une table commandée par date, avec une valeur d'identité pour nous garder pour

DECLARE @TableVar (low int, hi int, day date, autoid int IDENTITY) 
INSERT INTO @TableVar 
(SELECT low, hi, day 
FROM (
SELECT Low, NULL as 'hi', date FROM @LowTable 
UNION ALL 
SELECT NULL as 'Low', hi, date FROM @HiTable 
) 
ORDER BY DATE) 

4 - Supprimer les valeurs aberrantes

DELETE FROM @TableVar WHERE AutoID > (SELECT MAX(AutoID) FROM @Table WHERE low IS NULL) 
DELETE FROM @TableVar WHERE AutoID < (SELECT MIN(AutoID) FROM @Table WHERE hi IS NULL) 
+0

J'ai commencé à regarder le code pour les pics que vous avez fournis.On dirait qu'il y a quelque chose qui ne va pas. Je joue avec quelques données réelles maintenant pour voir si je peux comprendre juste comment c'est fini-y compris les hauts .... – Ramy

+0

Je suis sur le point de rentrer à la maison, mais poster ce que vous trouvez je vérifierai plus tard ce soir. – JNK

Questions connexes