+Repository: CRAN
+Date/Publication: 2023-04-22 07:10:02 UTC
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..31e220d
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,2 @@
+YEAR: 2023
+COPYRIGHT HOLDER: Yongchao Fang
diff --git a/MD5 b/MD5
new file mode 100644
index 0000000..20581c9
--- /dev/null
+++ b/MD5
@@ -0,0 +1,18 @@
+0df37465f88340fdcd308abbca5a1138 *DESCRIPTION
+0d3cb8d6ab2e2ec2955fd3e7e0674652 *LICENSE
+c43b22885efa36e5be67cb4e5beb4b99 *NAMESPACE
+a42ec1c4244360d3eec4031cb5e03648 *R/funcs.R
+70f6b0fb294838cf04f5b782e6eb0559 *R/restAPI.R
+2ac6566ea0e1e3230d60124baa76eae8 *R/utils.R
+580132d53dc4d1455d2dca1e5fb724f5 *R/websockerAPIprivate.R
+13873099c8fc3e9b2466cdbd66237ae6 *R/websocketAPIpublic.R
+703ddbf7088aff8797ce4d6315b172ca *README.md
+eae3f11c522c7f9c34fcdeb24e231041 *man/get_functions.Rd
+45700e5426fda3522acedec9ff6636b0 *man/get_history_candles.Rd
+5c9e06661a94a771518e944398790373 *man/get_positions_history.Rd
+07f49942d8cb0a6400ae4a680b0007e0 *man/restAPI.Rd
+96d6b96cc4d461b2cbe4908b0c26fe67 *man/restAPIaccount.Rd
+44dfd99788fe451e16578f879fe46d13 *man/restAPImarket.Rd
+3b0c114f825b8f93f4dabafd04bc162b *man/restAPItrade.Rd
+6883bf6c50b48bf01093925f03111910 *man/websocketAPIprivate.Rd
+6c3bdcc93739a40a916d4761aa47471f *man/websocketAPIpublic.Rd
diff --git a/NAMESPACE b/NAMESPACE
new file mode 100644
index 0000000..49695b5
--- /dev/null
+++ b/NAMESPACE
@@ -0,0 +1,17 @@
+# Generated by roxygen2: do not edit by hand
+
+export(get_history_candles)
+export(get_positions_history)
+export(restAPI)
+export(restAPIaccount)
+export(restAPImarket)
+export(restAPItrade)
+export(websocketAPIprivate)
+export(websocketAPIpublic)
+import(R6)
+import(base64enc)
+import(data.table)
+import(digest)
+import(httr)
+import(jsonlite)
+import(websocket)
diff --git a/R/funcs.R b/R/funcs.R
new file mode 100644
index 0000000..0840de2
--- /dev/null
+++ b/R/funcs.R
@@ -0,0 +1,133 @@
+#' @name get_functions
+#'
+#' @title Wrapper for some frequently used APIs to get data easily
+#'
+#' @description The main purpose is to handle APIs that have limitations on the number of results returned per single request.
+#' @seealso
+#' \code{\link{get_positions_history}}
+#' \code{\link{get_history_candles}}
+NULL
+
+
+#' @title Retrieve the position data
+#'
+#' @description Wrapper for API [Get positions history](https://www.okx.com/docs-v5/en/#rest-api-account-get-positions-history).
+#'
+#' @param api_key Okx API key.
+#' @param secret_key Okx API secret key.
+#' @param passphrase Okx API passphrase.
+#' @param count Retrieve position data for a specified number of past days, with a maximum of 90(days)
+#' @param period Due to the 'Number of results per request' limitation of the API,
+#' the \code{period} parameter must be specified to ensure that the number of position data entries within each period does not exceed 100.
+#' @param ... Other request parameters to be passed, See
+#' [Get positions history](https://www.okx.com/docs-v5/en/#rest-api-account-get-positions-history) for more information.
+#'
+#' @return Position data
+#'
+#' @examples
+#' \dontrun{
+#' positions <- get_positions_history(
+#' api_key, secret_key, passphrase, count = 90, period = 10,
+#' instType = "SWAP", mgnMode = "isolated"
+#' )
+#' }
+#'
+#' @import data.table
+#' @export
+get_positions_history <- function(
+ api_key, secret_key, passphrase, count = 90, period = 10, ...
+) {
+ account <- restAPIaccount$new(api_key, secret_key, passphrase)
+ now <- time2ts(Sys.time())
+ start <- now - count*24*60*60
+ end <- start + period*24*60*60 - 0.001
+ dat <- list()
+ while (start < now) {
+ result <- account$positions_history(
+ before = as.character(1000*start - 1), after = as.character(1000*end + 1), ...
+ )
+ if (result$code == "0") {
+ dat <- c(dat, result$data)
+ message("From ", ts2time(start), " to ", ts2time(end), " complete")
+ start <- end + 0.001
+ end <- start + period*24*60*60 - 0.001
+ Sys.sleep(15)
+ }
+ }
+ dat <- lapply(dat, data.table::as.data.table)
+ dat <- data.table::rbindlist(dat)
+ to_time <- c("cTime", "uTime")
+ dat[, (to_time) := lapply(.SD, ts2time), .SDcols = to_time]
+ to_numeric <- c("closeAvgPx", "closeTotalPos", "lever", "openAvgPx", "openMaxPos", "pnl", "pnlRatio")
+ dat[, (to_numeric) := lapply(.SD, as.numeric), .SDcols = to_numeric]
+ dat
+}
+
+#' @title Retrieve the candlestick charts
+#'
+#' @description Wrapper for API [Get candlesticks](https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks)
+#' and [Get candlesticks history](https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks-history).
+#'
+#' @param api_key Okx API key.
+#' @param secret_key Okx API secret key.
+#' @param passphrase Okx API passphrase.
+#' @param bar Bar size, the default is 1m, e.g. 1m/3m/5m/15m/30m/1H/2H/4H, Hong Kong time opening price k-line: 6H/12H/1D/2D/3D.
+#' @param count Number of Bars.
+#' @param instId Instrument ID, e.g. BTC-USDT-SWAP.
+#' @param ... Other request parameters to be passed, See [Get candlesticks history](https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks-history) for more information.
+#'
+#' @return Candlestick charts data
+#'
+#' @examples
+#' \dontrun{
+#' candles <- get_history_candles(
+#' api_key, secret_key, passphrase, bar = "1m",
+#' count = 24*60, instId = "CFX-USDT-SWAP"
+#' )
+#' }
+#'
+#' @import data.table
+#' @export
+get_history_candles <- function(
+ api_key, secret_key, passphrase,
+ bar = c("1m", "3m", "5m", "15m", "30m", "1H", "4H", "6H", "12H", "1D", "2D", "3D"),
+ count, instId, ...
+) {
+ bar <- match.arg(bar)
+ period <- str2period(bar)
+
+ market <- restAPImarket$new(api_key, secret_key, passphrase)
+
+ now <- time2ts(Sys.time())
+ end <- now
+ start <- end - ifelse(count >= 100, 100, count) * period + 0.001
+ dat <- list()
+ for (i in 1:ceiling(count / 100)) {
+ if (i == 1) {
+ result <- market$candles(
+ instId = instId, before = as.character(1000*start - 1),
+ after = as.character(1000*end + 1), bar = bar, ...
+ )
+ } else {
+ result <- market$history_candles(
+ instId = instId, before = as.character(1000*start - 1),
+ after = as.character(1000*end + 1), bar = bar, ...
+ )
+ }
+ if (result$code == "0") {
+ dat <- c(dat, result$data)
+ message("From ", ts2time(start), " to ", ts2time(end), " complete")
+ count <- count - 100
+ end <- start - 0.001
+ start <- end - ifelse(count >= 100, 100, count) * period + 0.001
+ # Sys.sleep(1/20)
+ }
+ }
+ col_names <- c("ts", "open", "high", "low", "close", "vol", "volCcy", "volCcyQuote", "confirm")
+ dat <- lapply(dat, as.data.frame, col.names = c(col_names))
+ dat <- data.table::rbindlist(dat)
+ dat$ts <- ts2time(dat$ts)
+ to_numeric <- c("open", "high", "low", "close", "vol", "volCcy", "volCcyQuote")
+ dat[, (to_numeric) := lapply(.SD, as.numeric), .SDcols = to_numeric]
+ dat
+}
diff --git a/R/restAPI.R b/R/restAPI.R
new file mode 100644
index 0000000..459bcfd
--- /dev/null
+++ b/R/restAPI.R
@@ -0,0 +1,299 @@
+#' @title restAPI Class
+#'
+#' @description Base class for [Okx exchange v5 API](https://www.okx.com/docs-v5/en/).
+#'
+#' @details You can implement all REST API requests in Okx exchange by inheriting the \code{restAPI} class.
+#' Please refer to the example provided at the end of the document.
+#'
+#' For commonly used interfaces, they have been implemented in this package.
+#' The naming convention is as follows: for "/api/v5/AAA/BBB", a new class named \code{restAPIAAA},
+#' which inherits from \code{restAPI}, has been defined in this package.
+#' The \code{BBB} method in this new class is used to call the API.
+#'
+#' @examples
+#' \dontrun{
+#' # for [Get currencies](https://www.okx.com/docs-v5/en/#rest-api-funding-get-currencies)
+#' # you can define the class like this
+#' myRestAPI <- R6::R6Class(
+#' inherit = restAPI,
+#' public = list(
+#' get_currencies = function(ccy, process = "identity") {
+#' self$get_result(
+#' api = "/api/v5/asset/currencies", method = "GET", process = process,
+#' ccy = ccy
+#' )
+#' }
+#' )
+#' )
+#' # And call it like this
+#' tmp <- myRestAPI$new(api_key, secret_key, passphrase)
+#' tmp$get_currencies("BTC")
+#' }
+#'
+#' @seealso
+#' \code{\link{restAPItrade}}
+#' \code{\link{restAPIaccount}}
+#' \code{\link{restAPImarket}}
+#'
+#' @import R6 httr jsonlite base64enc base64enc
+#' @export
+restAPI <- R6::R6Class(
+ "restAPI",
+ public = list(
+ #' @field url Okx REST API url, which is https://www.okx.com.
+ url = "https://www.okx.com",
+ #' @field api_key Okx API key.
+ api_key = NA,
+ #' @field secret_key Okx API secret key.
+ secret_key = NA,
+ #' @field passphrase Okx API passphrase.
+ passphrase = NA,
+ #' @field simulate Whether to use demo trading service.
+ simulate = NA,
+ #' @description Create a new REST API object.
+ #' @param api_key Okx API key.
+ #' @param secret_key Okx API secret key.
+ #' @param passphrase Okx API passphrase.
+ #' @param simulate Whether to use demo trading service.
+ initialize = function(api_key, secret_key, passphrase, simulate = FALSE) {
+ self$api_key <- api_key
+ self$secret_key <- secret_key
+ self$passphrase <- passphrase
+ self$simulate <- simulate
+ },
+ #' @description Get UTC timestamp.
+ get_timestamp = function() {
+ timestamp <- as.numeric(Sys.time()) * 1000
+ timestamp <- as.POSIXct(timestamp / 1000, origin = "1970-01-01", tz = "UTC")
+ timestamp <- format(timestamp, format = "%Y-%m-%dT%H:%M:%OS3Z", usetz = FALSE)
+ timestamp
+ },
+ #' @description Get request path.
+ #' @param api Request api e.g. /api/v5/account/positions-history.
+ #' @param method Request method, \code{GET} or \code{POST}.
+ #' @param ... Other request parameters.
+ get_request_path = function(api, method = c("GET", "POST"), ...) {
+ method <- match.arg(method)
+ if (method == "GET") {
+ tmp <- list(...)
+ if (length(tmp) == 0) {
+ request_path <- api
+ } else {
+ tmp <- tmp[!is.na(tmp)]
+ request_path <- paste0(api, "?")
+ for (i in 1:length(tmp)) {
+ tmp[[i]] <- paste0(names(tmp)[i], "=", paste(tmp[[i]], collapse = ","))
+ }
+ tmp <- paste(unlist(tmp), collapse = "&")
+ request_path <- paste0(api, "?", tmp)
+ }
+ } else {
+ request_path <- api
+ }
+ request_path
+ },
+ #' @description Get request body.
+ #' @param method Request method, \code{GET} or \code{POST}.
+ #' @param ... Other request parameters.
+ get_body = function(method = c("GET", "POST"), ...) {
+ method <- match.arg(method)
+ if (method == "GET") {
+ body <- ""
+ } else {
+ tmp <- list(...)
+ tmp <- tmp[!is.na(tmp)]
+ body <- jsonlite::toJSON(tmp, auto_unbox = TRUE)
+ }
+ body
+ },
+ #' @description Get the signing messages.
+ #' @param timestamp Retrieve through method \code{get_timestamp}.
+ #' @param request_path Retrieve through method \code{get_request_path}.
+ #' @param body Retrieve through method \code{get_body}.
+ #' @param method Request method, \code{GET} or \code{POST}.
+ get_message = function(timestamp, request_path, body, method = c("GET", "POST")) {
+ method <- match.arg(method)
+ paste0(timestamp, method, request_path, body)
+ },
+ #' @description Get the signature.
+ #' @param msg Retrieve through method \code{get_message}.
+ #' @param secret_key Okx API secret key.
+ get_signature = function(msg, secret_key = self$secret_key) {
+ base64enc::base64encode(base64enc::hmac(secret_key, msg, algo = "sha256", raw = TRUE))
+ },
+ #' @description Get request headers.
+ #' @param timestamp Retrieve through method \code{get_timestamp}.
+ #' @param msg Retrieve through method \code{get_message}.
+ get_header = function(timestamp, msg) {
+ headers <- c(
+ "OK-ACCESS-KEY" = self$api_key,
+ "OK-ACCESS-SIGN" = self$get_signature(msg),
+ "OK-ACCESS-TIMESTAMP" = timestamp,
+ "OK-ACCESS-PASSPHRASE" = self$passphrase,
+ "Content-Type" = "application/json"
+ )
+ if (self$simulate) {
+ headers <- c(headers, "x-simulated-trading" = "1")
+ }
+ headers
+ },
+ #' @description Retrieve data from api.
+ #' @param api Request api e.g. /api/v5/account/positions-history.
+ #' @param method Request method, \code{GET} or \code{POST}.
+ #' @param process A function to process the data received from the API.
+ #' @param ... Other request parameters.
+ get_result = function(api, method = c("GET", "POST"), process, ...) {
+ method <- match.arg(method)
+ timestamp <- self$get_timestamp()
+ request_path <- self$get_request_path(api = api, method = method, ...)
+ body <- self$get_body(method = method, ...)
+ msg <- self$get_message(timestamp, request_path, body, method)
+ if (method == "GET") {
+ response <- httr::GET(
+ paste0(self$url, request_path),
+ httr::add_headers(.headers = self$get_header(timestamp, msg))
+ )
+ } else {
+ response <- httr::POST(
+ paste0(self$url, request_path),
+ httr::add_headers(.headers = self$get_header(timestamp, msg)),
+ body = body
+ )
+ }
+ result <- httr::content(response)
+ if (httr::http_error(response)) {
+ message("Error code ", result$code, ": ", result$msg)
+ } else if (result$code != "0") {
+ message("Error code ", result$data[[1]]$sCode, ": ", result$data[[1]]$sMsg)
+ } else {
+ return(do.call(process, list(result)))
+ }
+ }
+ )
+)
+
+
+#' @title restAPItrade Class
+#'
+#' @description Wrapper for [REST API TRADE](https://www.okx.com/docs-v5/en/#rest-api-trade).
+#'
+#' @import R6
+#' @export
+restAPItrade <- R6::R6Class(
+ "restAPItrade",
+ inherit = restAPI,
+ public = list(
+ #' @description See [Place order](https://www.okx.com/docs-v5/en/#rest-api-trade-place-order) for more information.
+ #' @param instId Instrument ID, e.g. BTC-USD-190927-5000-C.
+ #' @param tdMode Trade mode. Margin mode: \code{cross} or \code{isolated.} Non-Margin mode: \code{cash}.
+ #' @param side Order side, \code{buy} or \code{sell}.
+ #' @param sz Quantity to buy or sell.
+ #' @param ordType Order type. \code{market}: Market order, \code{limit}: Limit order, \code{post_only}: Post-only order,
+ #' \code{fok}: Fill-or-kill order, \code{ioc}: Immediate-or-cancel order,
+ #' \code{optimal_limit_ioc}: Market order with immediate-or-cancel order (applicable only to Futures and Perpetual swap).
+ #' @param process A function to process the data received from the API. Default to \code{identity}.
+ #' @param ... Other request parameters.
+ order = function(
+ instId, tdMode = c("isolated", "cross", "cash"), side = c("buy", "sell"), sz,
+ ordType = c("market", "limit", "post_only", "fok", "ioc", "optimal_limit_ioc"),
+ process = "identity", ...
+ ) {
+ tdMode <- match.arg(tdMode)
+ side <- match.arg(side)
+ ordType <- match.arg(ordType)
+
+ self$get_result(
+ api = "/api/v5/trade/order", method = "POST", process = process,
+ instId = instId, tdMode = tdMode, side = side, sz = sz, ordType = ordType, ...
+ )
+ },
+ #' @description See [Cancel order](https://www.okx.com/docs-v5/en/#rest-api-trade-cancel-order) for more information.
+ #' @param instId Instrument ID, e.g. BTC-USD-190927.
+ #' @param ordId Order ID, Either \code{ordId} or \code{clOrdId} is required. If both are passed, \code{ordId} will be used.
+ #' @param clOrdId Client Order ID as assigned by the client.
+ #' @param process A function to process the data received from the API. Default to \code{identity}.
+ #' @param ... Other request parameters.
+ cancel_order = function(instId, ordId, clOrdId, process = "identity", ...) {
+ if (missing(ordId)) ordId <- NA
+ if (missing(clOrdId)) clOrdId <- NA
+ self$get_result(
+ api = "/api/v5/trade/cancel-order", method = "POST", process = process,
+ instId = instId, ordId = ordId, clOrdId = clOrdId, ...
+ )
+ }
+ )
+)
+
+#' @title restAPIaccount Class
+#'
+#' @description Wrapper for [REST API ACCOUNT](https://www.okx.com/docs-v5/en/#rest-api-account).
+#'
+#' @import R6
+#' @export
+restAPIaccount <- R6::R6Class(
+ "restAPIaccount",
+ inherit = restAPI,
+ public = list(
+ #' @description See [Get balance](https://www.okx.com/docs-v5/en/#rest-api-account-get-balance) for more information.
+ #' @param ccy Single currency or a vector composed of multiple currencies. (no more than 20).
+ #' @param process A function to process the data received from the API. Default to \code{identity}.
+ balance = function(ccy, process = "identity") {
+ self$get_result(
+ api = "/api/v5/account/balance", method = "GET", process = process,
+ ccy = ccy
+ )
+ },
+ #' @description See [Get positions](https://www.okx.com/docs-v5/en/#rest-api-account-get-positions) for more information.
+ #' @param process A function to process the data received from the API. Default to \code{identity}.
+ #' @param ... Other request parameters.
+ positions = function(process = "identity", ...) {
+ self$get_result(
+ api = "/api/v5/account/positions", method = "GET", process = process,
+ ...
+ )
+ },
+ #' @description See [Get positions history](https://www.okx.com/docs-v5/en/#rest-api-account-get-positions-history) for more information.
+ #' @param process A function to process the data received from the API. Default to \code{identity}.
+ #' @param ... Other request parameters.
+ positions_history = function(process = "identity", ...) {
+ self$get_result(
+ api = "/api/v5/account/positions-history", method = "GET", process = process,
+ ...
+ )
+ }
+ )
+)
+
+
+#' @title restAPImarket Class
+#'
+#' @description Wrapper for [REST API MARKET](https://www.okx.com/docs-v5/en/#rest-api-market-data).
+#'
+#' @import R6
+#' @export
+restAPImarket <- R6::R6Class(
+ "restAPImarket",
+ inherit = restAPI,
+ public = list(
+ #' @description See [Get candlesticks](https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks) for more information.
+ #' @param instId Instrument ID, e.g. BTC-USD-190927-5000-C.
+ #' @param process A function to process the data received from the API. Default to \code{identity}.
+ #' @param ... Other request parameters.
+ candles = function(instId, process = "identity", ...) {
+ self$get_result(
+ api = "/api/v5/market/candles", method = "GET", process = process,
+ instId = instId, ...
+ )
+ },
+ #' @description See [Get candlesticks history](https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks-history) for more information.
+ #' @param instId Instrument ID, e.g. BTC-USD-190927-5000-C.
+ #' @param process A function to process the data received from the API. Default to \code{identity}.
+ #' @param ... Other request parameters.
+ history_candles = function(instId, process = "identity", ...) {
+ self$get_result(
+ api = "/api/v5/market/history-candles", method = "GET", process = process,
+ instId = instId, ...
+ )
+ }
+ )
+)
diff --git a/R/utils.R b/R/utils.R
new file mode 100644
index 0000000..286410a
--- /dev/null
+++ b/R/utils.R
@@ -0,0 +1,30 @@
+
+ts2time <- function(timestamp) {
+ timestamp <- substr(as.character(timestamp), 1, 10)
+ as.POSIXct(as.integer(timestamp), origin = "1970-01-01 00:00:00", tz = "Asia/Shanghai")
+}
+
+
+time2ts <- function(time, type = c("s", "ms")) {
+ if (!inherits(time, "POSIXt")) {
+ stop("parameter time must be of POSIXt type")
+ } else {
+ type <- match.arg(type)
+ time <- as.integer(time)
+ if (type == "ms") {
+ time <- time * 1000
+ }
+ time
+ }
+}
+
+
+str2period <- function(str) {
+ time_vec <- c(
+ "1m" = 60, "3m" = 3*60, "5m" = 5*60, "15m" = 15*60, "30m" = 30*60,
+ "1H" = 1*60*60, "2H" = 2*60*60, "4H" = 4*60*60,
+ "6H" = 6*60*60, "12H" = 12*60*60,
+ "1D" = 1*24*60*60, "2D" = 2*24*60*60, "3D" = 3*24*60*60
+ )
+ time_vec[str]
+}
diff --git a/R/websockerAPIprivate.R b/R/websockerAPIprivate.R
new file mode 100644
index 0000000..da6bd84
--- /dev/null
+++ b/R/websockerAPIprivate.R
@@ -0,0 +1,161 @@
+#' @title websocketAPIprivate Class
+#'
+#' @description Private channel of WebSocket API for [Okx exchange v5 API](https://www.okx.com/docs-v5/en/).
+#' See [Private Channel](https://www.okx.com/docs-v5/en/#websocket-api-private-channel) for more information.
+#'
+#' @examples
+#' \dontrun{
+#' tmp <- websocketAPIprivate$new(api_key, secret_key, passphrase)
+#' tmp$connect()
+#' Sys.sleep(1)
+#' tmp$login()
+#'
+#' # subscribe account information
+#' msg <- list(
+#' op = "subscribe",
+#' args = list(
+#' list(channel = "account", ccy = "USDT")
+#' )
+#' )
+#' msg <- jsonlite::toJSON(msg, auto_unbox = TRUE, pretty = TRUE)
+#' tmp$send(msg)
+#'
+#' # pass your own callback function
+#' tmp$on_message(function(event) {
+#' if (event$data == "pong") {
+#' cat("Bingo!!\n")
+#' }
+#' })
+#' tmp$send("ping")
+#'
+#' tmp$close()
+#' }
+#'
+#' @import R6 websocket base64enc digest
+#' @export
+websocketAPIprivate <- R6::R6Class(
+ "websockerAPIprivate",
+ public = list(
+ #' @field channel Private WebSocket url.
+ channel = "wss://ws.okx.com:8443/ws/v5/private",
+ #' @field api_key Okx API key.
+ api_key = NA,
+ #' @field secret_key Okx API secret key.
+ secret_key = NA,
+ #' @field passphrase Okx API passphrase.
+ passphrase = NA,
+ #' @field simulate Whether to use demo trading service.
+ simulate = NA,
+ #' @field ws A websocket::WebSocket object to establish a connection to the server.
+ ws = NA,
+ #' @description Craeate a new websocketAPIprivate object.
+ #' @param api_key Okx API key.
+ #' @param secret_key Okx API secret key.
+ #' @param passphrase Okx API passphrase.
+ #' @param simulate Whether to use demo trading service.
+ initialize = function(api_key, secret_key, passphrase, simulate = FALSE) {
+ self$api_key <- api_key
+ self$secret_key <- secret_key
+ self$passphrase <- passphrase
+ self$simulate <- simulate
+ if (simulate) self$channel <- "wss://wspap.okx.com:8443/ws/v5/private?brokerId=9999"
+ self$ws <- websocket::WebSocket$new(self$channel, autoConnect = FALSE)
+ },
+ #' @description Get UTC timestamp.
+ get_timestamp = function() {
+ as.integer(Sys.time())
+ },
+ #' @description Get the signing messages.
+ #' @param timestamp Retrieve through method \code{get_timestamp}.
+ get_message = function(timestamp) {
+ paste0(timestamp, "GET", "/users/self/verify")
+ },
+ #' @description Get the signature.
+ #' @param secret_key Okx API secret key.
+ #' @param msg Retrieve through method \code{get_message}.
+ get_signature = function(secret_key, msg) {
+ base64enc::base64encode(digest::hmac(
+ secret_key, msg, algo = "sha256", raw = TRUE
+ ))
+ },
+ #' @description Initiate the connection to the server.
+ connect = function() {
+ self$ws$onOpen(function(event) {
+ cat("Connection opened\n")
+ })
+
+ self$ws$onMessage(function(event) {
+ cat("Client got msg: ", event$data, "\n")
+ })
+
+ self$ws$onClose(function(event) {
+ cat("Client disconnected with code ", event$code, ": ", event$reason, "\n")
+ })
+
+ self$ws$onError(function(event) {
+ cat("Client failed to connect: ", event$message, "\n")
+ })
+
+ self$ws$connect()
+ },
+ #' @description Log in.
+ login = function() {
+ status <- attr(self$ws$readyState(), "description") == "Open"
+ if (status) {
+ timestamp <- self$get_timestamp()
+ msg <- self$get_message(timestamp)
+ signature <- self$get_signature(self$secret_key, msg)
+
+ login_msg <- list(
+ "op" = "login",
+ "args" = list(
+ list(
+ "apiKey" = self$api_key,
+ "passphrase" = self$passphrase,
+ "timestamp" = timestamp,
+ "sign" = signature
+ )
+ )
+ )
+ login_msg <- jsonlite::toJSON(login_msg, auto_unbox = TRUE)
+ self$ws$send(login_msg)
+ } else {
+ stop("Connection is not open")
+ }
+ },
+ #' @description Called when the connection is established.
+ #' @param func A Callback function.
+ on_open = function(func) {
+ self$ws$onOpen(func)
+ },
+ #' @description Called when a previously-opened connection is closed.
+ #' The event will have 'code' (integer) and 'reason' (one-element character)
+ #' elements that describe the remote's reason for closing.
+ #' @param func A Callback function.
+ on_close = function(func) {
+ self$ws$onClose(func)
+ },
+ #' @description Called each time a message is received from the server.
+ #' The event will have a 'data' element, which is the message content.
+ #' @param func A Callback function.
+ on_message = function(func) {
+ self$ws$onMessage(func)
+ },
+ #' @description Called when the connection fails to be established.
+ #' The event will have an 'message' element, a character vector of length 1
+ #' describing the reason for the error.
+ #' @param func A Callback function.
+ on_error = function(func) {
+ self$ws$onError(func)
+ },
+ #' @description Send a message to the server.
+ #' @param msg Messages.
+ send = function(msg) {
+ self$ws$send(msg)
+ },
+ #' @description Close the connection.
+ close = function() {
+ self$ws$close()
+ }
+ )
+)
diff --git a/R/websocketAPIpublic.R b/R/websocketAPIpublic.R
new file mode 100644
index 0000000..a0985e5
--- /dev/null
+++ b/R/websocketAPIpublic.R
@@ -0,0 +1,106 @@
+#' @title websocketAPIpublic Class
+#'
+#' @description Public channel of WebSocket API for [Okx exchange v5 API](https://www.okx.com/docs-v5/en/).
+#' See [Public Channel](https://www.okx.com/docs-v5/en/#websocket-api-public-channel) for more information.
+#'
+#' @examples
+#' \dontrun{
+#' tmp <- websocketAPIpublic$new()
+#' tmp$connect()
+#'
+#' # subscribe BTC-USDT-SWAP 5m candlesticks data
+#' msg <- list(
+#' op = "unsubscribe",
+#' args = list(
+#' list(channel = "candle5m", instId = "BTC-USDT-SWAP")
+#' )
+#' )
+#' msg <- jsonlite::toJSON(msg, auto_unbox = TRUE, pretty = TRUE)
+#' tmp$send(msg)
+#'
+#' # pass your own callback function
+#' tmp$on_message(function(event) {
+#' if (event$data == "pong") {
+#' cat("Bingo!!\n")
+#' }
+#' })
+#' tmp$send("ping")
+#'
+#' tmp$close()
+#' }
+#'
+#' @import R6 websocket
+#' @export
+websocketAPIpublic <- R6::R6Class(
+ "websocketAPIpublic",
+ public = list(
+ #' @field channel Public WebSocket url.
+ channel = "wss://ws.okx.com:8443/ws/v5/public",
+ #' @field simulate Whether to use demo trading service.
+ simulate = NA,
+ #' @field ws A websocket::WebSocket object to establish a connection to the server.
+ ws = NA,
+ #' @description Create a new websocketAPIpublic object.
+ #' @param simulate Whether to use demo trading service.
+ initialize = function(simulate = FALSE) {
+ self$simulate <- simulate
+ if (simulate) self$channel <- "wss://wspap.okx.com:8443/ws/v5/public?brokerId=9999"
+ self$ws <- websocket::WebSocket$new(self$channel, autoConnect = FALSE)
+ },
+ #' @description Initiate the connection to the server.
+ connect = function() {
+ self$ws$onOpen(function(event) {
+ cat("Connection opened\n")
+ })
+
+ self$ws$onMessage(function(event) {
+ cat("Client got msg: ", event$data, "\n")
+ })
+
+ self$ws$onClose(function(event) {
+ cat("Client disconnected with code ", event$code, ": ", event$reason, "\n")
+ })
+
+ self$ws$onError(function(event) {
+ cat("Client failed to connect: ", event$message, "\n")
+ })
+
+ self$ws$connect()
+ },
+ #' @description Called when the connection is established.
+ #' @param func A Callback function.
+ on_open = function(func) {
+ self$ws$onOpen(func)
+ },
+ #' @description Called when a previously-opened connection is closed.
+ #' The event will have 'code' (integer) and 'reason' (one-element character)
+ #' elements that describe the remote's reason for closing.
+ #' @param func A Callback function.
+ on_close = function(func) {
+ self$ws$onClose(func)
+ },
+ #' @description Called each time a message is received from the server.
+ #' The event will have a 'data' element, which is the message content.
+ #' @param func A Callback function.
+ on_message = function(func) {
+ self$ws$onMessage(func)
+ },
+ #' @description Called when the connection fails to be established.
+ #' The event will have an 'message' element, a character vector of length 1
+ #' describing the reason for the error.
+ #' @param func A Callback function.
+ on_error = function(func) {
+ self$ws$onError(func)
+ },
+ #' @description Send a message to the server.
+ #' @param msg Messages.
+ send = function(msg) {
+ self$ws$send(msg)
+ },
+ #' @description Close the connection.
+ close = function() {
+ self$ws$close()
+ }
+ )
+)
+
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..7d23178
--- /dev/null
+++ b/README.md
@@ -0,0 +1,130 @@
+# okxAPI
+
+An unofficial wrapper for [Okx exchange v5 API](https://www.okx.com/docs-v5/en/)
+
+## Installation
+
+You can install the released version of okxAPI from [CRAN](https://CRAN.R-project.org) with:
+
+``` r
+install.packages("okxAPI")
+```
+
+And the development version from [GitHub](https://github.com/) with:
+
+``` r
+# install.packages("devtools")
+devtools::install_github("fanggong/okxAPI")
+```
+
+## Requirements
+
+Please refer to [okx my api page](https://www.okx.com/account/my-api) regarding V5 API Key creation.
+
+## Example
+
+### REST API
+
+You can implement all REST API requests in Okx exchange by inheriting the `restAPI` class. For example, to implement [Get currencies](https://www.okx.com/docs-v5/en/#rest-api-funding-get-currencies), you can define the class and call the method as follows:
+
+``` r
+myRestAPI <- R6::R6Class(
+ inherit = restAPI,
+ public = list(
+ get_currencies = function(ccy, process = "identity") {
+ self$get_result(
+ api = "/api/v5/asset/currencies", method = "GET", process = process,
+ ccy = ccy
+ )
+ }
+ )
+)
+tmp <- myRestAPI$new(api_key, secret_key, passphrase)
+tmp$get_currencies("BTC")
+```
+
+For commonly used interfaces, they have been implemented in this package. The naming convention is as follows: for "/api/v5/AAA/BBB", a new class named `restAPIAAA`, which inherits from `restAPI`, has been defined in this package. The `BBB` method in this new class is used to call the API.
+
+### WebSocket API Public Channel
+
+A `websocketAPIpublic` class based on [websocket package](https://github.com/rstudio/websocket) is used here.
+
+Create new `websocketAPIpublic` object and initiate the connection to the server.
+
+``` r
+tmp <- websocketAPIpublic$new()
+tmp$connect()
+```
+
+Subscribe BTC-USDT-SWAP 5m candlesticks data.
+
+``` r
+msg <- list(
+ op = "subscribe",
+ args = list(
+ list(channel = "candle5m", instId = "BTC-USDT-SWAP")
+ )
+)
+msg <- jsonlite::toJSON(msg, auto_unbox = TRUE, pretty = TRUE)
+tmp$send(msg)
+```
+
+Pass your own callback function
+
+``` r
+tmp$on_message(function(event) {
+ if (event$data == "pong") {
+ cat("Bingo!!")
+ }
+})
+tmp$send("ping")
+```
+
+Close the connection.
+
+``` r
+tmp$close()
+```
+
+### WebSocket API Private Channel
+
+A `websocketAPIprivate` class based on [websocket package](https://github.com/rstudio/websocket) is used here.
+
+Create new `websocketAPIprivate` object and initiate the connection to the server.
+
+``` r
+tmp <- websocketAPIprivate$new(api_key, secret_key, passphrase)
+tmp$connect()
+Sys.sleep(1) # Waiting for connection success
+tmp$login()
+```
+
+Subscribe account information.
+
+``` r
+msg <- list(
+ op = "subscribe",
+ args = list(
+ list(channel = "account", ccy = "USDT")
+ )
+)
+msg <- jsonlite::toJSON(msg, auto_unbox = TRUE, pretty = TRUE)
+tmp$send(msg)
+```
+
+Pass your own callback function.
+
+``` r
+tmp$on_message(function(event) {
+ if (event$data == "pong") {
+ cat("Bingo!!")
+ }
+})
+tmp$send("ping")
+```
+
+Close the connection.
+
+``` r
+tmp$close()
+```
diff --git a/man/get_functions.Rd b/man/get_functions.Rd
new file mode 100644
index 0000000..57c0bf6
--- /dev/null
+++ b/man/get_functions.Rd
@@ -0,0 +1,12 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/funcs.R
+\name{get_functions}
+\alias{get_functions}
+\title{Wrapper for some frequently used APIs to get data easily}
+\description{
+The main purpose is to handle APIs that have limitations on the number of results returned per single request.
+}
+\seealso{
+\code{\link{get_positions_history}}
+\code{\link{get_history_candles}}
+}
diff --git a/man/get_history_candles.Rd b/man/get_history_candles.Rd
new file mode 100644
index 0000000..01b4aa7
--- /dev/null
+++ b/man/get_history_candles.Rd
@@ -0,0 +1,47 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/funcs.R
+\name{get_history_candles}
+\alias{get_history_candles}
+\title{Retrieve the candlestick charts}
+\usage{
+get_history_candles(
+ api_key,
+ secret_key,
+ passphrase,
+ bar = c("1m", "3m", "5m", "15m", "30m", "1H", "4H", "6H", "12H", "1D", "2D", "3D"),
+ count,
+ instId,
+ ...
+)
+}
+\arguments{
+\item{api_key}{Okx API key.}
+
+\item{secret_key}{Okx API secret key.}
+
+\item{passphrase}{Okx API passphrase.}
+
+\item{bar}{Bar size, the default is 1m, e.g. 1m/3m/5m/15m/30m/1H/2H/4H, Hong Kong time opening price k-line: 6H/12H/1D/2D/3D.}
+
+\item{count}{Number of Bars.}
+
+\item{instId}{Instrument ID, e.g. BTC-USDT-SWAP.}
+
+\item{...}{Other request parameters to be passed, See \href{https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks-history}{Get candlesticks history} for more information.}
+}
+\value{
+Candlestick charts data
+}
+\description{
+Wrapper for API \href{https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks}{Get candlesticks}
+and \href{https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks-history}{Get candlesticks history}.
+}
+\examples{
+\dontrun{
+candles <- get_history_candles(
+ api_key, secret_key, passphrase, bar = "1m",
+ count = 24*60, instId = "CFX-USDT-SWAP"
+)
+}
+
+}
diff --git a/man/get_positions_history.Rd b/man/get_positions_history.Rd
new file mode 100644
index 0000000..394858d
--- /dev/null
+++ b/man/get_positions_history.Rd
@@ -0,0 +1,45 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/funcs.R
+\name{get_positions_history}
+\alias{get_positions_history}
+\title{Retrieve the position data}
+\usage{
+get_positions_history(
+ api_key,
+ secret_key,
+ passphrase,
+ count = 90,
+ period = 10,
+ ...
+)
+}
+\arguments{
+\item{api_key}{Okx API key.}
+
+\item{secret_key}{Okx API secret key.}
+
+\item{passphrase}{Okx API passphrase.}
+
+\item{count}{Retrieve position data for a specified number of past days, with a maximum of 90(days)}
+
+\item{period}{Due to the 'Number of results per request' limitation of the API,
+the \code{period} parameter must be specified to ensure that the number of position data entries within each period does not exceed 100.}
+
+\item{...}{Other request parameters to be passed, See
+\href{https://www.okx.com/docs-v5/en/#rest-api-account-get-positions-history}{Get positions history} for more information.}
+}
+\value{
+Position data
+}
+\description{
+Wrapper for API \href{https://www.okx.com/docs-v5/en/#rest-api-account-get-positions-history}{Get positions history}.
+}
+\examples{
+\dontrun{
+positions <- get_positions_history(
+ api_key, secret_key, passphrase, count = 90, period = 10,
+ instType = "SWAP", mgnMode = "isolated"
+)
+}
+
+}
diff --git a/man/restAPI.Rd b/man/restAPI.Rd
new file mode 100644
index 0000000..2cd159d
--- /dev/null
+++ b/man/restAPI.Rd
@@ -0,0 +1,247 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/restAPI.R
+\name{restAPI}
+\alias{restAPI}
+\title{restAPI Class}
+\description{
+Base class for \href{https://www.okx.com/docs-v5/en/}{Okx exchange v5 API}.
+}
+\details{
+You can implement all REST API requests in Okx exchange by inheriting the \code{restAPI} class.
+Please refer to the example provided at the end of the document.
+
+For commonly used interfaces, they have been implemented in this package.
+The naming convention is as follows: for "/api/v5/AAA/BBB", a new class named \code{restAPIAAA},
+which inherits from \code{restAPI}, has been defined in this package.
+The \code{BBB} method in this new class is used to call the API.
+}
+\examples{
+\dontrun{
+# for [Get currencies](https://www.okx.com/docs-v5/en/#rest-api-funding-get-currencies)
+# you can define the class like this
+myRestAPI <- R6::R6Class(
+ inherit = restAPI,
+ public = list(
+ get_currencies = function(ccy, process = "identity") {
+ self$get_result(
+ api = "/api/v5/asset/currencies", method = "GET", process = process,
+ ccy = ccy
+ )
+ }
+ )
+)
+# And call it like this
+tmp <- myRestAPI$new(api_key, secret_key, passphrase)
+tmp$get_currencies("BTC")
+}
+
+}
+\seealso{
+\code{\link{restAPItrade}}
+\code{\link{restAPIaccount}}
+\code{\link{restAPImarket}}
+}
+\section{Public fields}{
+\if{html}{\out{}}
+\describe{
+\item{\code{url}}{Okx REST API url, which is https://www.okx.com.}
+
+\item{\code{api_key}}{Okx API key.}
+
+\item{\code{secret_key}}{Okx API secret key.}
+
+\item{\code{passphrase}}{Okx API passphrase.}
+
+\item{\code{simulate}}{Whether to use demo trading service.}
+}
+\if{html}{\out{
}}
+}
+\section{Methods}{
+\subsection{Public methods}{
+\itemize{
+\item \href{#method-restAPI-new}{\code{restAPI$new()}}
+\item \href{#method-restAPI-get_timestamp}{\code{restAPI$get_timestamp()}}
+\item \href{#method-restAPI-get_request_path}{\code{restAPI$get_request_path()}}
+\item \href{#method-restAPI-get_body}{\code{restAPI$get_body()}}
+\item \href{#method-restAPI-get_message}{\code{restAPI$get_message()}}
+\item \href{#method-restAPI-get_signature}{\code{restAPI$get_signature()}}
+\item \href{#method-restAPI-get_header}{\code{restAPI$get_header()}}
+\item \href{#method-restAPI-get_result}{\code{restAPI$get_result()}}
+\item \href{#method-restAPI-clone}{\code{restAPI$clone()}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPI-new}{}}}
+\subsection{Method \code{new()}}{
+Create a new REST API object.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPI$new(api_key, secret_key, passphrase, simulate = FALSE)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{api_key}}{Okx API key.}
+
+\item{\code{secret_key}}{Okx API secret key.}
+
+\item{\code{passphrase}}{Okx API passphrase.}
+
+\item{\code{simulate}}{Whether to use demo trading service.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPI-get_timestamp}{}}}
+\subsection{Method \code{get_timestamp()}}{
+Get UTC timestamp.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPI$get_timestamp()}\if{html}{\out{
}}
+}
+
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPI-get_request_path}{}}}
+\subsection{Method \code{get_request_path()}}{
+Get request path.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPI$get_request_path(api, method = c("GET", "POST"), ...)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{api}}{Request api e.g. /api/v5/account/positions-history.}
+
+\item{\code{method}}{Request method, \code{GET} or \code{POST}.}
+
+\item{\code{...}}{Other request parameters.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPI-get_body}{}}}
+\subsection{Method \code{get_body()}}{
+Get request body.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPI$get_body(method = c("GET", "POST"), ...)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{method}}{Request method, \code{GET} or \code{POST}.}
+
+\item{\code{...}}{Other request parameters.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPI-get_message}{}}}
+\subsection{Method \code{get_message()}}{
+Get the signing messages.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPI$get_message(timestamp, request_path, body, method = c("GET", "POST"))}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{timestamp}}{Retrieve through method \code{get_timestamp}.}
+
+\item{\code{request_path}}{Retrieve through method \code{get_request_path}.}
+
+\item{\code{body}}{Retrieve through method \code{get_body}.}
+
+\item{\code{method}}{Request method, \code{GET} or \code{POST}.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPI-get_signature}{}}}
+\subsection{Method \code{get_signature()}}{
+Get the signature.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPI$get_signature(msg, secret_key = self$secret_key)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{msg}}{Retrieve through method \code{get_message}.}
+
+\item{\code{secret_key}}{Okx API secret key.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPI-get_header}{}}}
+\subsection{Method \code{get_header()}}{
+Get request headers.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPI$get_header(timestamp, msg)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{timestamp}}{Retrieve through method \code{get_timestamp}.}
+
+\item{\code{msg}}{Retrieve through method \code{get_message}.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPI-get_result}{}}}
+\subsection{Method \code{get_result()}}{
+Retrieve data from api.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPI$get_result(api, method = c("GET", "POST"), process, ...)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{api}}{Request api e.g. /api/v5/account/positions-history.}
+
+\item{\code{method}}{Request method, \code{GET} or \code{POST}.}
+
+\item{\code{process}}{A function to process the data received from the API.}
+
+\item{\code{...}}{Other request parameters.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPI-clone}{}}}
+\subsection{Method \code{clone()}}{
+The objects of this class are cloneable with this method.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPI$clone(deep = FALSE)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{deep}}{Whether to make a deep clone.}
+}
+\if{html}{\out{
}}
+}
+}
+}
diff --git a/man/restAPIaccount.Rd b/man/restAPIaccount.Rd
new file mode 100644
index 0000000..e8a8094
--- /dev/null
+++ b/man/restAPIaccount.Rd
@@ -0,0 +1,109 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/restAPI.R
+\name{restAPIaccount}
+\alias{restAPIaccount}
+\title{restAPIaccount Class}
+\description{
+Wrapper for \href{https://www.okx.com/docs-v5/en/#rest-api-account}{REST API ACCOUNT}.
+}
+\section{Super class}{
+\code{\link[okxAPI:restAPI]{okxAPI::restAPI}} -> \code{restAPIaccount}
+}
+\section{Methods}{
+\subsection{Public methods}{
+\itemize{
+\item \href{#method-restAPIaccount-balance}{\code{restAPIaccount$balance()}}
+\item \href{#method-restAPIaccount-positions}{\code{restAPIaccount$positions()}}
+\item \href{#method-restAPIaccount-positions_history}{\code{restAPIaccount$positions_history()}}
+\item \href{#method-restAPIaccount-clone}{\code{restAPIaccount$clone()}}
+}
+}
+\if{html}{\out{
+Inherited methods
+
+
+}}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPIaccount-balance}{}}}
+\subsection{Method \code{balance()}}{
+See \href{https://www.okx.com/docs-v5/en/#rest-api-account-get-balance}{Get balance} for more information.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPIaccount$balance(ccy, process = "identity")}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{ccy}}{Single currency or a vector composed of multiple currencies. (no more than 20).}
+
+\item{\code{process}}{A function to process the data received from the API. Default to \code{identity}.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPIaccount-positions}{}}}
+\subsection{Method \code{positions()}}{
+See \href{https://www.okx.com/docs-v5/en/#rest-api-account-get-positions}{Get positions} for more information.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPIaccount$positions(process = "identity", ...)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{process}}{A function to process the data received from the API. Default to \code{identity}.}
+
+\item{\code{...}}{Other request parameters.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPIaccount-positions_history}{}}}
+\subsection{Method \code{positions_history()}}{
+See \href{https://www.okx.com/docs-v5/en/#rest-api-account-get-positions-history}{Get positions history} for more information.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPIaccount$positions_history(process = "identity", ...)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{process}}{A function to process the data received from the API. Default to \code{identity}.}
+
+\item{\code{...}}{Other request parameters.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPIaccount-clone}{}}}
+\subsection{Method \code{clone()}}{
+The objects of this class are cloneable with this method.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPIaccount$clone(deep = FALSE)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{deep}}{Whether to make a deep clone.}
+}
+\if{html}{\out{
}}
+}
+}
+}
diff --git a/man/restAPImarket.Rd b/man/restAPImarket.Rd
new file mode 100644
index 0000000..8ecf313
--- /dev/null
+++ b/man/restAPImarket.Rd
@@ -0,0 +1,93 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/restAPI.R
+\name{restAPImarket}
+\alias{restAPImarket}
+\title{restAPImarket Class}
+\description{
+Wrapper for \href{https://www.okx.com/docs-v5/en/#rest-api-market-data}{REST API MARKET}.
+}
+\section{Super class}{
+\code{\link[okxAPI:restAPI]{okxAPI::restAPI}} -> \code{restAPImarket}
+}
+\section{Methods}{
+\subsection{Public methods}{
+\itemize{
+\item \href{#method-restAPImarket-candles}{\code{restAPImarket$candles()}}
+\item \href{#method-restAPImarket-history_candles}{\code{restAPImarket$history_candles()}}
+\item \href{#method-restAPImarket-clone}{\code{restAPImarket$clone()}}
+}
+}
+\if{html}{\out{
+Inherited methods
+
+
+}}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPImarket-candles}{}}}
+\subsection{Method \code{candles()}}{
+See \href{https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks}{Get candlesticks} for more information.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPImarket$candles(instId, process = "identity", ...)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{instId}}{Instrument ID, e.g. BTC-USD-190927-5000-C.}
+
+\item{\code{process}}{A function to process the data received from the API. Default to \code{identity}.}
+
+\item{\code{...}}{Other request parameters.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPImarket-history_candles}{}}}
+\subsection{Method \code{history_candles()}}{
+See \href{https://www.okx.com/docs-v5/en/#rest-api-market-data-get-candlesticks-history}{Get candlesticks history} for more information.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPImarket$history_candles(instId, process = "identity", ...)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{instId}}{Instrument ID, e.g. BTC-USD-190927-5000-C.}
+
+\item{\code{process}}{A function to process the data received from the API. Default to \code{identity}.}
+
+\item{\code{...}}{Other request parameters.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPImarket-clone}{}}}
+\subsection{Method \code{clone()}}{
+The objects of this class are cloneable with this method.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPImarket$clone(deep = FALSE)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{deep}}{Whether to make a deep clone.}
+}
+\if{html}{\out{
}}
+}
+}
+}
diff --git a/man/restAPItrade.Rd b/man/restAPItrade.Rd
new file mode 100644
index 0000000..a94bed1
--- /dev/null
+++ b/man/restAPItrade.Rd
@@ -0,0 +1,115 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/restAPI.R
+\name{restAPItrade}
+\alias{restAPItrade}
+\title{restAPItrade Class}
+\description{
+Wrapper for \href{https://www.okx.com/docs-v5/en/#rest-api-trade}{REST API TRADE}.
+}
+\section{Super class}{
+\code{\link[okxAPI:restAPI]{okxAPI::restAPI}} -> \code{restAPItrade}
+}
+\section{Methods}{
+\subsection{Public methods}{
+\itemize{
+\item \href{#method-restAPItrade-order}{\code{restAPItrade$order()}}
+\item \href{#method-restAPItrade-cancel_order}{\code{restAPItrade$cancel_order()}}
+\item \href{#method-restAPItrade-clone}{\code{restAPItrade$clone()}}
+}
+}
+\if{html}{\out{
+Inherited methods
+
+
+}}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPItrade-order}{}}}
+\subsection{Method \code{order()}}{
+See \href{https://www.okx.com/docs-v5/en/#rest-api-trade-place-order}{Place order} for more information.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPItrade$order(
+ instId,
+ tdMode = c("isolated", "cross", "cash"),
+ side = c("buy", "sell"),
+ sz,
+ ordType = c("market", "limit", "post_only", "fok", "ioc", "optimal_limit_ioc"),
+ process = "identity",
+ ...
+)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{instId}}{Instrument ID, e.g. BTC-USD-190927-5000-C.}
+
+\item{\code{tdMode}}{Trade mode. Margin mode: \code{cross} or \code{isolated.} Non-Margin mode: \code{cash}.}
+
+\item{\code{side}}{Order side, \code{buy} or \code{sell}.}
+
+\item{\code{sz}}{Quantity to buy or sell.}
+
+\item{\code{ordType}}{Order type. \code{market}: Market order, \code{limit}: Limit order, \code{post_only}: Post-only order,
+\code{fok}: Fill-or-kill order, \code{ioc}: Immediate-or-cancel order,
+\code{optimal_limit_ioc}: Market order with immediate-or-cancel order (applicable only to Futures and Perpetual swap).}
+
+\item{\code{process}}{A function to process the data received from the API. Default to \code{identity}.}
+
+\item{\code{...}}{Other request parameters.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPItrade-cancel_order}{}}}
+\subsection{Method \code{cancel_order()}}{
+See \href{https://www.okx.com/docs-v5/en/#rest-api-trade-cancel-order}{Cancel order} for more information.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPItrade$cancel_order(instId, ordId, clOrdId, process = "identity", ...)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{instId}}{Instrument ID, e.g. BTC-USD-190927.}
+
+\item{\code{ordId}}{Order ID, Either \code{ordId} or \code{clOrdId} is required. If both are passed, \code{ordId} will be used.}
+
+\item{\code{clOrdId}}{Client Order ID as assigned by the client.}
+
+\item{\code{process}}{A function to process the data received from the API. Default to \code{identity}.}
+
+\item{\code{...}}{Other request parameters.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-restAPItrade-clone}{}}}
+\subsection{Method \code{clone()}}{
+The objects of this class are cloneable with this method.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{restAPItrade$clone(deep = FALSE)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{deep}}{Whether to make a deep clone.}
+}
+\if{html}{\out{
}}
+}
+}
+}
diff --git a/man/websocketAPIprivate.Rd b/man/websocketAPIprivate.Rd
new file mode 100644
index 0000000..ae9862d
--- /dev/null
+++ b/man/websocketAPIprivate.Rd
@@ -0,0 +1,280 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/websockerAPIprivate.R
+\name{websocketAPIprivate}
+\alias{websocketAPIprivate}
+\title{websocketAPIprivate Class}
+\description{
+Private channel of WebSocket API for \href{https://www.okx.com/docs-v5/en/}{Okx exchange v5 API}.
+See \href{https://www.okx.com/docs-v5/en/#websocket-api-private-channel}{Private Channel} for more information.
+}
+\examples{
+\dontrun{
+tmp <- websocketAPIprivate$new(api_key, secret_key, passphrase)
+tmp$connect()
+Sys.sleep(1)
+tmp$login()
+
+# subscribe account information
+msg <- list(
+ op = "subscribe",
+ args = list(
+ list(channel = "account", ccy = "USDT")
+ )
+)
+msg <- jsonlite::toJSON(msg, auto_unbox = TRUE, pretty = TRUE)
+tmp$send(msg)
+
+# pass your own callback function
+tmp$on_message(function(event) {
+ if (event$data == "pong") {
+ cat("Bingo!!\n")
+ }
+})
+tmp$send("ping")
+
+tmp$close()
+}
+
+}
+\section{Public fields}{
+\if{html}{\out{}}
+\describe{
+\item{\code{channel}}{Private WebSocket url.}
+
+\item{\code{api_key}}{Okx API key.}
+
+\item{\code{secret_key}}{Okx API secret key.}
+
+\item{\code{passphrase}}{Okx API passphrase.}
+
+\item{\code{simulate}}{Whether to use demo trading service.}
+
+\item{\code{ws}}{A websocket::WebSocket object to establish a connection to the server.}
+}
+\if{html}{\out{
}}
+}
+\section{Methods}{
+\subsection{Public methods}{
+\itemize{
+\item \href{#method-websockerAPIprivate-new}{\code{websocketAPIprivate$new()}}
+\item \href{#method-websockerAPIprivate-get_timestamp}{\code{websocketAPIprivate$get_timestamp()}}
+\item \href{#method-websockerAPIprivate-get_message}{\code{websocketAPIprivate$get_message()}}
+\item \href{#method-websockerAPIprivate-get_signature}{\code{websocketAPIprivate$get_signature()}}
+\item \href{#method-websockerAPIprivate-connect}{\code{websocketAPIprivate$connect()}}
+\item \href{#method-websockerAPIprivate-login}{\code{websocketAPIprivate$login()}}
+\item \href{#method-websockerAPIprivate-on_open}{\code{websocketAPIprivate$on_open()}}
+\item \href{#method-websockerAPIprivate-on_close}{\code{websocketAPIprivate$on_close()}}
+\item \href{#method-websockerAPIprivate-on_message}{\code{websocketAPIprivate$on_message()}}
+\item \href{#method-websockerAPIprivate-on_error}{\code{websocketAPIprivate$on_error()}}
+\item \href{#method-websockerAPIprivate-send}{\code{websocketAPIprivate$send()}}
+\item \href{#method-websockerAPIprivate-close}{\code{websocketAPIprivate$close()}}
+\item \href{#method-websockerAPIprivate-clone}{\code{websocketAPIprivate$clone()}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-new}{}}}
+\subsection{Method \code{new()}}{
+Craeate a new websocketAPIprivate object.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$new(api_key, secret_key, passphrase, simulate = FALSE)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{api_key}}{Okx API key.}
+
+\item{\code{secret_key}}{Okx API secret key.}
+
+\item{\code{passphrase}}{Okx API passphrase.}
+
+\item{\code{simulate}}{Whether to use demo trading service.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-get_timestamp}{}}}
+\subsection{Method \code{get_timestamp()}}{
+Get UTC timestamp.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$get_timestamp()}\if{html}{\out{
}}
+}
+
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-get_message}{}}}
+\subsection{Method \code{get_message()}}{
+Get the signing messages.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$get_message(timestamp)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{timestamp}}{Retrieve through method \code{get_timestamp}.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-get_signature}{}}}
+\subsection{Method \code{get_signature()}}{
+Get the signature.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$get_signature(secret_key, msg)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{secret_key}}{Okx API secret key.}
+
+\item{\code{msg}}{Retrieve through method \code{get_message}.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-connect}{}}}
+\subsection{Method \code{connect()}}{
+Initiate the connection to the server.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$connect()}\if{html}{\out{
}}
+}
+
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-login}{}}}
+\subsection{Method \code{login()}}{
+Log in.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$login()}\if{html}{\out{
}}
+}
+
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-on_open}{}}}
+\subsection{Method \code{on_open()}}{
+Called when the connection is established.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$on_open(func)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{func}}{A Callback function.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-on_close}{}}}
+\subsection{Method \code{on_close()}}{
+Called when a previously-opened connection is closed.
+The event will have 'code' (integer) and 'reason' (one-element character)
+elements that describe the remote's reason for closing.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$on_close(func)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{func}}{A Callback function.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-on_message}{}}}
+\subsection{Method \code{on_message()}}{
+Called each time a message is received from the server.
+The event will have a 'data' element, which is the message content.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$on_message(func)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{func}}{A Callback function.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-on_error}{}}}
+\subsection{Method \code{on_error()}}{
+Called when the connection fails to be established.
+The event will have an 'message' element, a character vector of length 1
+describing the reason for the error.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$on_error(func)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{func}}{A Callback function.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-send}{}}}
+\subsection{Method \code{send()}}{
+Send a message to the server.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$send(msg)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{msg}}{Messages.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-close}{}}}
+\subsection{Method \code{close()}}{
+Close the connection.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$close()}\if{html}{\out{
}}
+}
+
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websockerAPIprivate-clone}{}}}
+\subsection{Method \code{clone()}}{
+The objects of this class are cloneable with this method.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIprivate$clone(deep = FALSE)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{deep}}{Whether to make a deep clone.}
+}
+\if{html}{\out{
}}
+}
+}
+}
diff --git a/man/websocketAPIpublic.Rd b/man/websocketAPIpublic.Rd
new file mode 100644
index 0000000..f645259
--- /dev/null
+++ b/man/websocketAPIpublic.Rd
@@ -0,0 +1,206 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/websocketAPIpublic.R
+\name{websocketAPIpublic}
+\alias{websocketAPIpublic}
+\title{websocketAPIpublic Class}
+\description{
+Public channel of WebSocket API for \href{https://www.okx.com/docs-v5/en/}{Okx exchange v5 API}.
+See \href{https://www.okx.com/docs-v5/en/#websocket-api-public-channel}{Public Channel} for more information.
+}
+\examples{
+\dontrun{
+tmp <- websocketAPIpublic$new()
+tmp$connect()
+
+# subscribe BTC-USDT-SWAP 5m candlesticks data
+msg <- list(
+ op = "unsubscribe",
+ args = list(
+ list(channel = "candle5m", instId = "BTC-USDT-SWAP")
+ )
+)
+msg <- jsonlite::toJSON(msg, auto_unbox = TRUE, pretty = TRUE)
+tmp$send(msg)
+
+# pass your own callback function
+tmp$on_message(function(event) {
+ if (event$data == "pong") {
+ cat("Bingo!!\n")
+ }
+})
+tmp$send("ping")
+
+tmp$close()
+}
+
+}
+\section{Public fields}{
+\if{html}{\out{}}
+\describe{
+\item{\code{channel}}{Public WebSocket url.}
+
+\item{\code{simulate}}{Whether to use demo trading service.}
+
+\item{\code{ws}}{A websocket::WebSocket object to establish a connection to the server.}
+}
+\if{html}{\out{
}}
+}
+\section{Methods}{
+\subsection{Public methods}{
+\itemize{
+\item \href{#method-websocketAPIpublic-new}{\code{websocketAPIpublic$new()}}
+\item \href{#method-websocketAPIpublic-connect}{\code{websocketAPIpublic$connect()}}
+\item \href{#method-websocketAPIpublic-on_open}{\code{websocketAPIpublic$on_open()}}
+\item \href{#method-websocketAPIpublic-on_close}{\code{websocketAPIpublic$on_close()}}
+\item \href{#method-websocketAPIpublic-on_message}{\code{websocketAPIpublic$on_message()}}
+\item \href{#method-websocketAPIpublic-on_error}{\code{websocketAPIpublic$on_error()}}
+\item \href{#method-websocketAPIpublic-send}{\code{websocketAPIpublic$send()}}
+\item \href{#method-websocketAPIpublic-close}{\code{websocketAPIpublic$close()}}
+\item \href{#method-websocketAPIpublic-clone}{\code{websocketAPIpublic$clone()}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websocketAPIpublic-new}{}}}
+\subsection{Method \code{new()}}{
+Create a new websocketAPIpublic object.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIpublic$new(simulate = FALSE)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{simulate}}{Whether to use demo trading service.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websocketAPIpublic-connect}{}}}
+\subsection{Method \code{connect()}}{
+Initiate the connection to the server.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIpublic$connect()}\if{html}{\out{
}}
+}
+
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websocketAPIpublic-on_open}{}}}
+\subsection{Method \code{on_open()}}{
+Called when the connection is established.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIpublic$on_open(func)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{func}}{A Callback function.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websocketAPIpublic-on_close}{}}}
+\subsection{Method \code{on_close()}}{
+Called when a previously-opened connection is closed.
+The event will have 'code' (integer) and 'reason' (one-element character)
+elements that describe the remote's reason for closing.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIpublic$on_close(func)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{func}}{A Callback function.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websocketAPIpublic-on_message}{}}}
+\subsection{Method \code{on_message()}}{
+Called each time a message is received from the server.
+The event will have a 'data' element, which is the message content.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIpublic$on_message(func)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{func}}{A Callback function.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websocketAPIpublic-on_error}{}}}
+\subsection{Method \code{on_error()}}{
+Called when the connection fails to be established.
+The event will have an 'message' element, a character vector of length 1
+describing the reason for the error.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIpublic$on_error(func)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{func}}{A Callback function.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websocketAPIpublic-send}{}}}
+\subsection{Method \code{send()}}{
+Send a message to the server.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIpublic$send(msg)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{msg}}{Messages.}
+}
+\if{html}{\out{
}}
+}
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websocketAPIpublic-close}{}}}
+\subsection{Method \code{close()}}{
+Close the connection.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIpublic$close()}\if{html}{\out{
}}
+}
+
+}
+\if{html}{\out{
}}
+\if{html}{\out{}}
+\if{latex}{\out{\hypertarget{method-websocketAPIpublic-clone}{}}}
+\subsection{Method \code{clone()}}{
+The objects of this class are cloneable with this method.
+\subsection{Usage}{
+\if{html}{\out{}}\preformatted{websocketAPIpublic$clone(deep = FALSE)}\if{html}{\out{
}}
+}
+
+\subsection{Arguments}{
+\if{html}{\out{}}
+\describe{
+\item{\code{deep}}{Whether to make a deep clone.}
+}
+\if{html}{\out{
}}
+}
+}
+}