简体   繁体   English

MYSQL:30天移动平均股价

[英]MYSQL: 30 day moving average stock prices

Objective to select the average closing price of last 30 trading days for each stock, based on input date NOT latest date 目标根据输入日期而非最新日期选择每只股票最近30个交易日的平均收盘价

Given that; 鉴于;

1) If the input date is 2015-09-18, to select average closing price of last 30 TRADING days, eg (2015-09-18, 2015-09-17, 2015-09-16,...30 days) 1)如果输入日期为2015-09-18,则选择最近30个交易日的平均收盘价,例如(2015-09-18、2015-09-17、2015-09-16,... 30天)

2) If the input date is 2015-09-01, to select average closing price of last 30 TRADING days, eg (2015-09-01, 2015-09-31, 2015-09-28,...30 days) 2)如果输入日期为2015-09-01,则选择最近30个交易日的平均收盘价,例如(2015-09-01,2015-09-31,2015-09-28,... 30天)

3) Table columns: ticker | 3)表格栏:股票行情| code | 代码 date | 日期| open | 打开 high | 高| low | 低| close | 关闭| volume 体积

4) Table contains records for only TRADING days, weekends and holidays are excluded 4)该表仅包含交易日,周末和节假日的记录

5) For each stock, there are thousands of days of records, but we just want the 30 Day MA at any given point in time 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

EDIT This version should be flexible and I hope not too slow. 编辑这个版本应该很灵活,我希望不要太慢。 Since no idea what means what in your table and how the table is called, I assume a table pricetable with code='AAA','BBB' and so and close meaning the price. 由于不知道什么在您的表中意味着什么以及如何调用该表,因此我假设一个表价格表的代码为“ AAA”,“ BBB”等,而close表示价格。 Your given date should be '2015-09-12' here. 您的给定日期应为“ 2015-09-12”。 Replace '2015-09-12' whith whatever you like. 随心所欲地替换“ 2015-09-12”。

30 should be the number of trading days. 30个交易日应该是。 Replace by whatever you want in 'limit 30'. 用“限制30”中的任何内容替换。

ticker | 股票| code | 代码 date | 日期| open | 打开 high | 高| low | 低| close | 关闭| volume 体积

TRY THIS VERSION 尝试此版本

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;

Use some of the latter versions if the subselect get too slow. 如果子选择太慢,请使用某些后者版本。

You definitely should make a table with calendar days, and they get a column to mark trading days. 您绝对应该制作一个带有日历天的表格,并且它们会出现一个列来标记交易日。 It would be much easier if they also contain a reference to the 30-day-before and the 90-day-before. 如果它们还包含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
 );

Then it gets easy: 然后变得容易:

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;

You can fill that calendar day table quite easy from your stock table. 您可以从库存表中轻松填写该日历日表。

EDIT: this way you can fill it at first requests of day, assuming that only trading days are in this table. 编辑:这样,您可以在一天的第一个请求时填写该表格,假设此表中交易日。

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;

You could of course try to dynamically construct a list of the last 30 trading days out of your stockprice table, but that table has many many entries per day, so that would be a unneccessary slow down of your query - the day changes very seldom, just once every day. 当然,您可以尝试从股价表中动态构建最近30个交易日的列表,但是该表每天都有很多条目,因此这会不必要地减慢查询速度-日期很少更改,每天一次。

You could even add a trigger to your closing day table so that on every insert it will check if calendar days are to be refilled. 您甚至可以在收盘日表中添加一个触发器,以便在每次插入时都会检查是否要补充日历日。

A version without that table would look like: 没有该表的版本如下所示:

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;

and then 接着

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

The temp-table will be only visible in one connection. 临时表仅在一个连接中可见。

As a starting point see https://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_date-add these functions. 作为起点,请参见https://dev.mysql.com/doc/refman/5.0/en/date-and-time-functions.html#function_date-添加这些功能。 Should be like (not tested): 应该像(未经测试):

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM