2010-10-28 199 views
1

爲了查找股票價格與時間的最大值繪製圖,首先必須爲給定的一組價格找到所有局部最大值(峯值)和局部最小值(谷值)和幾天。你如何在SQL Server 2005中做到這一點?在SQL中查找局部最大值和局部最小值

編輯: 有一種蠻力的方式,用光標做這件事: 比較第一天的高點到第二天的高點。 如果第一天的高價高於第二天的高價,那麼第一天的高價是本地最高價。

有效地,我需要找到價格圖形趨勢變化方向的每一點。

EDIT2:我要指出的是,數據庫表,從以下幾列工作:

stockid INT
一天日期
喜INT - 這是便士
低INT - 兼論在便士
因此對於給定的日期範圍,您會在該日期範圍內每天看到相同的stockid。

+0

可能的重複:[在SQL中計算「Max Draw Down」](http://stackoverflow.com/questions/4045177/calculating-max-draw-down- in-sql) – 2010-10-28 19:56:00

+0

更多的讚揚,而不是我認爲的重複。 – Ramy 2010-10-28 20:24:17

+0

更多的補充,而不是恭維,我想。 ;) – 2010-10-29 17:37:21

回答

0

Admitedly不徹底的測試 - 而是用CTE怎麼了,ROWNUMBER()做這兩個步驟

1)確定每行的所有nextsubseqent hi 2)緊鄰的下一行的後續高位小於當前行的任何行 - 那麼當前行必須是本地最大行。

或類似的東西:

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以上是錯誤的 - 這似乎是更多的軌道上:

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 

獲取雖與重複(高點/低點)問題...

1

OK,一步一步這裏就是我想:

1 - 尋找你的所有的「峯」,這是最高值較低最大值第二天:

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 - 尋找你的所有的「山谷」,這是最小的值具有較高的最小值第二天:

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 - 這些組合成按日期排序表一個標識值保持我們爲了

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 - 刪除異常

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

我已經開始查看您提供的峯的代碼。似乎有不太正確的東西。我正在玩一些實際的數據,看看我是否能夠弄清楚它是如何結束的 - 包括高點...... – Ramy 2010-10-28 20:50:39

+0

我即將回家,但發佈你發現我將在今晚晚些時候檢查。 – JNK 2010-10-28 21:00:44