2

我正在尝试制作一个旨在使用 quantstrat 的网络应用程序。但是,我在整合两者时遇到了一些困难。没有这方面的文档,所以很难找到一个开始的地方。这是我现在拥有的代码。如果您能让我知道我做错了什么,将不胜感激。谢谢

library(shiny)
library(devtools)
library(quantmod)
library(quantstrat)
library(TTR)
library(png)
library(dplyr)
Sys.setenv(TZ = "UTC")
currency('USD')

ui <- fluidPage(

# Application title
titlePanel("myfirst"),


sidebarLayout(
  sidebarPanel(
    selectInput(
     "stocks", label = "chose stock", choices = 
      c("AAPL", "CAT")
    ),
    dateInput("init_date", "chose init date", 
     value = Sys.Date() -100),
    dateInput("start_date", "chose start date", 
     value = Sys.Date() - 99),
    dateInput("end_date", "chose end date", 
     value = Sys.Date()),
    selectInput("init_equity", "starting 
    equity", choices = c(1000, 50000))
  ),


  mainPanel(
     plotOutput("plot"),
     textOutput("text")
  )
  )

  )

  server <- function(input, output) {
  init_date = reactive({
  input$init_date
   })
  start_date = reactive({
input$start_date
})
end_date = reactive({
input$end_date
 })
 init_equity = reactive({
  input$init_equity
 })

  V = reactive({
  getSymbols(input$stocks, from = start_date(), 
 to = end_date(), index.class = "POSIXct", 
adjust = T)
 })

 observe({
stock(input$stocks, currency = "USD", multiplier 
= 1)
   })

  portfolio.st = account.st = strategy.st = 
 "my.first"

 rm.strat(portfolio.st)
 rm.strat(account.st)

 observe({ 
   initPortf(name = portfolio.st,
        symbols = "V",
        initDate = init_date())
 initAcct(name = account.st,
         portfolios = portfolio.st,
         initDate = init_date(),
         initEq = init_equity())
 initOrders(portfolio = portfolio.st,
           symbols = "V",
           initDate = init_date()
           )
 strategy(strategy.st, store = T)


 })

observe({ add.indicator(strategy = strategy.st,
            name = "SMA",
            arguments = list(x = 
  quote(Cl(mktdata)), 
                             n = 10),
            label = "nFast")

add.indicator(strategy = strategy.st, 
              name = "SMA", 
              arguments = list(x = 
quote(Cl(mktdata)), 
                               n = 30), 
              label = "nSlow")

add.signal(strategy = strategy.st,
           name="sigCrossover",
           arguments = list(columns = c("nFast", "nSlow"),
                            relationship = "gte"),
           label = "long")
add.signal(strategy = strategy.st,
           name="sigCrossover",
           arguments = list(columns = c("nFast", "nSlow"),
                            relationship = "lt"),
           label = "short")
add.rule(strategy = strategy.st,
         name = "ruleSignal",
         arguments = list(sigcol = "long",
                          sigval = TRUE,
                          orderqty = 100,
                          ordertype = "stoplimit",
                          orderside = "long", 
                          threshold = 0.0005,
                          prefer = "High", 
                          TxnFees = -10, 
                          replace = FALSE),
         type = "enter",
         label = "EnterLONG")
add.rule(strategy.st,
         name = "ruleSignal",
         arguments = list(sigcol = "short",
                          sigval = TRUE,
                          orderqty = -100,
                          ordertype = "stoplimit",
                          threshold = -0.005, 
                          orderside = "short", 
                          replace = FALSE, 
                          TxnFees = -10, 
                          prefer = "Low"),
         type = "enter",
         label = "EnterSHORT")
add.rule(strategy.st, 
         name = "ruleSignal", 
         arguments = list(sigcol = "short", 
                          sigval = TRUE, 
                          orderside = "long", 
                          ordertype = "market", 
                          orderqty = "all", 
                          TxnFees = -10, 
                          replace = TRUE), 
         type = "exit", 
         label = "Exit2SHORT")
add.rule(strategy.st, 
         name = "ruleSignal", 
         arguments = list(sigcol = "long", 
                          sigval = TRUE, 
                          orderside = "short", 
                          ordertype = "market", 
                          orderqty = "all", 
                          TxnFees = -10, 
                          replace = TRUE), 
         type = "exit", 
         label = "Exit2LONG")
applyStrategy(strategy.st, portfolios = portfolio.st)
updatePortf(portfolio.st)
updateAcct(account.st)
updateEndEq(account.st)

})

 output$plot = reactive(
  chart.Posn(portfolio.st, Symbol = "V")
  )
 }

 # Run the application 
  shinyApp(ui = ui, server = server)
4

1 回答 1

1

有趣的想法。由于交易工具的市场数据如何存储在本地环境中的变量名称与其符号/代码相同的性质,您正在尝试做的事情有点挑战性。

此外,您的闪亮应用程序有些奇怪;小心你如何使用reactive({,isolate({和其他服务器组件。例如,当您有服务器对象时

start_date = reactive({
input$start_date
})` 

那是多余的。

这是一个示例,可以实现您想要实现的目标。我尽量使变量名与您的示例保持一致。

您可能需要重新考虑您的工作流程:我认为您应该独立于闪亮运行大量模拟quantstrat,然后将结果保存到磁盘。然后在启动 Shiny 应用程序时从磁盘加载这些结果。尽管如此,这个例子还是希望能解决你剩下的困惑。

此外,您应该注意通过getSymbols. 我在下面做的是在应用程序首次启动时仅请求一次数据,并将市场数据存储在名为rawdata. 然后,如果您再次停止并重新启动您的应用程序,您将不会继续向雅虎请求数据(当他们限制您在一段时间内可以下载的数量时,这可能会给您带来错误)。


# Could put these in global.R, these global variables are "hard coded"  ----------------
min_date_barrier <- "2012-01-01"
max_date_barrier <- "2019-04-17"
stock_universe <- c("AAPL", "CAT", "BB")

# These variables won't change when the app launches, so hard code them too:

Sys.setenv(TZ = "UTC")
currency('USD')
stock(stock_universe, currency = "USD", multiplier = 1)

portfolio.st <- account.st <- strategy.st <- "my.first"

# In here, store the original market data which contains your full range of possible values for the market data:
# Don't keep requesting data frequently otherwise you won't be able to download the data temporarily.
if (!exists("rawdata")) {
    rawdata <- new.env()
    assign("rawdata", rawdata, envir = .GlobalEnv)

    lapply(stock_universe, function(sym) {
        # if (exists(sym, envir = rawdata)) {
        #     message("Have already downloaded data for ", sym)
        #     return()
        # } else {
            getSymbols(stock_universe,
                       env = rawdata,  # important to specify environment
                       from = min_date_barrier,
                       to = max_date_barrier,
                       adjust = T, auto.assign = TRUE)
        #}
        return()
    })

}

# UI ----------------------------------------------------------------------

ui <- fluidPage(

    # Application title
    titlePanel("myfirst"),


    sidebarLayout(
        sidebarPanel(
            selectInput(
                "stock", label = "Choose stock", choices = stock_universe
            ),

            dateInput("start_date", "Choose start date",
                      value = "2018-02-03"),
            dateInput("end_date", "Choose end date",
                      value = "2019-04-10"),
            selectInput("init_equity", "starting
    equity", choices = c(1000, 50000))
        ),


        mainPanel(
            plotOutput("plot_backtest"),
            verbatimTextOutput("results")
        )
    )

)



# server ------------------------------------------------------------------

server <- function(input, output, session) {

    # all your reactives don't make sense -- only use the inputs when you need them on the server side


    backtest_setup <- reactive({

        # need these input variables in this reactive to avoid bugs in the app when you change the time range:

        input$start_date
        input$end_date
        rm.strat(portfolio.st, silent = FALSE)
        initPortf(name = portfolio.st,
                  symbols = input$stock,        #------------------------ correct way to apply the "stock" input
                  initDate = "2000-01-01")
        initAcct(name = account.st,
                 portfolios = portfolio.st,
                 initDate = "2000-01-01",
                 initEq = as.numeric(input$init_equity)) # convert equity to numeric from string
        initOrders(portfolio = portfolio.st,
                   symbols = input$stock,  # ----------------------------------
                   initDate = "2000-01-01"
        )
        strategy(strategy.st, store = T)


        add.indicator(strategy = strategy.st,
                      name = "SMA",
                      arguments = list(x =
                                           quote(Cl(mktdata)),
                                       n = 10),
                      label = "nFast")

        add.indicator(strategy = strategy.st,
                      name = "SMA",
                      arguments = list(x =
                                           quote(Cl(mktdata)),
                                       n = 30),
                      label = "nSlow")

        add.signal(strategy = strategy.st,
                   name="sigCrossover",
                   arguments = list(columns = c("nFast", "nSlow"),
                                    relationship = "gte"),
                   label = "long")
        add.signal(strategy = strategy.st,
                   name="sigCrossover",
                   arguments = list(columns = c("nFast", "nSlow"),
                                    relationship = "lt"),
                   label = "short")
        add.rule(strategy = strategy.st,
                 name = "ruleSignal",
                 arguments = list(sigcol = "long",
                                  sigval = TRUE,
                                  orderqty = 100,
                                  ordertype = "stoplimit",
                                  orderside = "long",
                                  threshold = 0.0005,
                                  prefer = "High",
                                  TxnFees = -10,
                                  replace = FALSE),
                 type = "enter",
                 label = "EnterLONG")
        add.rule(strategy.st,
                 name = "ruleSignal",
                 arguments = list(sigcol = "short",
                                  sigval = TRUE,
                                  orderqty = -100,
                                  ordertype = "stoplimit",
                                  threshold = -0.005,
                                  orderside = "short",
                                  replace = FALSE,
                                  TxnFees = -10,
                                  prefer = "Low"),
                 type = "enter",
                 label = "EnterSHORT")
        add.rule(strategy.st,
                 name = "ruleSignal",
                 arguments = list(sigcol = "short",
                                  sigval = TRUE,
                                  orderside = "long",
                                  ordertype = "market",
                                  orderqty = "all",
                                  TxnFees = -10,
                                  replace = TRUE),
                 type = "exit",
                 label = "Exit2SHORT")
        add.rule(strategy.st,
                 name = "ruleSignal",
                 arguments = list(sigcol = "long",
                                  sigval = TRUE,
                                  orderside = "short",
                                  ordertype = "market",
                                  orderqty = "all",
                                  TxnFees = -10,
                                  replace = TRUE),
                 type = "exit",
                 label = "Exit2LONG")

    })

    V <- reactive({

        validate(need(input$start_date >= as.Date(min_date_barrier), "start date cannot be less than hard coded min_date_barrier"))
        validate(need(input$end_date <= as.Date(max_date_barrier), "end date cannot be greater than  hard coded max_date_barrier"))
        validate(need(as.Date(input$start_date) < as.Date(input$end_date), "start date must be less than end date."))
        # assign symbol market data to the global environment for the range of dates you want:
        time_rng <- paste0(input$start_date, "/", input$end_date)
        mdata <- get(input$stock, envir = rawdata)
        mdata <- mdata[time_rng]

        validate(need(NROW(mdata) > 0, "no data available, choose an appropriate time range"))

        mdata
    })

    backtest_results <- reactive({

        backtest_setup()
        mdata <- V()
        assign(input$stock, mdata, envir = .GlobalEnv)
        # not supplying mktdata as a parameter, so look in global environment for objects with the symbol names (which will exist because V assigns to .GlobalEnv):
        applyStrategy(strategy.st, portfolios = portfolio.st)
        # alternatively you could pass in the data directly to apply strategy if you're just using one symbol of data in the applyStrategy call, instead of having applyStrategy directly search in the .GlobalEnv for the symbol name
        #applyStrategy(strategy.st, portfolios = portfolio.st, mktdata = mdata)
        updatePortf(portfolio.st)
        updateAcct(account.st)
        updateEndEq(account.st)

    })

    output$plot_backtest = renderPlot({
        backtest_results()
        chart.Posn(portfolio.st, Symbol = input$stock)
    })

    output$results = renderPrint({
        backtest_setup()
        tmpdata <- V() # need this here so that any changes to the inputs will reprint the trade stats table
        print(tradeStats(portfolio.st))
    })

}

# Run the application
shinyApp(ui = ui, server = server)

该应用程序将如下所示:

在此处输入图像描述

于 2019-04-20T06:02:29.913 回答