(очень) Простая квантратная торговая модель с использованием логистической регрессии - PullRequest
0 голосов
/ 10 декабря 2018

Я играл с пакетом тестирования на истории quantstrat в R, и я хочу получить совет относительно особенно (плохой) стратегии.

Идея состоит в том, чтобы покупать, когда модель логистической регрессии говорит мнечто рынок будет расти (обозначено 1 в столбце prediction).Каждый день логистическая регрессия говорит мне, что рынок будет расти, я покупаю .orderqtf = 10 акций Google.В тот день, когда логистическая регрессия сообщает мне, что цена пойдет вниз (указано 0 в столбце prediction), мы сбрасываем все наши текущие акции в Google и начинаем снова, пока он не скажет нам покупать.

Вопросы:

Правильно ли мой код относительно того, что я описываю?

Если вы заметили, что я отстала от двух входных переменных.то есть momentum(lag(GOOG$close), n = 12)

, то есть я хочу использовать t-1 день, чтобы предсказать день t.Это тоже правильно?Я не хочу использовать какой-либо индикатор, который мог бы дать достоверные результаты для прогноза

Мне кажется, что есть некоторая кривая обучения с пакетом quantstrat, поэтому я просто хочу убедиться, что я получаюосновной правильный.

Модель:

rm(list=ls())
require(quantstrat)
require(PerformanceAnalytics)

set.seed(1234)

#setting up some initial parameters for the quantstrat trading model
initDate="2007-01-01"
from <- "2017-01-01"
to <- "2018-12-01"
init_equity <- 1000
adjustment <- TRUE

.orderqty <- 10
.txnfees <- -10

currency('USD')
Sys.setenv(TZ="UTC")

#Collect the data
symbols <- c('GOOG')
getSymbols(symbols, from=from, to=to, src="yahoo", adjust=TRUE)  

colnames(GOOG) <- c("open", "high", "low", "close", "volume", "adjusted")

# create the dependent variable for a logistic regression
GOOG$direction <- with(GOOG, ifelse(close >= open, 1, 0))

#create two basic input variables - lagged
GOOG$rsi <- RSI(lag(GOOG$close), nFast=14, nSlow = 26, nSig = 9, maType = SMA)
GOOG$momentum <- momentum(lag(GOOG$close), n = 12)

GOOG <- GOOG[complete.cases(GOOG), ] 

# create a training and test set
train_date <- nrow(GOOG) *0.8
train <- GOOG[1:train_date,]
test <- GOOG[-c(1:train_date),]

#Run a simple logistic regression and obtain predicted probabilities
lm.fit <- glm(direction ~ rsi + momentum, data = train, family = binomial)
summary(lm.fit)
pr.lm <- predict(lm.fit, test, type = "response")


# Extract the OHLC from the GOOG stock and match it with the test dates
TEST <- subset(GOOG, index(GOOG) %in% index(test))

#Add out predictions to the TEST data if its greater than 0.6
TEST$prediction <- ifelse(pr.lm > 0.6, 1, 0)

paste0("Accuracy", mean(TEST$direction == TEST$prediction))

# Now that we have a strategy we want to buy everytime the logistic model states that
# the direction would be a "1"

# Setting up the strategy
GOOG <- TEST
stock("GOOG", currency="USD", multiplier=1)
strategy.st <- portfolio.st <- account.st <- "LogisticRegressionStrategy"
rm.strat(strategy.st)
rm.strat(portfolio.st)
rm.strat(account.st)

initPortf(name = portfolio.st,
          symbols = symbols, 
          initDate = initDate, 
          currency = 'USD')

initAcct(name = account.st, 
         portfolios = portfolio.st, 
         initDate = initDate, 
         currency = 'USD',
         initEq = init_equity)

initOrders(portfolio.st,
           symbols = symbols,
           initDate = initDate)

strategy(strategy.st, store = TRUE)


# Adding the rules, enter at the low price when "prediction" = 1, taking transaction fees into account
add.rule(strategy = strategy.st,
         name = "ruleSignal",
         arguments = list(sigcol = "prediction",
                          sigval = 1,
                          orderqty = .orderqty,
                          ordertype = "market",
                          #orderside = "long", 
                          prefer = "Low", 
                          TxnFees = .txnfees, 
                          replace = FALSE),
         type = "enter",
         label = "EnterLONG")

# As soon as the Logistic regression predicts a "0" we dump all our shares in GOOG

add.rule(strategy.st, 
         name = "ruleSignal", 
         arguments = list(sigcol = "prediction", 
                          sigval = 0, 
                          #orderside = "short", 
                          ordertype = "market", 
                          orderqty = "all", 
                          TxnFees = .txnfees, 
                          replace = TRUE), 
         type = "exit", 
         label = "Exit2SHORT")


applyStrategy(strategy.st, portfolios = portfolio.st)

updatePortf(portfolio.st)
updateAcct(account.st)
updateEndEq(account.st)

chart.Posn(portfolio.st, Symbol = "GOOG", 
           TA="add_SMA(n = 10, col = 2); add_SMA(n = 30, col = 4)")

1 Ответ

0 голосов
/ 20 апреля 2019

Похоже, ты почти у цели.Вы подгоняете модель к тренировочным данным и обязательно выполняете тестирование на тестовом наборе, что является правильным решением.

Некоторые вещи, которые вы хотите соблюдать осторожно: не устанавливайте prefer = low в add.rule для входных сигналов;вы никогда не узнаете заранее, где был минимум в реальной торговле, для заполнения на следующем баре.

Я позволил логистической регрессии здесь прогнозировать 1 бар впереди от текущего бара, потому что это то, что выделать, если вы делали эти прогнозы "онлайн" / в режиме реального времени.Это нормально, при условии, что мы используем только прогнозируемые вероятности, и, очевидно, никогда не используем direction_fwd в качестве торгового сигнала, потому что это приведет к смещению в сторону ожидания .

, чтобы упростить повторный запуск кодаЯ также храню рыночные данные в среде .data, поэтому вы можете восстановить данные в GOOG для applyStrategy, не запрашивая данные снова у Yahoo, если повторно выполнять части кода.

Также вы, вероятно, захотитеОграничьте количество раз, когда вы войдете в позицию.Вы можете сделать это с addPositionLimit.И вы, вероятно, не хотите покупать каждый бар, когда вероятность> 0,6, а скорее только в первый раз (крест), поэтому я ввел код signal, чтобы справиться с этим.

Помните,по умолчанию в quantstrat, ордер заполняется на следующем баре данных (здесь, цена открытия на следующем баре, начиная с prefer = "Open"), который по умолчанию делает заливки более реалистичными (это более применимодля внутридневных данных баров, или отметьте строки данных), но это то, что вы хотите здесь, я думаю, так как вы не знаете значения RSI и импульса для текущего бара в то время end текущего бара, поэтомузаполнение следующего открытого бара имеет смысл.

rm(list=ls())
require(quantstrat)
require(PerformanceAnalytics)

set.seed(1234)

#setting up some initial parameters for the quantstrat trading model
initDate="2007-01-01"
from <- "2017-01-01"
to <- "2018-12-01"
init_equity <- 1000
adjustment <- TRUE

.orderqty <- 10
.txnfees <- -10

currency('USD')
Sys.setenv(TZ="UTC")

#Collect the data
symbols <- c('GOOG')
.data <- new.env()
getSymbols(symbols, from=from, to=to, src="yahoo", adjust=TRUE, env = .data)  

colnames(.data$GOOG) <- c("open", "high", "low", "close", "volume", "adjusted")

mdata <- .data$GOOG

# create the dependent variable for a logistic regression
mdata$direction <- with(mdata, ifelse(close >= open, 1, 0))

#create two basic input variables - lagged
mdata$rsi <- RSI(mdata$close, nFast=14, nSlow = 26, nSig = 9, maType = SMA)
mdata$momentum <- momentum(mdata$close, n = 12)

mdata <- mdata[complete.cases(mdata), ] 
mdata$direction_fwd <- lag.xts(mdata$direction, k = -1)
# create a training and test set
train_date <- nrow(mdata) *0.8
train <- mdata[1:train_date,]
test <- mdata[-c(1:train_date),]



#Run a simple logistic regression and obtain predicted probabilities
lm.fit <- glm(direction_fwd ~ rsi + momentum, data = train, family = binomial)
summary(lm.fit)
pr.lm <- predict(lm.fit, test, type = "response")
test$pred_prob <- pr.lm

#Add out predictions to the TEST data if its greater than 0.6
test$prediction <- ifelse(pr.lm > 0.6, 1, 0)

paste0("Accuracy: ", mean(test$direction_fwd == test$prediction, na.rm = T))


# Simple way to run applyStrategy is to make sure the data for the symbol is in a variable with its name, like so:
GOOG <- test


stock("GOOG", currency="USD", multiplier=1)
strategy.st <- portfolio.st <- account.st <- "LogisticRegressionStrategy"
rm.strat(strategy.st)
rm.strat(portfolio.st)
rm.strat(account.st)



initPortf(name = portfolio.st,
          symbols = symbols, 
          initDate = initDate, 
          currency = 'USD')

initAcct(name = account.st, 
         portfolios = portfolio.st, 
         initDate = initDate, 
         currency = 'USD',
         initEq = init_equity)

initOrders(portfolio.st,
           symbols = symbols,
           initDate = initDate)

strategy(strategy.st, store = TRUE)

nMult_orderqty <- 2
addPosLimit(portfolio.st, symbol = "GOOG", timestamp = initDate, maxpos = nMult_orderqty * .orderqty)

# Buy when prob exceeds 0.6 for the first time, using cross= TRUE
add.signal(strategy = strategy.st,
         name = "sigThreshold",
         arguments = list(threshold=0.6, column="pred_prob", relationship="gt", cross= TRUE),
         label = "longSig")

 #exit when prob drops below 0.5 for the first time
add.signal(strategy = strategy.st,
           name = "sigThreshold",
           arguments = list(threshold=0.5, column="pred_prob", relationship="lt", cross= TRUE),
           label = "exitLongSig")

# Adding the rules, enter at the low price when "prediction" = 1, taking transaction fees into account
add.rule(strategy = strategy.st,
         name = "ruleSignal",
         arguments = list(sigcol = "longSig",
                          sigval = 1,
                          orderqty = .orderqty,
                          ordertype = "market",
                          orderside = "long",
                          osFUN = osMaxPos,
                          prefer = "Open",  #Never kknow the low in advance. Use the open, as it is for the next day (be aware that the open price for bar data has its own problems too)
                          TxnFees = .txnfees, 
                          replace = FALSE),
         type = "enter",
         label = "EnterLONG")

# As soon as the Logistic regression predicts a "0" we dump all our shares in GOOG

add.rule(strategy.st, 
         name = "ruleSignal", 
         arguments = list(sigcol = "exitLongSig", 
                          sigval = 1, 
                          ordertype = "market", 
                          orderside = "long",
                          orderqty = "all", 
                          TxnFees = .txnfees, 
                          replace = TRUE), 
         type = "exit", 
         label = "Exit2SHORT")


applyStrategy(strategy.st, portfolios = portfolio.st)

updatePortf(portfolio.st)
updateAcct(account.st)
updateEndEq(account.st)

chart.Posn(portfolio.st, Symbol = "GOOG", 
           TA="add_SMA(n = 10, col = 2); add_SMA(n = 30, col = 4)")
...