我想要有SQL代码,可以让我为每月股票数据形成五分之一投资组合。五分位投资组合的形成取决于比率(在我的电子表格中称为B/M)。我希望代码能够自动为每个月产生不同的五分位投资组合,因为与前一个月相比,股票/公司增加或撤销某个月。比率也可以改变,以便在接下来的一个月内某个股票可以排在另一个五分位数中。用SQL创建五分之一股票投资组合
我添加了一个打印屏幕来简要地展示我如何组织我的Excel表格。 基本上,它每月排序。 enter image description here
我想要有SQL代码,可以让我为每月股票数据形成五分之一投资组合。五分位投资组合的形成取决于比率(在我的电子表格中称为B/M)。我希望代码能够自动为每个月产生不同的五分位投资组合,因为与前一个月相比,股票/公司增加或撤销某个月。比率也可以改变,以便在接下来的一个月内某个股票可以排在另一个五分位数中。用SQL创建五分之一股票投资组合
我添加了一个打印屏幕来简要地展示我如何组织我的Excel表格。 基本上,它每月排序。 enter image description here
注意:这适用于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个不同的五分位数。它也低于其他昆泰3价格。所以检查它是你想要的。
最后,最好是添加一个日期维度表,预先为您计算日期部分,然后JOIN
这对您的主要子查询而言,但这是一个完全不同的讨论。
如果您计算比率,并且可以使用这些比率来确定某个五分位数应该处于哪个五分位数,那么它会使的变得更容易。您不必使用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
我看不到您的图片。你目前用什么公式计算比率?您可以使用窗口函数(https://docs.microsoft.com/zh-cn/sql/t-sql/functions/ranking-functions-transact-sql)计算五分位数。你使用什么风格和版本的SQL? – Shawn
另外,https://stackoverflow.com/help/mcve <<<非常有帮助。 – Shawn