从SQLite中的不完整交易时间序列获取每日股票投资组合

发布于 2025-02-12 10:26:14 字数 3506 浏览 1 评论 0原文

我试图为以下问题提出SQL解决方案。我有一张桌子,可以保存库存交易。由于不每天进行交易,表中的时间序列是不完整的。

餐桌交易

日期仓库股票收购或出售股票
2022-02-01AMSFT购买100
2022-02-04BAAPL购买20
2022-02-05AMSFT卖出80
2022-02-02APG A PG购买50
2022-02-02-08PG购买30
2022-02-08APG购买20
2022-02-09APG购买50
2022-02-10BT购买10

现在,我想写一个SQL语句,这使我每天的每日份额是自2022-02-01以来每天的股票。预期的结果是。

日期仓库股票股票计数
2022-02-01AMSFT100
2022-02-02AMSFT100
2022-02-03AMSFT100
2022-02-04AMSFT100
2022-02-02-04BAAPL20
2022-02-02-02-02-05AMSFT20
2022-02-05BAAPL20
2022-02-06AMSFT20
2022-02-06BAAPL20
2022-02-07AMSFT20
2022-02-07APG50
2022-02-07BAAPL20
2022-02-08APG50
20222-02-02
​02-08APG100
2022-02-08BAAPL50
2022-02-09aMSFT20
2022-02-09APG150
2022-02-09BAAPL50
2022-02-10AMSFT20
2022-02-10APG150
2022-02-10BAAPL AAPL50
2022-2022-02-10B T 10 BT10

到目前为止,我所做的事情:

  • a:在2022-02-01和当前日期之间获取所有日期的列表(例如2022-02-10)。
  • B:按仓库和按日期订购的股票列出的股票列的运行总额。
  • 一个左联接B
WITH RECURSIVE dates(date) AS (
  VALUES('2022-02-01')
  UNION ALL
  SELECT date(date, '+1 day')
  FROM dates
  WHERE date < DATE()
)
SELECT dt.Date
    , tr.Date
    , tr.Ticker
    , tr.Shares AS [Share Count]
FROM dates dt
LEFT JOIN (
    SELECT Date
        , Depot
        , Ticker
        , SUM(shares) OVER (PARTITION BY Depot, Ticker ORDER BY Date ROWS UNBOUNDED PRECEDING) AS Shares
    FROM TRANSACTION
    ORDER BY Depot, Date, Ticker
) ON (
    tr.Date <= dt.Date
)
ORDER BY dt.Date, Ticker

似乎没有解决问题,因为运行总计无法正确汇总日期行。结果看起来更像合成日期表和事务表之间的一种交叉连接。

我在哪里错了?有人解决了我的问题吗?

多谢!

I'm trying to come up with an SQL solution for the following problem. I have a table in which stock transactions are saved. As transactions don't occur on a daily basis the time series in the table is incomplete.

Table TRANSACTION

DateDepotTickerBuy or SellShares
2022-02-01AMSFTBUY100
2022-02-04BAAPLBUY20
2022-02-05AMSFTSELL80
2022-02-07APGBUY50
2022-02-08APGBUY30
2022-02-08APGBUY20
2022-02-09APGBUY50
2022-02-10BTBUY10

Now I would like to write a SQL statement that gives me the daily share count per depot an ticker for every day since 2022-02-01. The expected result would be this.

DateDepotTickerShare Count
2022-02-01AMSFT100
2022-02-02AMSFT100
2022-02-03AMSFT100
2022-02-04AMSFT100
2022-02-04BAAPL20
2022-02-05AMSFT20
2022-02-05BAAPL20
2022-02-06AMSFT20
2022-02-06BAAPL20
2022-02-07AMSFT20
2022-02-07APG50
2022-02-07BAAPL20
2022-02-08APG50
2022-02-08AMSFT20
2022-02-08APG100
2022-02-08BAAPL50
2022-02-09AMSFT20
2022-02-09APG150
2022-02-09BAAPL50
2022-02-10AMSFT20
2022-02-10APG150
2022-02-10BAAPL50
2022-02-10BT10

What I'v done so far:

  • A: Getting a list of all dates between 2022-02-01 and the current date (e.g. 2022-02-10).
  • B: Getting a running total over the shares column by depot and ticker ordered by date.
  • A Left join B
WITH RECURSIVE dates(date) AS (
  VALUES('2022-02-01')
  UNION ALL
  SELECT date(date, '+1 day')
  FROM dates
  WHERE date < DATE()
)
SELECT dt.Date
    , tr.Date
    , tr.Ticker
    , tr.Shares AS [Share Count]
FROM dates dt
LEFT JOIN (
    SELECT Date
        , Depot
        , Ticker
        , SUM(shares) OVER (PARTITION BY Depot, Ticker ORDER BY Date ROWS UNBOUNDED PRECEDING) AS Shares
    FROM TRANSACTION
    ORDER BY Depot, Date, Ticker
) ON (
    tr.Date <= dt.Date
)
ORDER BY dt.Date, Ticker

That doesn't seem to do the trick as the running total does not properly aggregate the date rows. The result looks more like a kind of cross join between the synthetic date table and the transaction table.

Where am I wrong? Has anyone a solution for my problem?

Thanks a lot!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

隱形的亼 2025-02-19 10:26:14

您快到了,只是在扩展您的想法。
我在以下示例中有硬编码的结束日期,但是可以根据要求更改。

日期CTE只是在所需范围内建立日期。
在下一个子查询(T1)中,还有另外两个列 - 最大日期和列S_SHARES的列MD,以根据购买(添加)(添加)或减去出售的股票运行总和。

然后,我们从日期最大日期(列MD)和原始日期之间的两个集合值中选择。

WITH RECURSIVE dates(date1) AS (
  select date('2022-02-01')
  UNION ALL
  SELECT  date(date1, '+1 day')
  FROM dates
  WHERE date1 <  date('2022-02-10')
) select d.date1,depot,ticker, s_shares 
from dates d, 
(select date1, 
case 
coalesce(lead(date1) over (partition by depot, ticker order by date1),0) 
when 0 then date('2022-02-10', '+1 day')
else lead(date1) over (partition by depot, ticker order by date1) 
end md,
depot, ticker, buyorsell,
sum(case when buyorsell = 'SELL' then -(Shares) else Shares end) 
over (partition by depot, ticker order by Date1 ROWS UNBOUNDED PRECEDING) s_shares
from tic) t1
where d.date1< t1.md
and d.date1>= t1.date1
order by depot, ticker, d.date1;

请参阅小提琴

You are almost there, just expanded on your idea.
I have hard-coded end date in below example, but that can be changed as per requirement.

The dates CTE is just building dates within the needed range.
In the next sub-query (t1), there are two more columns added - column md for max date and column s_shares to get a running sum of shares based on if share is bought (added) or subtracted if sold.

We then select from the two sets values between dates max date (column md) and original date.

WITH RECURSIVE dates(date1) AS (
  select date('2022-02-01')
  UNION ALL
  SELECT  date(date1, '+1 day')
  FROM dates
  WHERE date1 <  date('2022-02-10')
) select d.date1,depot,ticker, s_shares 
from dates d, 
(select date1, 
case 
coalesce(lead(date1) over (partition by depot, ticker order by date1),0) 
when 0 then date('2022-02-10', '+1 day')
else lead(date1) over (partition by depot, ticker order by date1) 
end md,
depot, ticker, buyorsell,
sum(case when buyorsell = 'SELL' then -(Shares) else Shares end) 
over (partition by depot, ticker order by Date1 ROWS UNBOUNDED PRECEDING) s_shares
from tic) t1
where d.date1< t1.md
and d.date1>= t1.date1
order by depot, ticker, d.date1;

Refer to the fiddle here.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文