将国库券价格(32位,第64位,第128位)转换为小数

时间:2013-11-29 01:13:56

标签: r string-matching

我希望将美国国债期货价格转换为小数(所以127-01 + = 127 + 1/32 + 1/64,以及127-01 1/4 = 127 + 1/32 + 1/128等) 。

我在一些分数存在的情况下取得了一些成功,但是当一个分数没有跟随大数字时我失败了。

失败的原因是strsplit没有返回NA或空对象 - 因此比特的顺序被敲掉了,结果后来的分数都是错误的。

这是我的情况:

ty1 <- c("127-03", "126-31", "126-31+", "127-04+", "127-02+", "127-00+")
ty2 <- c("127-03", "126-31", "127-04+", "127-02+", "127-00+", "127", 
         "127-01 1/4", "128-01 3/4")

ty1_dec <- c(127+3/32, 126+31/32, 126+31/32+1/64, 127+4/32+1/64, 
             127+2/32+1/64, 127+0/32+1/64)
ty2_dec <- c(127+3/32, 126+31/32, 127+04/32+1/64, 127+2/32+1/64, 
             127+0/32+1/64, 127, 127+1/32+0/64+1/128, 128+1/32+1/64+1/128) 

tFrac2Dec <-function(x){
    hyphSplit <- strsplit(x, "-")
    splitMatx <- matrix(unlist(hyphSplit), ncol=2, byrow=TRUE)
    fracs <- t(apply(splitMatx[,2, drop=F], 1, function(X) substring(X, c(1,3), c(2,3))))
    splitMatx[,2] <-  (as.numeric(fracs[,1]) + ifelse(fracs[,2] == "+", 0.5, 0))/32
    fracEval <- function(y){
        eval(parse(text=paste(y[1], "+", y[2])))
    }
    apply(splitMatx,1,fracEval)
}

所有内容适用于ty1,因为所有价格都有-和以下分数。

R> tFrac2Dec(ty1) == ty1_dec
[1] TRUE TRUE TRUE TRUE TRUE TRUE

R> tFrac2Dec(ty1)
[1] 127.0938 126.9688 126.9844 127.1406 127.0781 127.0156

但是当价格仅 时,它就会失败。

> tFrac2Dec(ty2) == ty2_dec
Error in parse(text = paste(y[1], "+", y[2])) : 
  <text>:1:4: unexpected numeric constant
1: 01 1
       ^
In addition: Warning message:
In matrix(unlist(hyphSplit), ncol = 2, byrow = TRUE) :
  data length [15] is not a sub-multiple or multiple of the number of rows [8]

我可以看到它是由于第一个strsplit步骤,但我无法找到解决方案。我已经摆弄了一些if类型的解决方案但没有任何效果。

有一种简单的方法吗?

2 个答案:

答案 0 :(得分:1)

这样的东西?

tFrac2Dec <- function(x) {
  hyphSplit <- strsplit(x, "-")
  ch1 <- sapply(hyphSplit,`[`, 1)
  ch2 <- sapply(hyphSplit,`[`, 2)
  x32 <- as.integer(substring(ch2, 1, 2))
  x128 <- rep(0, length(ch1))
  x128[grep("\\+$", ch2)] <- 2
  x128[grep("1/4", ch2, fixed=TRUE)] <- 1
  x128[grep("3/4", ch2, fixed=TRUE)] <- 3
  dec <- x32/32 + x128/128
  dec[is.na(dec)] <- 0
  as.integer(ch1) + dec
}

tFrac2Dec(ty1)
## [1] 127.0938 126.9688 126.9844 127.1406 127.0781 127.0156
tFrac2Dec(ty2)
## [1] 127.0938 126.9688 127.1406 127.0781 127.0156 127.0000 127.0312

答案 1 :(得分:-1)

这会将十进制转换为报价价格,反之亦然

class TreasuryPriceConverter:
    """
    convert decimal formate treas ticks to treasury format
    125.50 => 125.16

    0.015625 => 0.01 tick

    and vice versa with toDecimal method
    *This class does not round output

    Works with ZT,ZF,ZN,ZB options and futures products
    """
    def __init__(self,price):
        self.price=price

    def toTick(self):

        priceFloat = float(self.price)
        settleInt = int(priceFloat)
        diff = priceFloat - settleInt
        diff = diff / 100 * 32
        settleFloat = float(settleInt) + diff
        return settleFloat

    def toDecimal(self):

        price=float(self.price)
        priceFloat = float(price)
        priceInt = int(price)
        diff = priceFloat - priceInt
        diff = diff * 100 / 32
        decPrice = float(priceInt) + diff
        return decPrice