为了找到股票价格与时间图表的最大亏损,您首先必须找到给定价格和天数的所有局部最大值(峰值)和局部最小值(谷值)。您将如何在SQL Server 2005中执行此操作?
编辑: 使用游标有一种蛮力的方式: 比较第一天的高点和第二天的高点。 如果第一天的高点高于第二天的高点,则第一天的高点是当地的Max。
有效地,我需要找到价格图表趋势改变方向的每个点。
edit2:我应该注意到要使用的数据库表包含以下列:
stockid int
日期
嗨int - 这是便士 低价 - 也是便士 因此,对于给定的日期范围,您将在该日期范围内每天看到相同的stockid。
答案 0 :(得分:1)
好的,这里一步一步是我的想法:
1 - 查找所有“峰值”,这些峰值是第二天LOWER最大值的最大值:
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)
答案 1 :(得分:0)
有时未经过彻底测试 - 但如何使用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
好的以上是错误的 - 这似乎更正常:
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
虽然可以解决重复(高/低)问题...