es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Websockets en R-Shiny

Estoy trabajando en Shiny, y estoy tratando de obtener datos financieros con websockets, dado que la latencia con las APIs es demasiado grande (>1min). Cada minuto, necesito obtener los precios de apertura, máximo, mínimo y cierre (OHLC) de un flujo correspondiente a un ticker (por ejemplo, AAPL).

El código a continuación es el esqueleto de un reprex, similar al que se encuentra en el sitio web de Finnhub (https://finnhub.io/docs/api/websocket-trades).

library(websocket)
ws <- WebSocket$new("wss://ws.finnhub.io/?token=btj392748v6p9f1po5vg")
ws$onOpen(function(event) {
  cat("IOWebSocket opened!\n")
})
ws$onClose(function(event) {
  cat("IOWebSocket closed with code ", event$code,
      " and reason ", event$reason, "\n", sep = "")
})
ws$onError(function(event) {
  cat("IOWebSocket ERROR: ", event$message, "\n")
})
ws$onMessage(function(event) {
  cat("Received event:", event$data, "\n")
})
ws$send('{"type": "subscribe", "symbol": ["AAPL"]}')

Tenga en cuenta que el código debe ejecutarse dentro de Shiny, donde, entre otros problemas de temporización, (a) las conexiones y otras funciones no se ejecutan inmediatamente, sino que se colocan en colas y (b) el script debe evitar simplemente salir mientras está realizando la comunicación. Esto se notó en , que también proporciona algunos enfoques para resolverlos.

Pregunta

¿Qué código se debe incluir para obtener el flujo de precios, determinar los valores OHLC y mostrar los datos OHLC cada minuto (o en intervalos seleccionables)?

Gracias

Tags:  , ,

Answer

  1. Avatar for davy.ai

    Para obtener el flujo de precios y determinar los valores OHLC, se puede agregar el siguiente código dentro de la función ws$onMessage:

    msg <- fromJSON(event$data)
    if (msg$type == "trade") {
      # Obtener el precio
      price <- msg$data[[1]]$p
      # Almacenar el precio en un data frame o vector para el ticker seleccionado
    
      # Calcular los valores OHLC en cada intervalo de un minuto
      if (format(Sys.time(), "%S") == "00") {
        # Calcular los valores OHLC y mostrar los datos
        open <- price[1]
        max <- max(price)
        min <- min(price)
        close <- price[length(price)]
        ohlc_data <- data.frame(open, max, min, close)
        # Mostrar los datos OHLC o almacenarlos para su uso posterior
      }
    }
    

    Este código primero verificará si el mensaje recibido es un mensaje de transacción (trade), y si es así, extraerá los datos de precio y los almacenará en un data frame o vector para el ticker seleccionado. Luego, en cada intervalo de un minuto (cuando los segundos son cero), calculará los valores OHLC utilizando los datos de precio almacenados y mostrará los datos. Los datos OHLC pueden ser mostrados o almacenados para su uso posterior, dependiendo de los requisitos.

    Para asegurarse de que la comunicación no se termine mientras el código se está ejecutando, se puede utilizar una función reactiveTimer para activar el código cada minuto, y otra opción es utilizar la función on.exit para asegurarse de que la conexión WebSocket se cierre incluso si el script encuentra un error o si el usuario lo detiene. Una implementación posible es la siguiente:

    library(shiny)
    library(websocket)
    library(jsonlite)
    
    ui <- fluidPage(
      # Elementos de la interfaz de usuario
    )
    
    server <- function(input, output, session) {
      # Conexión WebSocket
      ws <- WebSocket$new("wss://ws.finnhub.io/?token=btj392748v6p9f1po5vg")
      ws$onOpen(function(event) {
        cat("IOWebSocket opened!\n")
      })
      ws$onClose(function(event) {
        cat("IOWebSocket closed with code ", event$code,
            " and reason ", event$reason, "\n", sep = "")
      })
      ws$onError(function(event) {
        cat("IOWebSocket ERROR: ", event$message, "\n")
      })
      ws$onMessage(function(event) {
        msg <- fromJSON(event$data)
        if (msg$type == "trade") {
          # Obtener el precio
          price <- msg$data[[1]]$p
          # Almacenar el precio en un data frame o vector para el ticker seleccionado
    
          # Calcular los valores OHLC en cada intervalo de un minuto
          if (format(Sys.time(), "%S") == "00") {
            # Calcular los valores OHLC y mostrar los datos
            open <- price[1]
            max <- max(price)
            min <- min(price)
            close <- price[length(price)]
            ohlc_data <- data.frame(open, max, min, close)
            # Mostrar los datos OHLC o almacenarlos para su uso posterior
          }
        }
      })
      ws$send('{"type": "subscribe", "symbol": ["AAPL"]}')
    
      # Reactivos
      trigger_ohlc <- reactiveTimer(60000) # Activar cada minuto
    
      # Ejecución del código
      observe({
        trigger_ohlc() # Activar el temporizador reactivo
    
        # Código a ejecutar cada minuto
        # ...
      })
    
      # Cerrar la conexión WebSocket cuando se cierre o pare la aplicación
      on.exit(ws$close())
    }
    
    shinyApp(ui, server)
    

    En esta implementación, se utiliza una función reactiveTimer para activar el código OHLC cada minuto. El código está envuelto dentro de una función observe para asegurarse de que se ejecute cada vez que se activa el temporizador. La función on.exit se utiliza para asegurarse de que la conexión WebSocket se cierre cuando la aplicación se cierra o se detiene.

Comments are closed.