使用MYSQL中的闭市价格的简单移动平均值计算和更新表格

时间:2012-10-21 13:17:51

标签: mysql sql average finance

我可以使用一些帮助(最好是假人指南)来更新下表:

CREATE TABLE `SYMBOL` (
  `day` date NOT NULL,
  `open` decimal(8,3) DEFAULT NULL,
  `high` decimal(8,3) DEFAULT NULL,
  `low` decimal(8,3) DEFAULT NULL,
  `close` decimal(8,3) DEFAULT NULL,
  `volume` bigint(20) DEFAULT NULL,
  `adj_close` decimal(8,3) DEFAULT NULL,
  `moving_average` decimal(8,3) DEFAULT NULL,
  PRIMARY KEY (`day`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

moving_average列现在为空。填充所有其他列(暂时,我很好,这是“静态”,它不需要更新,因为我添加行 - 但如果这很容易做,那将是伟大的)。这是我希望计算的20天移动平均线。

我已经尝试过尽我所能执行此处的步骤:

How do I calculate a moving average using MySQL?

我的疑问是:

SELECT
     `close`,
     (
     SELECT
          AVG(`close`) AS moving_average
     FROM
          SYMBOL T2
     WHERE
          (
               SELECT
                    COUNT(*)
               FROM
                    SYMBOL T3
               WHERE
                    `day` BETWEEN T2.day AND T1.day
          ) BETWEEN 1 AND 20
     )
FROM
     SYMBOL T1

我是否正确修改了查询?将结果写入moving_average列需要做些什么?

当我运行以上操作时,没有任何反应(它说它运行,没有错误,让它运行很长一段时间后我就停止了它)。列moving_average仍然具有NULL值。

我也看了这个答案: How to calculated multiple moving average in MySQL

但是,我不确定我需要更改为我的桌子的回复。

感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

有两种方法可以做到这一点:

  1. 创建更新表格中每一行的update查询
  2. 创建执行作业的存储过程
  3. 我个人更喜欢选项2:

    delimiter $$
    create procedure movingAvg()
    begin
        declare mv double;
        declare t date;
        declare done int default false;
        declare cur_t cursor for
             select distinct day from symbol
             order by day;
        declare cur_mv cursor for
             select avg(close) from symbol
             where day between date_add(t, interval -19 day) and t;
             -- Here you define the interval of your MV.
             -- If you want a 20-day MV, then the interval is between t-19 and t
        declare continue handler for not found set done=true;
    
        open cur_t;
        loop_day: loop
            fetch cur_t into t;
            if not done then
                open cur_mv;
                fetch cur_mv into mv;
                close cur_mv;
                update SYMBOL
                    set moving_average = mv
                    where day=t;
            else
                leave loop_day;
            end if;
        end loop loop_day;
        close cur_t;
    end;
    delimiter ;
    

答案 1 :(得分:0)

这是一个可能的解决方案:

update SYMBOLS
from (
   select a.day
        , avg(b.close) as moving_average
   from   SYMBOLS a
   cross join SYMBOLS b
   where b.day BETWEEN date_sub(a.day, INTERVAL 19 DAY) and a.day
      and a.moving_average is null
   group by a.day
   ) x
set moving_average=x.moving_average
where SYMBOLS.day=x.day

抱歉,我自己不使用mysql,所以我猜测日期算术语法。我添加了一个条件,只更新moving_average为空的行。

更新:请确保您了解此解决方案基于365天的日历。大多数股票市场平均值如“20天”或“30天”均基于不包括周末和假日的交易日历。您需要自己创建一个交易日历表(所有交易日期的简单列表)。如果你想这样做,你可能想问一个新的问题。