僕编写了个外汇秒钟价格数据采集应用 Data Collection,不过浏览器一旦关闭后,所有运作都即可停止,参考了Persistent R sessions in Shiny Server?,请问有啥其它管道可以让shiny服务器即使在关闭浏览器后也能继续运行呢?

? 僕也在RStudio社区发问了How to keep shiny sever operating even though closed browser?,希望有解决方案... ?

require('shiny')
require('shinyTime')
#'@ require('rdrop2')
require('magrittr')
require('plyr')
require('dplyr')
require('stringr')
require('data.table')
#'@ require('rvest')
require('quantmod')
require('TFX')
require('lubridate')
require('ggplot2')
require('DT')

#'@ drop_auth()
## email : scibrokes_demo@gmail.com
## pass : trader888
#
# https://github.com/karthik/rdrop2
#
#'@ token <- drop_auth()
#'@ saveRDS(token, "droptoken.rds")
# Upload droptoken to your server
# ******** WARNING ********
# Losing this file will give anyone 
# complete control of your Dropbox account
# You can then revoke the rdrop2 app from your
# dropbox account and start over.
# ******** WARNING ********
# read it back with readRDS
#'@ token <- readRDS("droptoken.rds")
# Then pass the token to each drop_ function
#'@ drop_acc(dtoken = token)
#'@ token <<- readRDS("droptoken.rds")
# Then pass the token to each drop_ function
#'@ drop_acc(dtoken = token)

# === Data =====================================================
Sys.setenv(TZ = 'Asia/Tokyo')
zones <- attr(as.POSIXlt(now('Asia/Tokyo')), 'tzone')
zone <- ifelse(zones[[1]] == '', paste(zones[-1], collapse = '/'), zones[[1]])

# === UI =====================================================
ui <- shinyUI(fluidPage(
  
  titlePanel(
    tags$a(href='https://github.com/scibrokes', target='_blank', 
           tags$img(height = '120px', alt='HFT', #align='right', 
                    src='https://raw.githubusercontent.com/scibrokes/real-time-fxcm/master/www/HFT.jpg'))), 
  pageWithSidebar(
    mainPanel(
      tabsetPanel(
        tabPanel('Data Price', 
                 tabsetPanel(
                   tabPanel('Board', 
                            h3('Real Time Board'), 
                            p(strong(paste0('Current time (', zone, '):')),
                              textOutput('currentTime')),
                            br(), 
                            p(strong('Latest FX Quotes:'),
                              tableOutput('fxdata'), 
                              checkboxInput('pause', 'Pause updates', FALSE))), 
                   tabPanel('Chart', 
                            h3('Real Time Chart'), 
                            p(strong(paste0('Current time (', zone, '):')),
                              textOutput('currentTime2')),
                            br(), 
                            plotOutput("plotPrice")#, 
                            #'@ tags$hr(),
                            #'@ plotOutput("plotAskPrice")
                            ), 
                   tabPanel('Data', 
                            h3('Data Download'), 
                            p(strong(paste0('Current time (', zone, '):')),
                              textOutput('currentTime3')), 
                            p('The time zone of data in GMT, Current time (GMT) :', 
                              textOutput('currentTime4')), 
                            dataTableOutput('fxDataTable'), 
                            p(strong('Refresh'), 'button will collect the latest dataset ', 
                              '(time unit in seconds).'), 
                            p('Please becareful, once you click on', 
                              strong('Reset'), 'button, ', 
                              'all data will be lost. Kindly download the dataset ', 
                              'as csv format prior to reset it.'), 
                            actionButton('refresh', 'Refresh', class = 'btn-primary'), 
                            downloadButton('downloadData', 'Download'), 
                            actionButton('reset', 'Reset', class = 'btn-danger')))), 
        
        tabPanel('Appendix', 
                 tabsetPanel(
                   tabPanel('Reference', 
                            h3('Speech'), 
                            p('I try to refer to the idea from below reference to create this web ', 
                              'application for data collection.'), 
                            p(HTML("<a href='https://beta.rstudioconnect.com/content/3138/'>Q1App2</a>"), 
                              '(', strong('Q1App2'), 'inside 2nd reference link at below', 
                              strong('Reference'), 'tab) for algorithmic trading. Kindly browse over', 
                              HTML("<a href='https://github.com/scibrokes/real-time-fxcm'>Real Time FXCM</a>"), 
                              'for more information about high frequency algorithmic trading.'), 
                            br(), 
                            h3('Reference'), 
                            p('01. ', HTML("<a href='https://github.com/cran/TFX'>TFX r package</a>")), 
                            p('02. ', HTML("<a href='https://www.fxcmapps.com/apps/basic-historical-data-downloader/'>Basic Historical Data Downloader</a>")), 
                            p('03. ', HTML("<a href='https://github.com/englianhu/binary.com-interview-question'>binary.com : Job Application - Quantitative Analyst</a>"))), 
                   
                   tabPanel('Author', 
                            h3('Author'), 
                            tags$iframe(src = 'https://beta.rstudioconnect.com/content/3091/ryo-eng.html', 
                                        height = 800, width = '100%', frameborder = 0)))))), 
    br(), 
    p('Powered by - Copyright® Intellectual Property Rights of ', 
      tags$a(href='http://www.scibrokes.com', target='_blank', 
             tags$img(height = '20px', alt='scibrokes', #align='right', 
                      src='https://raw.githubusercontent.com/scibrokes/betting-strategy-and-model-validation/master/regressionApps/oda-army.jpg')), 
      HTML("<a href='http://www.scibrokes.com'>Scibrokes®</a>")))))

# === Server =====================================================
server <- shinyServer(function(input, output, session){
  
  output$currentTime <- renderText({
    # Forces invalidation in 1000 milliseconds
    invalidateLater(1000, session)
    as.character(now('Asia/Tokyo'))
  })
  
  output$currentTime2 <- renderText({
    # Forces invalidation in 1000 milliseconds
    invalidateLater(1000, session)
    as.character(now('Asia/Tokyo'))
  })
  
  output$currentTime3 <- renderText({
    # Forces invalidation in 1000 milliseconds
    invalidateLater(1000, session)
    as.character(now('Asia/Tokyo'))
  })
  
  output$currentTime4 <- renderText({
    # Forces invalidation in 1000 milliseconds
    invalidateLater(1000, session)
    as.character(now('GMT'))
  })
  
  fetchData <- reactive({
    if (!input$pause)
      invalidateLater(750)
    qtf <- QueryTrueFX()
    qtf %<>% mutate(TimeStamp = as.character(TimeStamp))
    names(qtf)[6] <- 'TimeStamp (GMT)'
    return(qtf)
  })
  
  output$fxdata <- renderTable({
    update_data()
    
    fetchData()
  }, digits = 5, row.names = FALSE)
  
  # Function to get new observations
  get_new_data <- function(){
    readLines('http://webrates.truefx.com/rates/connect.html')
    }
  
  ## ----------------- Start fxData ---------------------------
  # Initialize fxData
  fxData <<- get_new_data()
  
  # Function to update fxData, latest data will be showing upside.
  update_data <- function(){
    fxData <<- rbind(fxData, get_new_data())#  %>% unique
    saveRDS(fxData, paste0(str_replace_all(now('GMT'), ':', 'T'), 'GMT.rds'))
    }
  
  output$plotPrice <- renderPlot({
    invalidateLater(1000, session)
    #update_data()
    
    if(any(file.exists(paste0(dir(pattern = '.rds'))))) {
      realPlot <<- llply(dir(pattern = '.rds'), readRDS)
      realPlot <<- do.call(rbind, realPlot) %>% unique
      realPlot <<- ldply(realPlot, ParseTrueFX) %>% unique %>% 
        filter(Symbol == 'USD/JPY')
    }
    
    if(nrow(realPlot) > 10) {
      
      ggplot(tail(realPlot, 10), aes(TimeStamp)) + 
        geom_line(aes(y = Bid.Price, colour = 'Bid.Price')) + 
        geom_line(aes(y = Ask.Price, colour = 'Ask.Price')) + 
        ggtitle('Real Time USD/JPY')
      
    } else {
      
      ggplot(realPlot, aes(TimeStamp)) + 
        geom_line(aes(y = Bid.Price, colour = 'Bid.Price')) + 
        geom_line(aes(y = Ask.Price, colour = 'Ask.Price')) + 
        ggtitle('Real Time USD/JPY')
    }
    })
  
  #'@ output$plotAskPrice <- renderPlot({
  #'@   invalidateLater(1000, session)
    #'@ update_data()
  #'@   
  #'@   dt <- terms()
  #'@   if(nrow(dt) > 40) {
  #'@     ggplot(data = tail(dt, 40), aes(x = TimeStamp, y = Ask.Price, 
  #'@                           group = Symbol, colour = Symbol)) +
  #'@       geom_line() + geom_point( size = 4, shape = 21, fill = 'white') + 
  #'@       ggtitle('Real Time Graph 2 : Forex Ask Price')
  #'@     
  #'@   } else {
  #'@     ggplot(data = dt, aes(x = TimeStamp, y = Ask.Price, 
  #'@                           group = Symbol, colour = Symbol)) +
  #'@       geom_line() + geom_point( size = 4, shape = 21, fill = 'white') + 
  #'@       ggtitle('Real Time Graph 2 : Forex Ask Price')
  #'@   }
  #'@ })
  ## ------------------ End fxData ----------------------------
  
  terms <- reactive({
    input$refresh

    if(any(file.exists(paste0(dir(pattern = '.rds'))))) {
      realData <<- llply(dir(pattern = '.rds'), readRDS)
      realData <<- do.call(rbind, realData) %>% unique
      realData <<- ldply(realData, ParseTrueFX) %>% unique
    }
  })
  
  # Downloadable csv
  output$downloadData <- downloadHandler(
    filename = function() {
      paste('fxData.csv', sep = '')
    },
    content = function(file) {
      fwrite(terms(), file, row.names = FALSE)
    }
  )
  
  observe({
    if(input$reset){
      do.call(file.remove, list(dir(pattern = '.rds')))
      rm(list = ls())
      stopApp('Delete all downloaded dataset!')
    }
  })
  
  output$fxDataTable <- renderDataTable({
    
    terms() %>% datatable(
      caption = "Table : Forex", 
      escape = FALSE, filter = "top", rownames = FALSE, 
      extensions = list("ColReorder" = NULL, "RowReorder" = NULL, 
                        "Buttons" = NULL, "Responsive" = NULL), 
      options = list(dom = 'BRrltpi', scrollX = TRUE, #autoWidth = TRUE, 
                     lengthMenu = list(c(10, 50, 100, -1), c('10', '50', '100', 'All')), 
                     ColReorder = TRUE, rowReorder = TRUE, 
                     buttons = list('copy', 'print', 
                                    list(extend = 'collection', 
                                         buttons = c('csv', 'excel', 'pdf'), 
                                         text = 'Download'), I('colvis'))))
  })
  
  # Set this to "force" instead of TRUE for testing locally (without Shiny Server)
  session$allowReconnect(TRUE)
  llply(c('plotPrice', 'fxdata', 'fxDataTable'), function(x) {
    outputOptions(output, x, suspendWhenHidden = FALSE)
  })
})

shinyApp(ui, server)

参考文献

7 天 后

对这些内容也十分期待。R语言对大型系统的开发给力吗?这是一个小型的程序吗?

    tctcab
    Financial services startup looking for freelance Shiny/R/UI developer这才算是个大应用系统吧?僕就是要学习该投资基金,使用shiny(自个儿也仅仅会R与shiny而不会c++、Javascript 、php、sql、sparklyr 等高效处理?)编写整个完善的投资系统。

    • 实时多用户账号管理
    • 实时多账号资金管理
    • 实时多类投资商品管理
    • 实时与大量数据运算金融预测统计模式
    • 实时数据视觉化

    单看链接中要求该职位的技术能力和以上系统条件,可想而知得精通编写实时高效运算金、cache 与 cookies、environment与session吖!?

    RStudio Community 的帖子突然在一个小时前被屏蔽也无法发新帖子。?

    I wrote a web application Data Collection but it o lyrics can save few days data... Thousands rows will be lack.

    I am using saveRDS() and invalidate() to save every single second forex price scrapped from website. Is there any efficient method to handle real time high frequency trading volume?

    希望有前辈可以指点唷

    6 天 后

    哈哈,身无分文的僕目前在柬埔寨??工作(网络博彩),还得等待明年才有钱买部 windows phone /tablet (https://community.rstudio.com/t/rstudio-server-more-user-friendly-than-rstudio-cloud/3199/3?u=englianhu) 继续编写网站,僕预先为2018年准备的阅读清单!让我们期待明年会更好... 干巴爹!?

    Multiple users login in shinyapp
    1) https://stackoverflow.com/questions/38558198/how-to-create-a-login-page-in-shiny
    2) https://stackoverflow.com/questions/28987622/starting-shiny-app-after-password-input
    3) https://lesliemyint.wordpress.com/2017/01/01/creating-a-shiny-app-with-google-login/amp/
    4) https://github.com/treysp/shiny_password
    5) https://github.com/aoles/shinypass
    6) https://gist.github.com/Ray901/656f4314d00a7b00a05f

    Add on

    1) rstudioconnect storage (deployed to rstudioconnect)
    https://support.rstudio.com/hc/en-us/articles/227009188-Where-can-I-find-the-files-created-by-RStudio-Connect-?mobile_site=true

    2) Multiple users in shinyapp
    https://github.com/JidduAlexander/user_account_app_skeleton

    3) persistent storage shiny (but need to tune with rstudioconnect storage)
    https://shiny.rstudio.com/articles/persistent-data-storage.html

    4) deploy desktop app with R
    http://oddhypothesis.blogspot.my/2014/04/deploying-self-co

    • ryo 回复了此帖
      3 年 后