2013-03-13 96 views
4

我想要計算股票的3日移動平均線(實際上30天)量。 我試圖得到最後3個日期條目的平均值(而不是今天-3天)。我一直在嘗試用SQL Server 2012中的rownumber做些事情,但沒有成功。任何人都可以幫忙。下面是一個模板模式,以及我對SQL的垃圾嘗試。我有以下SQL的各種化身與分組,但仍然無法正常工作。非常感謝!移動平均PER TICKER爲每一天

select dt_eod, ticker, volume 
from 
(
    select dt_eod, ticker, avg(volume) 
    row_number() over(partition by dt_eod order by max_close desc) rn 
    from mytable 
) src 
where rn >= 1 and rn <= 3 
order by dt_eod 

示例模式:

CREATE TABLE yourtable 
    ([dt_date] int, [ticker] varchar(1), [volume] int); 

INSERT INTO yourtable 
    ([dt_date], [ticker], [volume]) 
VALUES 
    (20121201, 'A', 5), 
    (20121201, 'B', 7), 
    (20121201, 'C', 6), 
    (20121202, 'A', 10), 
    (20121202, 'B', 8),  
    (20121202, 'C', 7), 
    (20121203, 'A', 10),  
    (20121203, 'B', 87),  
    (20121203, 'C', 74), 
    (20121204, 'A', 10),  
    (20121204, 'B', 86), 
    (20121204, 'C', 67), 
    (20121205, 'A', 100), 
    (20121205, 'B', 84), 
    (20121205, 'C', 70),  
    (20121206, 'A', 258), 
    (20121206, 'B', 864), 
    (20121206, 'C', 740); 
+0

如果您創建了一個包含Year和BusinessDay(從1到250左右)的Calandar表,那麼您可以將它加入到它,並通過BusinesDay(getdate()) - 3到BusinesDay(getdate())進行平均。 – 2013-03-13 20:56:21

回答

3

三天平均每一行:

with top3Values as 
(
    select t.ticker, t.dt_date, top3.volume 
    from yourtable t 
    outer apply 
    (
     select top 3 top3.volume 
     from yourtable top3 
     where t.ticker = top3.ticker 
     and t.dt_date >= top3.dt_date 
     order by top3.dt_date desc 
    ) top3 
) 
select ticker, dt_date, ThreeDayVolume = avg(volume) 
from top3Values 
group by ticker, dt_date 
order by ticker, dt_date 

SQL Fiddle demo

最新值:

with tickers as 
(
    select distinct ticker from yourtable 
), top3Values as 
(
    select t.ticker, top3.volume 
    from tickers t 
    outer apply 
    (
     select top 3 top3.volume 
     from yourtable top3 
     where t.ticker = top3.ticker 
     order by dt_date desc 
    ) top3 
) 
select ticker, ThreeDayVolume = avg(volume) 
from top3Values 
group by ticker 
order by ticker 

SQL Fiddle demo

現實,你就不需要創建代號CTE第二查詢,因爲你會被此基礎上[ticker]表,你可能會在查詢某種date參數,但希望這會讓你走上正軌。

+0

太棒了 - 它的作品,只需要現在就完全理解它! – SQLseeker 2013-03-13 21:50:15

+0

確實不錯。但是,使用'cross apply'而不是'outer apply'會產生相同的輸出,並且可能產生更好的執行計劃。 – 2013-03-14 21:49:35

+0

公平點,很難避免每個人都加入到自己的行列中......在這種情況下,「外部應用」顯然過於謹慎! – 2013-03-14 22:34:56

2

你提到了SQL 2012,這意味着你可以利用一個更簡單的範例。

select dt_date, ticker, avg(1.0*volume) over (
    partition by ticker 
    order by dt_date 
    ROWS BETWEEN 2 preceding and current row 
) 
from yourtable 

我覺得這對於實際嘗試完成的東西要透明得多。

1

你可能想看看這裏介紹的另一種技術:SQL-Server Moving Averages set-based algorithm with flexible window-periods and no self-joins

該算法相當快速(比APPLY快得多,在性能上不會像APPLY那樣降低數據點窗口的擴展性),可以很容易地適應您的需求,適用於pre-SQL2012,並克服了SQL的侷限性-2012的窗口功能需要在OVER/PARTITION-BY子句中對窗口寬度進行硬編碼。

對於具有移動價格平均一個股市類型的應用程序,它是一個常見的需求,以允許用戶到變化的包括在平均(從UI選擇數據點的數量,如允許用戶選擇7天,30天,60天等),而SQL-2012的OVER子句無法處理此變量分區寬度要求,而無需動態SQL。