我想拥有允许我为月度股票数据形成五分类投资组合的SQL代码。五分位组合的形成取决于比率(在我的电子表格中称为B / M)。我希望代码能够自动生成每个月不同的五分类投资组合,因为与上个月相比,某个月的股票/公司被添加或撤销。比率也可以改变,以便在下个月某个股票可以在另一个五分位数中排名。
我添加了一个版画屏幕,简要介绍了我如何组织我的Excel工作表。 基本上,它按月排序。enter image description here
答案 0 :(得分:0)
注意:这适用于MS SQL 2008 +。
我不知道您的数据结构是什么样的,但也许是
的内容/* Test Data */
WITH stocks AS (
/* Jan = 10 = 2 per quint */
SELECT 'abc' AS StockName, 100.00 AS StockPrice, '20170101' AS PriceDate UNION ALL
SELECT 'def' AS StockName, 99.00 AS StockPrice, '20170101' AS PriceDate UNION ALL
SELECT 'ghi' AS StockName, 50.00 AS StockPrice, '20170101' AS PriceDate UNION ALL
SELECT 'jkl' AS StockName, 50.00 AS StockPrice, '20170101' AS PriceDate UNION ALL
SELECT 'mno' AS StockName, 75.00 AS StockPrice, '20170101' AS PriceDate UNION ALL
SELECT 'pqr' AS StockName, 77.00 AS StockPrice, '20170101' AS PriceDate UNION ALL
SELECT 'stu' AS StockName, 20.00 AS StockPrice, '20170101' AS PriceDate UNION ALL
SELECT 'vwx' AS StockName, 10.00 AS StockPrice, '20170101' AS PriceDate UNION ALL
SELECT 'yz1' AS StockName, 2.00 AS StockPrice, '20170101' AS PriceDate UNION ALL
SELECT '234' AS StockName, 1.00 AS StockPrice, '20170101' AS PriceDate UNION ALL
/* Feb = 7 = uneven quints */
SELECT 'abc' AS StockName, 1.00 AS StockPrice, '20170201' AS PriceDate UNION ALL
SELECT 'def' AS StockName, 2.00 AS StockPrice, '20170201' AS PriceDate UNION ALL
SELECT 'ghi' AS StockName, 20.00 AS StockPrice, '20170201' AS PriceDate UNION ALL
SELECT 'jkl' AS StockName, 55.00 AS StockPrice, '20170201' AS PriceDate UNION ALL
SELECT 'mno' AS StockName, 50.00 AS StockPrice, '20170201' AS PriceDate UNION ALL
SELECT 'pqr' AS StockName, 100.00 AS StockPrice, '20170201' AS PriceDate UNION ALL
SELECT 'stu' AS StockName, 90.00 AS StockPrice, '20170201' AS PriceDate UNION ALL
/* Mar = 3 = not enough for 5 quints. */
SELECT 'abc' AS StockName, 42.00 AS StockPrice, '20170301' AS PriceDate UNION ALL
SELECT 'jkl' AS StockName, 42.00 AS StockPrice, '20170301' AS PriceDate UNION ALL
SELECT 'vwx' AS StockName, 42.00 AS StockPrice, '20170301' AS PriceDate
)
/* Query */
SELECT y.StockName, y.StockPrice, y.PriceMonth, y.quintile
FROM (
SELECT x.StockName, x.StockPrice, month(x.PriceDate) AS PriceMonth
, NTILE(5) OVER (PARTITION BY month(x.PriceDate) ORDER BY x.StockPrice DESC) AS quintile
FROM stocks x
GROUP BY x.StockName, x.StockPrice, month(x.PriceDate)
) y
ORDER BY y.PriceMonth, y.quintile ASC
给你
StockName StockPrice PriceMonth quintile
abc 100.00 1 1
def 99.00 1 1
pqr 77.00 1 2
mno 75.00 1 2
ghi 50.00 1 3
jkl 50.00 1 3
stu 20.00 1 4
vwx 10.00 1 4
yz1 2.00 1 5
234 1.00 1 5
pqr 100.00 2 1
stu 90.00 2 1
jkl 55.00 2 2
mno 50.00 2 2
ghi 20.00 2 3
def 2.00 2 4
abc 1.00 2 5
abc 42.00 3 1
jkl 42.00 3 2
vwx 42.00 3 3
然后当你显示它时,你可以按五分位进行排序/分组。
另外,我上面的示例说明了NTILE()可能不一定能为您提供所需的内容。您可能需要计算然后自己创建五分位数。请参阅三月组>>所有都是42美元,但他们被分为3个不同的五分位数。它也低于其他Quintile 3价格。所以检查它是你想要的。
最后,最好添加一个日期维度表,为您预先计算日期部分,然后JOIN
为您的主要子查询,但这是一个完全不同的讨论。
答案 1 :(得分:0)
如果您计算比率,并且您可以使用它们来确定应该使用哪个五分位数,那么它会更容易 。您不必使用NTILE(),您可以设置一个CTE,指定落入每个五分位数的最小和最大比率。
/* Test Data */
IF OBJECT_ID(N'tempdb..#stocks') IS NOT NULL
DROP TABLE #stocks
;
CREATE TABLE #stocks (StockName varchar(10), BMratio int, StockMonth datetime) ;
INSERT INTO #stocks (StockName, BMratio, StockMonth)
/* Jan = 10 = 2 per quint */
SELECT 'abc' AS StockName, 10 AS BMratio, '20170101' AS StockMonth UNION ALL
SELECT 'def' AS StockName, 9 AS BMratio, '20170101' AS StockMonth UNION ALL
SELECT 'ghi' AS StockName, 8 AS BMratio, '20170101' AS StockMonth UNION ALL
SELECT 'jkl' AS StockName, 7 AS BMratio, '20170101' AS StockMonth UNION ALL
SELECT 'mno' AS StockName, 6 AS BMratio, '20170101' AS StockMonth UNION ALL
SELECT 'pqr' AS StockName, 5 AS BMratio, '20170101' AS StockMonth UNION ALL
SELECT 'stu' AS StockName, 4 AS BMratio, '20170101' AS StockMonth UNION ALL
SELECT 'vwx' AS StockName, 3 AS BMratio, '20170101' AS StockMonth UNION ALL
SELECT 'yz1' AS StockName, 2 AS BMratio, '20170101' AS StockMonth UNION ALL
SELECT '234' AS StockName, 1 AS BMratio, '20170101' AS StockMonth UNION ALL
/* Feb = 7 = uneven quints */
SELECT 'abc' AS StockName, 1 AS BMratio, '20170201' AS StockMonth UNION ALL
SELECT 'def' AS StockName, 2 AS BMratio, '20170201' AS StockMonth UNION ALL
SELECT 'ghi' AS StockName, 4 AS BMratio, '20170201' AS StockMonth UNION ALL
SELECT 'jkl' AS StockName, 5 AS BMratio, '20170201' AS StockMonth UNION ALL
SELECT 'mno' AS StockName, 7 AS BMratio, '20170201' AS StockMonth UNION ALL
SELECT 'pqr' AS StockName, 10 AS BMratio, '20170201' AS StockMonth UNION ALL
SELECT 'stu' AS StockName, 9 AS BMratio, '20170201' AS StockMonth UNION ALL
/* Mar = 3 = not enough for 5 quints. */
SELECT 'abc' AS StockName, 5 AS BMratio, '20170301' AS StockMonth UNION ALL
SELECT 'jkl' AS StockName, 5 AS BMratio, '20170301' AS StockMonth UNION ALL
SELECT 'vwx' AS StockName, 5 AS BMratio, '20170301' AS StockMonth
;
/* Create CTE query */
; WITH Quint_CTE AS (
SELECT 1 AS quintNum, 9 AS quintMin, 10 AS quintMax UNION ALL
SELECT 2 AS quintNum, 7 AS quintMin, 8 AS quintMax UNION ALL
SELECT 3 AS quintNum, 5 AS quintMin, 6 AS quintMax UNION ALL
SELECT 4 AS quintNum, 3 AS quintMin, 4 AS quintMax UNION ALL
SELECT 5 AS quintNum, 0 AS quintMin, 2 AS quintMax
)
SELECT x.StockName, month(x.StockMonth) AS StockMonth, q.quintNum AS quintile
FROM #stocks x
INNER JOIN Quint_CTE q ON x.BMratio BETWEEN q.quintMin AND q.quintMax
ORDER BY StockMonth, q.quintNum ASC