MYSQL:30日均线股价

时间:2015-09-19 09:49:42

标签: mysql

目的根据输入日期而非最新日期选择每只股票最近30个交易日的平均收盘价

鉴于此;

1)如果输入日期是2015-09-18,则选择最近30个交易日的平均收盘价,例如(2015-09-18,2015-09-17,2015-09-16,...... 30天)

2)如果输入日期是2015-09-01,则选择最近30个交易日的平均收盘价,例如(2015-09-01,2015-09-31,2015-09-28,...... 30天)

3)表栏:自动收报机|代码|日期|打开|高|低|关闭|卷

4)表格仅包含交易日,周末和假日的记录

5)对于每只股票,有数千天的记录,但我们只想在任何给定时间点获得30天MA

Input date: 2015-09-01
Desired output

date     | ticker | code |  30 day average closing price 
2015-09-01  AAA    1122     1.33
2015-09-01  BBB    3344     0.79
... 
...
...and so on for each stock

2 个答案:

答案 0 :(得分:0)

EDIT 这个版本应该是灵活的,我希望不要太慢。由于不知道表格中的内容以及表格的调用方式,因此我假设一个表格可以使用代码=' AAA'' BBB'所以和close意味着价格。您的指定日期应为' 2015-09-12'这里。替换' 2015-09-12'无论你喜欢什么。

30应该是交易日数。在'限制30'。

中替换您想要的任何内容

自动收报机|代码|日期|打开|高|低|关闭|体积

尝试此版本

select pt.code, sum(pt.close) / count(*) as average
from pricetable pt 
inner join 
  ( select distinct `date`
    from pricetable 
    where `date` <= '2015-09-12' # your given date
    order by `date` desc 
    limit 30 # the number of trading days
  ) as  d on d.`date` = pt.`date`
where code in ("AAA","BBB","CCC")
group by code
order by average desc;

如果子选择太慢,请使用后面的一些版本。

你绝对应该制作一个包含日历日的表格,并且他们会得到一个标记交易日的列。如果它们还包含30天前和90天前的参考,那将会容易得多。

 create table calendar_days 
 (
    id int(11) not null auto_increment primary key, 
    calday date not null, 
    is_trading tinyint, 
    trading_before_30 date, 
    trading_before_90 date
 );

然后变得容易:

select pt.stockname, sum(pt.closing_price) / count(*) as avg_close
from calendar_days d
inner join pricetable pt on pt.day between d.calday and d.trading_before_30
where d.calday = '2015-08-15'
group by pt.stockname;

您可以从库存表中轻松填写该日历日表。

编辑:这样您就可以在第一天的请求中填写它,假设交易日在此表中。

insert into calendar_days (calday, is_trading) 
select distinct day, 1
from pricetable pt 
where pt.day > (select max(calday from calendar_days);

update calendar_days d1 
inner join calendar_days d2 on d2.nr = d1.nr - 29
set d1.trading_before_30 = d2.calday 
where d1.trading_before_30 is null;

您当然可以尝试动态构建您的stockprice表中最近30个交易日的列表,但该表每天有很多条目,因此这将是一个不必要的减慢您的查询 - 当天更改很少,每天只有一次。

您甚至可以在截止日期表中添加触发器,以便在每个插页上检查日历天是否需要重新填充。

没有该表的版本如下所示:

drop temporary table if exists tmp_days;
create temporary table tmp_days (tradingday date not null primary key);
insert into tmp_days 
select distinct `day` 
from pricetable 
where day <= '2015-08-15'
order by day desc limit 30;

然后

select pt.stockname, sum(pt.price) / count(*) as average
from pricetable pt 
inner join tmp_days d on d.tradingday = pt.day;

临时表只能在一个连接中显示。

答案 1 :(得分:0)

作为起点,请参阅https://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_date-add这些功能。应该像(未经测试):

SELECT `date`, ticker, avg(`close`) from TRADES where
date <= '2015-09-01' and date >= DATE_SUB('2015-09-01', INTERVAL 30 DAY)
GROUP BY ticker