在SQL中计算“Max Draw Down”

时间:2010-10-28 16:46:25

标签: sql sql-server sql-server-2005

编辑:值得回顾第一个答案的评论部分,以便更清楚地了解问题。

编辑:我正在使用SQLServer 2005

之前发布了类似于此的内容,但我认为海报没有提供足够的信息来真实地解释最大抽奖是什么。我对max draw-down的所有定义都来自本文的(前两页): http://www.stat.columbia.edu/~vecer/maxdrawdown3.pdf

有效地,您可以用数学方式定义一些术语:

运行最大值,M t

  

M t = [0,t] 中的max u(S u
  其中S t 是股票的价格,S,时间,t。

缩编,D t

  

D t = M t - S t

Max Draw Down,MDD t

  

MDD t = [0,t] 中的max u(D u

因此,有效的需要确定的是一段时间内给定股票的一组高价和低价的当地最大值和最小值。 我有一个历史报价表,其中包含以下(相关)列:

stockid int  
day date  
hi  int --this is in pennies  
low int --also in pennies  
     

因此,对于给定的日期范围,您将在该日期范围内每天看到相同的stockid。

修改
白天和白天都很高,每天都很低。

一旦确定了局部最大值和最小值,就可以将每个最大值与其后的每个最小值配对并计算差值。从该组中,最大差异将是“Max Draw Down”。

虽然困难的部分是找到那些最大和最小的。

编辑:应该注意: 最大亏损定义为假设损失的价值,如果股票在其最高买入点买入并以低卖点卖出。股票不能以maxval之前的最小值出售。所以,如果全局最小值在全局最大值之前,则这两个值不能提供足够的信息来确定最大值。

6 个答案:

答案 0 :(得分:3)

使用视图的残酷低效但非常简单的版本如下:

WITH DDView
AS (SELECT      pd_curr.StockID,
                pd_curr.Date,
                pd_curr.Low_Price  AS CurrPrice,
                pd_prev.High_Price AS PrevPrice,
                pd_curr.Low_Price / pd_prev.High_Price - 1.0 AS DD

    FROM        PriceData pd_curr
    INNER JOIN  PriceData pd_prev
            ON  pd_curr.StockID = pd_prev.StockID
            AND pd_curr.Date >= pd_prev.Date
            AND pd_curr.Low_Price <= pd_prev.High_Price
            AND pd_prev.Date >= '2001-12-31' -- @param: min_date of analyzed period
    WHERE       pd_curr.Date <= '2010-09-31' -- @param: max_date of analyzed period
)
SELECT      dd.StockID,
            MIN(COALESCE(dd.DD, 0)) AS MaxDrawDown
FROM        DDView dd
GROUP BY    dd.StockID

通常,您会在特定时间段内执行分析,将查询包装在带有参数@StartDate, @EndDate和可能@StockID的存储过程中是有意义的。同样,这在设计上是非常低效的 - O(N ^ 2),但是如果你有好的索引而不是大量的数据,SQL Server会很好地处理它。

答案 1 :(得分:1)

对于SQL Server和一次一个库存,请尝试以下操作:

Create Procedure 'MDDCalc'(
    @StartDate date,
    @EndDate date,
    @Stock int)

AS

DECLARE @MinVal Int
DECLARE @MaxVal Int
DECLARE @MaxDate date

SET @MaxVal = (
    SELECT MAX(hi)
    FROM Table
    WHERE Stockid = @Stock 
    AND Day BETWEEN (@Startdate-1) AND (@EndDate+1))

SET @MaxDate=(
    SELECT Min(Date)
    FROM Table
    WHERE Stockid = @Stock
    AND hi = @MaxVal)

SET @MinVal = (
    SELECT MIN(low)
    FROM Table
    WHERE Stockid = @Stock 
    AND Day BETWEEN (@MaxDate-1) AND (@EndDate+1))

SELECT  (@MaxVal-@MinVal) AS 'MDD'

答案 2 :(得分:1)

我们需要在问题域中考虑一些事项:

  1. 股票每天都有一系列价格,通常用烛台图表来查看
  2. 让我们拨打一天的最高价格HI
  3. 让我们调用一天的最低价格LOW
  4. 问题受时间限制,即使时间限制是IPO日期和退市日期
  5. 最大亏损是您在该时间范围内可能损失的最多亏损
  6. 假设LONG策略:逻辑上如果我们能够确定所有局部最大值(MAXES)和所有局部分钟(MINS),我们可以定义一组我们将每个MAX与每个后续MIN配对并计算差值DIFFS
  7. 有时差异会导致负数,但这不是缩编
  8. 因此,我们需要选择在差异集中追加0并选择最大值
  9. 问题在于定义MAXES和MINS,我们可以应用微积分的曲线函数,但我们不能。显然

    1. 最大需要来自HI和
    2. MINS需要来自LOW
    3. 解决此问题的一种方法是定义光标并强制它。功能语言也有很好的工具集来解决这个问题。

答案 3 :(得分:1)

我最近遇到过这个问题,我的解决方案是这样的: 让数据:3,5,7,3,-1,3,-8,-3,0,10 一个一个地加上和,如果总和大于0,设置为0,否则得到总和,结果就像这样 0,0,0,0,-1,0,-8,-11,-11,-1 最大下拉量是数据中的最低值,-11。

答案 4 :(得分:0)

这就是你要追求的吗?

select StockID,max(drawdown) maxdrawdown
from (
select h.StockID,h.day highdate,l.day lowdate,h.hi - l.lo drawdown
from mdd h
  inner join mdd l on h.StockID = l.StockID
    and h.day<l.day) x
group by StockID;

这是一种基于SQL的强力方法。它比较了同一股票中今天的高价之后的每个低价,并发现两个价格之间的最大差异。这将是最大平局。

由于我们在表格中没有足够的信息来确定Hi价格是否发生在当天的Lo价格之前,因此我们没有比较考虑当天的最大提款量。

答案 5 :(得分:0)

这是一个SQL Server 2005用户定义的函数,它应该非常有效地返回单个stockid的正确答案

CREATE FUNCTION dbo.StockMaxDD(@StockID int, @day datetime) RETURNS int  AS
 BEGIN
    Declare @MaxVal int;    Set @MaxVal = 0;
    Declare @MaxDD int;     Set @MaxDD = 0;

    SELECT TOP(99999)
        @MaxDD  = CASE WHEN @MaxDD < (@MaxVal-low) THEN (@MaxVal-low)  ELSE @MaxDD END,
        @MaxVal = CASE WHEN hi  > @MaxVal THEN hi   ELSE @MaxVal END
    FROM    StockHiLo
    WHERE   stockid = @Stockid
      AND   [day]  <= @day
    ORDER BY [day] ASC

    RETURN @MaxDD;
 END

然而,这对于同时进行多个库存来说不是非常有效。如果你需要同时做多个/所有的股票,那么有一个类似的,但实质上更难的方法可以非常有效地做到这一点。