为什么不平仓?Quantstrat软件包

9fkzdhlc  于 2023-10-13  发布在  其他
关注(0)|答案(2)|浏览(123)

我有一个简单的信号策略
0 =关闭所有头寸
1 =开盘买入(如果有,则平仓卖出)
-1=打开卖出(如果有买入,则关闭买入)
交易期间只能开设一个头寸
下面是生成假数据和计算信号的代码

require(quantstrat)

set.seed(1)
fake_data <- rnorm(100) |> cumsum() |> xts(order.by=as.POSIXct(x=60*1:100, origin='2021-07-01'))
colnames(fake_data) <-'Close'

make_seq <- function() sample(c(-1,0,1),size=1) |> rep(sample(3:20,1))
fake_data$signal <- lapply(1:50,\(x) make_seq())  |> unlist() |> tail(n = length(fake_data))

# signal 
chart_Series(fake_data)
abline(h=0)


fake_data$buy_open <- 0
fake_data$buy_close <- 0
fake_data$sell_open <- 0
fake_data$sell_close <- 0

S <- fake_data$signal |> coredata() |> as.vector()
for(i in 2:nrow(fake_data)){
  if(S[i-1]!=  1 & S[i]==  1) fake_data$buy_open[i]   <- 1
  if(S[i-1]==  1 & S[i]!=  1) fake_data$buy_close[i]  <- 1
  if(S[i-1]!= -1 & S[i]== -1) fake_data$sell_open[i]  <- 1
  if(S[i-1]== -1 & S[i]!= -1) fake_data$sell_close[i] <- 1
}

接下来我创建交易规则

rm.strat(strat.st)

strat.st <- "FAKESTRAT"
currency("USD")
stock("fake_data",currency = "USD")
initPortf(strat.st, symbols="fake_data")
initEq<-1000
initAcct(strat.st, portfolios=strat.st, initEq=initEq)
initOrders(portfolio=strat.st)
strategy(name=strat.st,store=TRUE)

addPosLimit("FAKESTRAT", "fake_data", maxpos = 1, timestamp = start(fake_data)-1)

# enterLong  exitLong

add.rule(strat.st,"ruleSignal", 
         arguments=list(sigcol="buy_open",
                        sigval=TRUE,
                        orderqty=1,
                        ordertype='market', 
                        orderside='long',
                        osFUN = osMaxPos),
         type="enter",
         label="enterLong"
)

add.rule(strat.st,"ruleSignal", 
         arguments=list(sigcol="buy_close",
                        sigval=TRUE,
                        orderqty="all",
                        ordertype='market', 
                        orderside='long'),
         type="exit",
         label="exitLong"
)

# enterShort  exitShort

add.rule(strat.st,"ruleSignal", 
         arguments=list(sigcol="sell_open",
                        sigval=TRUE,
                        orderqty=-1,
                        ordertype='market', 
                        orderside='short',
                        osFUN = osMaxPos),
         type="enter",
         label="enterShort"
)

add.rule(strat.st,"ruleSignal", 
         arguments=list(sigcol="sell_close",
                        sigval=TRUE,
                        orderqty="all",
                        ordertype='market', 
                        orderside='short'),
         type="exit",
         label="exitShort"
)



out<-applyStrategy(strat.st , portfolios=strat.st, verbose=T)
updatePortf(strat.st)
book <- getOrderBook(portfolio=strat.st)

....

print(book)

book
$FAKESTRAT
$FAKESTRAT$fake_data
                    Order.Qty      Order.Price Order.Type Order.Side Order.Threshold
2021-07-01 03:24:00        -1 3.59680448297358     market      short            <NA>
2021-07-01 03:40:00       all 3.68104715087989     market      short            <NA>
2021-07-01 03:40:00         1 3.68104715087989     market       long            <NA>
2021-07-01 03:54:00        -1 4.02025008047271     market      short            <NA>
2021-07-01 04:12:00       all 10.7346453103169     market      short            <NA>
2021-07-01 04:35:00        -1 13.8781211399328     market      short            <NA>
                    Order.Status    Order.StatusTime Prefer Order.Set Txn.Fees       Rule
2021-07-01 03:24:00       closed 2021-07-01 03:25:00             <NA>        0 enterShort
2021-07-01 03:40:00     replaced 2021-07-01 03:40:00             <NA>        0  exitShort
2021-07-01 03:40:00       closed 2021-07-01 03:41:00             <NA>        0  enterLong
2021-07-01 03:54:00       closed 2021-07-01 03:55:00             <NA>        0 enterShort
2021-07-01 04:12:00       closed 2021-07-01 04:13:00             <NA>        0  exitShort
2021-07-01 04:35:00       closed 2021-07-01 04:36:00             <NA>        0 enterShort
                    Time.In.Force
2021-07-01 03:24:00              
2021-07-01 03:40:00              
2021-07-01 03:40:00              
2021-07-01 03:54:00              
2021-07-01 04:12:00              
2021-07-01 04:35:00

我不明白为什么空仓是多头

2021-07-01 03:40:00         1 3.68104715087989     market       long

当卖出信号到达时,

2021-07-01 03:54:00        -1 4.02025008047271     market      short
dgjrabp2

dgjrabp21#

我不明白这是如何工作的,但答案就在replace变量中。
您所需要做的就是将其包含在开仓和平仓规则中
replace=TRUE用于关闭位置
replace=FALSE用于打开位置

# enterLong  exitLong

add.rule(strat.st,"ruleSignal", 
         arguments=list(sigcol="buy_open",
                        sigval=TRUE,
                        replace=FALSE,
                        orderqty=1,
                        ordertype='market', 
                        orderside='long',
                        osFUN = osMaxPos),
         type="enter",
         label="enterLong"
)

add.rule(strat.st,"ruleSignal", 
         arguments=list(sigcol="buy_close",
                        sigval=TRUE,
                        replace=TRUE,
                        orderqty="all",
                        ordertype='market', 
                        orderside='long'),
         type="exit",
         label="exitLong"
)

销售规则也需要这样做

book$FAKESTRAT$fake_data[,c(1,4,11)]
                    Order.Qty Order.Side       Rule
2021-07-01 03:24:00        -1      short enterShort
2021-07-01 03:40:00       all      short  exitShort
2021-07-01 03:40:00         1       long  enterLong
2021-07-01 03:54:00       all       long   exitLong
2021-07-01 03:54:00        -1      short enterShort
2021-07-01 04:12:00       all      short  exitShort
2021-07-01 04:35:00        -1      short enterShort
hgtggwj0

hgtggwj02#

每个用于进入(enterLongenterShort)和退出(exitLongexitShort)位置的函数只关注其指定的操作:根据相应的信号列(buy_openbuy_closesell_opensell_close)进入或退出多头或空头头寸。这些规则中没有任何机制来检查当一个新的头寸即将被打开时是否存在相反的头寸。
例如,当enterShort规则被触发时,它不会首先检查是否已经打开了需要关闭的多头头寸。它只是继续进入空头头寸。enterLong规则也是如此;它在建立多头头寸之前不会检查现有的空头头寸。
因此,在您当前的设置中,似乎没有任何逻辑可以在进入空头头寸的信号出现时关闭多头头寸,反之亦然。
如果我们将您的订单簿的这一部分视为示例:

2021-07-01 03:40:00         1 3.68104715087989     market       long
2021-07-01 03:54:00        -1 4.02025008047271     market      short

你在2021-07-01 03:40:00开了一个多头头寸,卖出信号在2021-07-01 03:54:00到达。然而,当卖出信号到来时,现有的多头头寸没有被平仓。
在您当前的设置中,您使用osMaxPos函数进行订单大小调整,以确保您一次只打开一个位置,但它不包括逻辑来 * 关闭 * 现有的相反位置。osMaxPos只查看当前位置类型(多头或空头)并限制它,但不关闭相反的类型。
您可能需要执行额外的逻辑,以便在收到进入空头头寸的信号时关闭多头头寸,反之亦然。这可能是一个自定义的订单大小函数(osFUN),在执行交易之前检查当前位置。如果当前头寸与新信号相反,则该函数需要关闭该头寸。
例如,你可以定义一个osCloseOpposite函数:

osCloseOpposite <- function(timestamp, orderqty, portfolio, symbol, ...) {
  # Close opposite position if it exists
  currentPos <- getPosQty(portfolio, symbol, timestamp)
  if (orderqty > 0 && currentPos < 0) {
    # Close existing short position
    return(-currentPos)
  } else if (orderqty < 0 && currentPos > 0) {
    # Close existing long position
    return(-currentPos)
  }
  
  # If no opposite position, apply osMaxPos logic
  return(osMaxPos(timestamp, orderqty, portfolio, symbol, ...))
}

然后将此函数用作现有规则中的osFUN

add.rule(strat.st,"ruleSignal", 
         arguments=list(sigcol="sell_open",
                        sigval=TRUE,
                        orderqty=-1,
                        ordertype='market', 
                        orderside='short',
                        osFUN = osCloseOpposite),
         type="enter",
         label="enterShort"
)

enterLong规则执行相同的操作。这样,您的自定义函数将检查现有的位置,如果它与新信号相反,则关闭它。

相关问题