所以我在R中有2个数据框。一个是需要出售的股票和数量表(SSTable),第二个是股票位于不同投资组合(PTable)的表格。除了PTable中的投资组合,库存和数量字段外,还有一个日期字段。 Ptable需要从最早的日期到最晚的日期进行排序。
我需要构建一些类型的脚本来循环遍历SSTable和PTable并告诉我从每个组合中销售哪些股票以及多少。我应该在它的末尾有2个输出表。
SSTableOP-此表应仅包含无法售出的剩余份额。
PTableOP - 此表是我的执行表,表明从哪个投资组合中销售哪种股票以及以哪种顺序出售。想按照投资组合然后自动收报机名称进行排序。这里有一个注释,我在任何投资组合中的销售量都不会超过我。举个例子,如果我的SSTable表明我需要出售400单位的AAPL,但是在我的所有投资组合中我只有200个,那么它应该告诉我只出售我拥有的200个。现在SSTableOP中不应该有AAPL记录。一个重要的注意事项是,我必须首先从最近日期的投资组合中出售单位。这就是我必须出售的顺序
在我的所有合并投资组合中,我的销售额不会超过我的销售额
以下是一些示例数据以及数据框的结构
Classes ‘tbl_df’, ‘tbl’ and 'data.frame': 58 obs. of 2 variables:
$ ticker : chr
$ Units : int
Classes ‘grouped_df’, ‘tbl_df’, ‘tbl’ and 'data.frame': 1030 obs. of 4
variables:
$ Portfolio : Factor w/ 2665 levels ".
$ ticker : Factor w/ 4677 levels .
$ Units : int
$ Date : POSIXct, format:
ticker Units
APPL 400
GOOG 1700
MFC 800
PWF 200
GWG 500
SUN 600
ARIA 200
HEI 100
GEO 300
Portfolio ticker units date
HGFR 6/17 APPL 200 20/04/2017
HGFR 6/17 GOOG 800 20/04/2017
HGFR 6/17 MFC 200 20/04/2017
SDSDF14 SUN 600 22/04/2017
DFDS11 GOOG 1700 25/04/2017
DFDS11 ARIA 100 25/04/2017
SDSDF14 ARIA 100 22/04/2017
SDSDF14 GEO 50 22/04/2017
SDSDF14 HEI 50 22/04/2017
HGFR 6/17 GWG 250 20/04/2017
GDSD114 HEI 50 26/04/2017
GDSD114 GEO 150 26/04/2017
GDSD114 PWF 50 26/04/2017
ticker Units
APPL 200
MFC 600
PWF 150
GWG 250
GEO 100
答案 0 :(得分:1)
投资组合名称HGFR 6/17略有修改,以便于作为表格阅读
PTable <- read.table(header=TRUE, stringsAsFactors = FALSE, text=
"Portfolio ticker units pdate
HGFR_6/17 APPL 200 20/04/2017
HGFR_6/17 GOOG 800 20/04/2017
HGFR_6/17 MFC 200 20/04/2017
SDSDF14 SUN 600 22/04/2017
DFDS11 GOOG 1700 25/04/2017
DFDS11 ARIA 100 25/04/2017
SDSDF14 ARIA 100 22/04/2017
SDSDF14 GEO 50 22/04/2017
SDSDF14 HEI 50 22/04/2017
HGFR_6/17 GWG 250 20/04/2017
GDSD114 HEI 50 26/04/2017
GDSD114 GEO 150 26/04/2017
GDSD114 PWF 50 26/04/2017
")
SSTable <- read.table(header=TRUE, stringsAsFactors = FALSE, text=
"ticker Units
APPL 400
GOOG 1700
MFC 800
PWF 200
GWG 500
SUN 600
ARIA 200
HEI 100
GEO 300
")
library(dplyr)
library(lubridate)
# ensure a date type (date renamed to pdate)
PTable$pdate <- dmy(PTable$pdate)
# First determine actual amount that can be sold based on
# overall portfolio balances. This may not be strictly
# needed but it simplifies later logic. left join in
# case there are sell orders without any mathcing portfolios
SSTableAdjusted <- SSTable %>%
left_join(PTable %>% group_by(ticker) %>% summarize(per_ticker_portfolio_units = sum(units))) %>%
mutate(
per_ticker_sell_units = if_else(Units > per_ticker_portfolio_units, per_ticker_portfolio_units, Units),
per_ticker_unfulfilled_units = Units - per_ticker_sell_units) %>%
arrange(ticker)
# process
PTableSummary <- PTable %>%
# join in the per ticker targets
left_join(SSTableAdjusted) %>%
# arrange in date priority
arrange(pdate, Portfolio) %>%
# group by ticker to compare totals by ticker
group_by(ticker) %>%
# apply the trading logic
mutate(
cum_portfolio_units = cumsum(lag(units, default = 0)),
gap = per_ticker_sell_units - cum_portfolio_units,
to_sell = if_else(gap <= 0, 0L,
if_else(gap >= units, units,
gap)),
remaining_to_sell = Units - cumsum(to_sell)) %>%
ungroup() %>%
arrange(pdate, Portfolio, ticker)
# test conditions - all should be TRUE
sum(PTableSummary$to_sell) == sum(SSTableAdjusted$per_ticker_sell_units)
PTableSummary$to_sell <= PTableSummary$units
# make the output table (doenseparately so that PTAbleSummary can be inspected)
PTableOP <- PTableSummary %>%
select(pdate, Portfolio, ticker, units, to_sell, remaining_to_sell) %>%
arrange(pdate, Portfolio, ticker)
# pdate Portfolio ticker units to_sell remaining_to_sell
# 1 2017-04-20 HGFR_6/17 APPL 200 200 200
# 2 2017-04-20 HGFR_6/17 GOOG 800 800 900
# 3 2017-04-20 HGFR_6/17 GWG 250 250 250
# 4 2017-04-20 HGFR_6/17 MFC 200 200 600
# 5 2017-04-22 SDSDF14 ARIA 100 100 100
# 6 2017-04-22 SDSDF14 GEO 50 50 250
# 7 2017-04-22 SDSDF14 HEI 50 50 50
# 8 2017-04-22 SDSDF14 SUN 600 600 0
# 9 2017-04-25 DFDS11 ARIA 100 100 0
# 10 2017-04-25 DFDS11 GOOG 1700 900 0
# 11 2017-04-26 GDSD114 GEO 150 150 100
# 12 2017-04-26 GDSD114 HEI 50 50 0
# 13 2017-04-26 GDSD114 PWF 50 50 150
## determine the unfulfilled
SSTableOP <- SSTableAdjusted %>%
filter(per_ticker_unfulfilled_units != 0) %>%
select(ticker, per_ticker_unfulfilled_units)
# ticker per_ticker_unfulfilled_units
# 1 APPL 200
# 2 GEO 100
# 3 GWG 250
# 4 MFC 600
# 5 PWF 150