每月价格数据:开盘价,最高价,最低价和收盘价

时间:2016-04-15 12:11:28

标签: sqlite

我有一个如下构建的表:

dpTicker    dpDate      dpOpen      dpHigh      dpLow       dpClose     dpVolume    dpAdjClose  dpCreated            dpModified
GLE.PA      2016-02-01  35.39       35.455      34.375      34.785      2951300     34.785      2016-02-06 13:33:40  2016-02-06 13:33:40
GLE.PA      2016-02-02  34.515      34.565      32.165      32.575      7353600     32.575      2016-02-06 13:33:40  2016-02-06 13:33:40
GLE.PA      2016-02-03  32.4        32.495      30.885      31.6        7007000     31.6        2016-02-06 13:33:40  2016-02-06 13:33:40
GLE.PA      2016-02-04  32.075      32.38       30.67       31.98       8181000     31.98       2016-02-06 13:33:40  2016-02-06 13:33:40
GLE.PA      2016-02-05  32.55       33.0        31.86       32.11       7056700     32.11       2016-02-06 13:33:40  2016-02-06 13:33:40

数据是每日股价信息,该表包含数百个代码(例如GLE.PA)。每个股票代码(例如GLE.PA)都有一个每个“营业日”的条目。

我的目标是从每日价格数据表中查询每月价格摘要。月度数据构建如下:

  1. 月份开放:dpOpen在该月的第一个工作日;
  2. 月高:月的最大值(dpHigh);
  3. 月份低:月份的最小值(dpLow);
  4. 月份关闭:dp在该月的最后一个营业日期关闭。
  5. 我设法通过在SQLite3中使用以下查询来查询特定月份的数据:

    SELECT
        strftime ('%Y-%m', dpDate) AS month,    
        (SELECT dpOpen
            FROM DailyPrices
            WHERE dpTicker = 'GLE.PA'
            AND dpDate = 
            (SELECT min(dpDate)
            FROM DailyPrices
            WHERE strftime('%Y%m', dpDate) = '201509'   
            )
        ) AS Open,
        max(dpHigh) AS High,
        min (dpLow) AS Low,
        (SELECT dpClose
            FROM DailyPrices
            WHERE dpTicker = 'GLE.PA'
            AND dpDate = 
            (SELECT max(dpDate)
            FROM DailyPrices
            WHERE strftime('%Y%m', dpDate) = '201509'   
            )
        ) AS Close
    FROM DailyPrices
    WHERE dpTicker ='GLE.PA'
    AND strftime('%Y%m', dpDate) = '201509';
    

    查询的输出如下:

    bash-3.2$ sqlite3 myShares < month.sql
    month       Open        High        Low         Close     
    ----------  ----------  ----------  ----------  ----------
    2015-09     42.72       44.07       37.25       39.85     
    bash-3.2$ 
    

    通过以下查询,我设法生成高和低的月度概览:

    SELECT  
        strftime('%Y-%m', dpDate) AS Month,
        max(dpHigh) AS High,
        min(dpLow) AS Low
    FROM DailyPrices
    WHERE dpTicker ='GLE.PA'
    GROUP BY strftime('%Y%m', update);
    

    输出的快照如下所示:

    bash-3.2$ sqlite3 myShares < monthly.sql
    Month       High        Low       
    ----------  ----------  ----------
    2000-01     219.32      184.346   
    2000-02     206.43      181.977   
    2000-03     210.411     181.503   
    2000-04     221.405     197.805   
    2000-05     226.239     55.9199
    ...
    

    通过以下查询,我设法提取正确的Open和类比正确的Close数据:

    SELECT 
        strftime('%Y-%m', dpDate) AS Month, 
        dpOpen AS Open
    FROM DailyPrices
    WHERE dpTicker = 'GLE.PA' 
    AND dpDate IN
        (SELECT min(dpDate)
            FROM DailyPrices
            WHERE dpTicker = 'GLE.PA'
            GROUP BY strftime('%Y%m', dpDate)
        );
    

    输出的快照如下:

    bash-3.2$ sqlite3 myShares < Open.sql
    Month       Open      
    ----------  ----------
    2000-01     218.846   
    2000-02     200.269   
    2000-03     206.525   
    2000-04     201.312   
    2000-05     215.908 
    ...
    

    我正在努力将查询month.sql和open.sql组合到一个查询中以获得以下输出:

    Month    Open    High    Low    Close
    -------  -----   -----   -----  -----
    2015-01  42.79   42.79   33.69  35.18
    2015-02  35.39   35.46   26.61  32.42
    2015-03  32.32   37.65   31.93  32.48
    ...
    

    任何帮助解决这个问题的人都会非常感激。 最诚挚的问候

2 个答案:

答案 0 :(得分:1)

第一个查询涉及搜索的特定月份有三个位置。让我们删除子查询中的两个出现;这需要使用别名,以便我们可以按名称引用同一个表的其他实例:

SELECT
    strftime ('%Y-%m', dpDate) AS month,    
    (SELECT dpOpen
        FROM DailyPrices
        WHERE dpTicker = 'GLE.PA'
        AND dpDate = 
        (SELECT min(dpDate)
        FROM DailyPrices AS DP2
        WHERE strftime('%Y%m', DP2.dpDate) = strftime('%Y%m', DP1.dpDate)
        )
    ) AS Open,
    max(dpHigh) AS High,
    min (dpLow) AS Low,
    (SELECT dpClose
        FROM DailyPrices
        WHERE dpTicker = 'GLE.PA'
        AND dpDate = 
        (SELECT max(dpDate)
        FROM DailyPrices AS DP2
        WHERE strftime('%Y%m', DP2.dpDate) = strftime('%Y%m', DP1.dpDate)
        )
    ) AS Close
FROM DailyPrices AS DP1
WHERE dpTicker ='GLE.PA'
AND strftime('%Y%m', dpDate) = '201509';

现在只有最外层的查询需要知道月份,我们可以简单地用GROUP BY替换过滤器:

SELECT
    strftime ('%Y-%m', dpDate) AS month,    
    (...) AS Open,
    max(dpHigh) AS High,
    min (dpLow) AS Low,
    (...) AS Close
FROM DailyPrices
WHERE dpTicker ='GLE.PA'
GROUP BY strftime('%Y%m', dpDate);

请注意,使用ORDER BY / LIMIT:

可以简化打开/关闭子查询
(SELECT dpOpen
 FROM DailyPrices
 WHERE dpTicker = 'GLE.PA'
   AND ... dpDate ...
 ORDER BY dpDate ASC
 LIMIT 1) AS Open

答案 1 :(得分:0)

谢谢CL !!对于SQLite新手来说,这是一个很好的学习方法,特别是对于使用ALIASES。

您的建议通常会产生良好的效果,但是,在运行几个测试运行时,我注意到以下样式的偶然错误:

bash-3.2$ sqlite3 myShares < tst.sql
month       Open        High        Low         Close     
----------  ----------  ----------  ----------  ----------
2006-03     75.4675     76.5852     70.4136     74.4956   
2006-04     75.0787     75.9048     70.5108     72.7948   
2006-05                 77.0225     68.5184     70.7538   
2006-06     70.5594     73.4751     64.7767     72.7462   
2006-07     72.5518     75.2245     68.2269     74.0582   
bash-3.2$

您可以注意到,2006年5月份的公开价格缺失。我确认数据确实存在:

bash-3.2$ sqlite3 myShares < test.sql
dpTicker    dpDate      dpOpen      dpHigh      dpLow       dpClose     dpVolume    dpAdjClose  dpCreated            dpModified         
----------  ----------  ----------  ----------  ----------  ----------  ----------  ----------  -------------------  -------------------
BNP.PA      2006-04-26  72.0173     73.1835     72.0173     72.892      2623400     48.8861     2015-12-08 12:04:22  2015-12-08 12:04:22
BNP.PA      2006-04-27  73.8153     74.0096     72.5032     73.6209     6001400     49.375      2015-12-08 12:04:22  2015-12-08 12:04:22
BNP.PA      2006-04-28  73.4751     73.9611     72.6976     72.7948     4133300     48.8209     2015-12-08 12:04:22  2015-12-08 12:04:22
BNP.PA      2006-05-02  72.5518     73.5723     72.3574     73.2807     3085400     49.1468     2015-12-08 12:04:22  2015-12-08 12:04:22
BNP.PA      2006-05-03  73.8639     74.0096     72.5518     72.649      3290400     48.7231     2015-12-08 12:04:22  2015-12-08 12:04:22
BNP.PA      2006-05-04  72.892      73.5237     72.2602     73.3779     3640300     49.212      2015-12-08 12:04:22  2015-12-08 12:04:22
BNP.PA      2006-05-05  73.6209     74.8357     73.4751     74.7872     3255600     50.1572     2015-12-08 12:04:22  2015-12-08 12:04:22
bash-3.2$

对于SQLite数据库中的每个代码,我通常在16年内有大约4个错误。

就我的SQLite新手知识而言,表中的数据很好。

任何想法为什么偶尔会跳过摘要记录?一般来说,差价发生在开盘价上,但也会不时出现在收盘价上。

致以最诚挚的问候,

GAM

对于记录,以下是我执行的查询

SELECT
    strftime ('%Y-%m', dpDate) AS month,    
    (SELECT dpOpen
     FROM DailyPrices
     WHERE dpTicker = 'BNP.PA'
       AND dpDate = 
        (SELECT min(dpDate)
        FROM DailyPrices AS DP2
        WHERE strftime('%Y%m', DP2.dpDate) = strftime('%Y%m', DP1.dpDate)
        )
     ORDER BY dpDate ASC
     LIMIT 1) AS Open,
    max(dpHigh) AS High,
    min (dpLow) AS Low,
    (SELECT dpClose
        FROM DailyPrices
        WHERE dpTicker = 'BNP.PA'
        AND dpDate = 
        (SELECT max(dpDate)
        FROM DailyPrices AS DP2
        WHERE strftime('%Y%m', DP2.dpDate) = strftime('%Y%m', DP1.dpDate)
        )
    ) AS Close
FROM DailyPrices AS DP1
WHERE dpTicker ='BNP.PA'
AND strftime('%Y-%m', dpDate) > '2006-02'
AND strftime('%Y-%m', dpDate) < '2006-08'
GROUP BY strftime('%Y-%m', dpDate);