如何从单个列中的两列中的几个引号和多个出价引号中获取最小值?

时间:2016-08-22 18:09:23

标签: r dplyr tidyr quantitative-finance

我有一个数据集,其中包含3天的买入价和卖出价以及股票。以下是数据集的一部分。我还给出了样本数据集的链接,以说明问题的本质。

> dput(head(q,30))

structure(list(Date = structure(c(1471424400, 1471424400, 1471424400, 
1471424401, 1471424401, 1471424406, 1471424407, 1471424415, 1471424417, 
1471424514, 1471424527, 1471424567, 1471424576, 1471424606, 1471424607, 
1471424621, 1471424621, 1471424621, 1471424641, 1471424642, 1471424715, 
1471424715, 1471424717, 1471424717, 1471424741, 1471424741, 1471424742, 
1471424793, 1471424800, 1471424807), class = c("POSIXct", "POSIXt"
), tzone = "UTC"), Type = c("ASK", "BID", "ASK", "BID", "ASK", 
"ASK", "BID", "BID", "BID", "ASK", "ASK", "BID", "BID", "BID", 
"BID", "BID", "ASK", "BID", "BID", "BID", "BID", "BID", "BID", 
"BID", "BID", "ASK", "BID", "BID", "BID", "BID"), Price = c(1749.95, 
1611, 1683.9, 1653, 1672, 1683.9, 1653, 1654.2, 1663, 1682, 1663, 
1664.75, 1663, 1664.75, 1663, 1664.75, 1662.9, 1663, 1664.75, 
1663, 1664.75, 1663, 1664.75, 1663, 1664.75, 1662.9, 1663, 1664.75, 
1663, 1664.75)), .Names = c("Date", "Type", "Price"), class = c("tbl_df", 
"data.frame"), row.names = c(NA, -30L))


                  Date  Type   Price
                (time) (chr)   (dbl)
1  2016-08-17 09:00:00   ASK 1749.95
2  2016-08-17 09:00:00   BID 1611.00
3  2016-08-17 09:00:00   ASK 1683.90
4  2016-08-17 09:00:01   BID 1653.00
5  2016-08-17 09:00:01   ASK 1672.00
6  2016-08-17 09:00:06   ASK 1683.90
7  2016-08-17 09:00:07   BID 1653.00
8  2016-08-17 09:00:15   BID 1654.20
9  2016-08-17 09:00:17   BID 1663.00
10 2016-08-17 09:01:54   ASK 1682.00
..                 ...   ...     ...

某些时间戳有多个引号。我想估算最佳出价,并使用以下步骤最好地询问这些报价:

最佳出价流程

  • 估算时间戳的最高出价。
  • 将其与现行的最佳报价进行比较。
  • 如果它高于现行的最佳出价,那么它是最好的 出价,否则现行最佳出价是最佳出价。

最佳提问流程

  • 估算时间戳的最低要求。

  • 将其与流行的最佳问题报价进行比较。

  • 如果它低于现行最好的问题那么这是最好的问题, 否则,流行的最好的询问是最好的出价。的附录 this document包含用于此目的的SAS代码。

必需的输出结构:

数据框应该有3列(日期,最佳询价,最佳出价)。行不应该有重复的时间戳,因此,最佳出价和最佳询问应该在特定时间戳的同一行而不是在两个相邻的行中。

我尝试了什么

我不知道如何将当前时间戳的最低要求与之前时间戳的最低要求进行比较。因此,下面的代码只给出了时间戳的最低要求。

library(dplyr)
library(tidyr)
library(reshape2)

m.q<- head(q,30) %>% 
  gather(variable, value, -(Date:Type)) %>%
  unite(temp,Type, variable) %>% 
  group_by(Date) %>% dcast(Date ~ temp, fun=min)

我得到以下内容:

> dput(m.q)
structure(list(Date = structure(c(1471424400, 1471424401, 1471424406, 
1471424407, 1471424415, 1471424417, 1471424514, 1471424527, 1471424567, 
1471424576, 1471424606, 1471424607, 1471424621, 1471424641, 1471424642, 
1471424715, 1471424717, 1471424741, 1471424742, 1471424793, 1471424800, 
1471424807), class = c("POSIXct", "POSIXt"), tzone = "UTC"), 
    ASK_Price = c(1683.9, 1672, 1683.9, Inf, Inf, Inf, 1682, 
    1663, Inf, Inf, Inf, Inf, 1662.9, Inf, Inf, Inf, Inf, 1662.9, 
    Inf, Inf, Inf, Inf), BID_Price = c(1611, 1653, Inf, 1653, 
    1654.2, 1663, Inf, Inf, 1664.75, 1663, 1664.75, 1663, 1663, 
    1664.75, 1663, 1663, 1663, 1664.75, 1663, 1664.75, 1663, 
    1664.75)), .Names = c("Date", "ASK_Price", "BID_Price"), row.names = c(NA, 
-22L), class = "data.frame")

                 Date ASK_Price BID_Price
1 2016-08-17 09:00:00    1683.9    1611.0
2 2016-08-17 09:00:01    1672.0    1653.0
3 2016-08-17 09:00:06    1683.9       Inf
4 2016-08-17 09:00:07       Inf    1653.0
5 2016-08-17 09:00:15       Inf    1654.2
6 2016-08-17 09:00:17       Inf    1663.0
[...]

请注意以下问题:

  1. bid和ask都有一些时间戳的值,但它们显示在相邻的行中。
  2. 函数min()正在应用于bid,因为我没有在dcast函数中仅对ask和max同时执行min的同时执行min。
  3. 而不是&#34; Inf&#34;在单元格中,如果时间戳没有出价或询问值,则应为NA。
  4. 这是我的data set

    这是涉及R编码的问题。我不知道SAS和R的初学者 (提前感谢您的建设性意见和答案,随时改进我的帖子。)

1 个答案:

答案 0 :(得分:2)

这可以使用dplyrzoo个包来完成。

使用dplyr查找每个时间戳的最低或最高价格(取决于我们是在查看BID还是ASK值),然后按&#34; Type&#34;并按日期排列汇总值。从这里开始,我们使用zoo::rollapply计算滚动最小值或滚动最大值,具体取决于Type是ASK还是BID。

library(dplyr)
library(zoo)

data.new <- group_by(data.stock, Date, Type) %>% 
    summarize(price = ifelse(Type[1] == 'ASK', min(Price), max(Price))) %>% 
    ungroup() %>% 
    group_by(Type) %>% 
    arrange(Type, Date) %>% 
    mutate(change = ifelse(Type == 'ASK',
                           rollapply(price, 1:length(price), min, align = 'right'),
                           rollapply(price, 1:length(price), max, align = 'right')
                           ))

输出:

                  Date  Type  price change
                <time> <chr>  <dbl>  <dbl>
1  2016-08-17 09:00:00   ASK 1683.9 1683.9
2  2016-08-17 09:00:01   ASK 1672.0 1672.0
3  2016-08-17 09:00:06   ASK 1683.9 1672.0
4  2016-08-17 09:01:54   ASK 1682.0 1672.0
5  2016-08-17 09:02:07   ASK 1663.0 1663.0
6  2016-08-17 09:03:41   ASK 1662.9 1662.9
7  2016-08-17 09:05:41   ASK 1662.9 1662.9
8  2016-08-17 09:00:00   BID 1611.0 1611.0
9  2016-08-17 09:00:01   BID 1653.0 1653.0
10 2016-08-17 09:00:07   BID 1653.0 1653.0
# ... with 16 more rows

因此,当我们向下移动时间戳时,滚动最小值(或最大值)将被保留。作为额外的奖励,这将永远不会产生InfNA值。

以下是dplyr正在做的事情的逐行细分:

group_by(data.stock, Date, Type) %>% 

这告诉dplyr根据日期和类型的组合获取股票价格数据并将其切割成子组。然后,我们将后续操作应用于这些子组(参见&#34; Split-Apply-Combine&#34;哲学)。所有后续操作都在子组上执行,就好像它们是分开的一样。 %>%符号&#34;管道&#34; group_by命令的输出。到下一个命令(参见magrittr包)。

summarize(price = ifelse(Type[1] == 'ASK', min(Price), max(Price))) %>% 

这将计算日期和类型的每个唯一组合的摘要(在上面的group_by行中建立)。如果Type为&#34; ASK&#34;,我们应该计算价格的最小值。否则我们计算最大值。

ungroup() %>% 
group_by(Type) %>% 

这些行告诉dplyr重置分组变量,因为我们不再希望按个别日期分组。

arrange(Type, Date) %>% 

为了安全起见,我按类型和日期arrange数据框,以确保所有值都按时间顺序排列。

mutate(change = ifelse(Type == 'ASK',
                       rollapply(price, 1:length(price), min, align = 'right'),
                       rollapply(price, 1:length(price), max, align = 'right')
                       ))

最后,最复杂的一行。这里我们使用dplyr::mutate创建一个存储滚动操作结果的列。如果类型为&#34; ASK&#34;,我们将滚动最小值应用于价格列。如果不是,我们应用滚动最大值。滚动最小值/最大值的结果存储在名为&#34;更改&#34;的新列中。 zoo包使这些类型的&#34;滚动&#34;操作更容易执行。