diff --git a/NAMESPACE b/NAMESPACE index 30009a99..2a13093a 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -2,10 +2,10 @@ export("%>%") export(addBBands) +export(addEvents) export(addMA) export(addMACD) export(addRSI) -export(addVlines) export(addVolume) export(availableExchanges) export(availableIntervals) diff --git a/R/chart.R b/R/chart.R index 246aca82..16683aab 100644 --- a/R/chart.R +++ b/R/chart.R @@ -205,6 +205,7 @@ chart <- function( chart <- chart %>% plotly::layout( + margin = list(l = 60, r = 60, b = 110, t = 60), yaxis = list( title = 'Price' ), @@ -214,12 +215,12 @@ chart <- function( ) ), showlegend = TRUE, - legend = list(orientation = 'h', x = 0, y = 1), + legend = list(orientation = 'h', x = 0, y = 1.1), paper_bgcolor='rgba(0,0,0,0)', plot_bgcolor='rgba(0,0,0,0)' ) %>% plotly::add_annotations( x= 0, - y= 1, + y= 1.05, xref = "paper", yref = "paper", text = paste( diff --git a/R/chartEvent.R b/R/chartEvent.R new file mode 100644 index 00000000..cca86b7d --- /dev/null +++ b/R/chartEvent.R @@ -0,0 +1,102 @@ +#' add eventlines to +#' the chart +#' +#' @description +#' A short description... +#' +#' `r lifecycle::badge("experimental")` +#' +#' @param plot Chart +#' @param event a data.frame with index, event and colors. +#' +#' @example man/examples/scr_addEvents.R +#' +#' @family chart indicators +#' @export +addEvents <- function( + plot, + event +) { + + # check if class is + # data.frame or the likes of it + if (!inherits(event, 'data.frame')) { + + rlang::abort( + message = 'The event data has to be data.frame, or similar.' + ) + + } + + # check if the column names + # include event, labels, color + colnames(event) <- tolower( + colnames( + event + ) + ) + + if (sum(grepl(x = colnames(event),pattern = 'index|event|color')) != 3) { + + # determine the missing column names + # from the data + missing_cols <- setdiff( + c('index', 'event', 'color'), + colnames(event) + ) + + rlang::abort( + message = paste('Colum:', paste(collapse = ', ', missing_cols), 'are missing. Check your spelling, or add the columns.') + ) + + + } + + + # 1) extract the main + # chart from the plot + plot_ <- plot$main + + + + plot_ <- plotly::layout( + p = plot_, + shapes = do.call( + list, + lapply( + 1:nrow(event), + function(i) { + + vline( + x = event$index[i], + col = event$color[i] + ) + } + + ) + ), + annotations = do.call( + list, + lapply( + 1:nrow(event), + function(i) { + + annotations( + x = event$index[i], + text = event$event[i] + ) + } + + ) + ) + ) + + plot$main <- plot_ + # attributes(plot)$quote <- toDF(quote) + + return( + invisible(plot) + ) + +} + diff --git a/R/chart_indicators.R b/R/chart_indicators.R index ab8c92ae..bf65b78f 100644 --- a/R/chart_indicators.R +++ b/R/chart_indicators.R @@ -472,64 +472,4 @@ addRSI <- function( } - - -#' add vertical lines to -#' the chart -#' -#' @description -#' A short description... -#' -#' `r lifecycle::badge("experimental")` -#' -#' @param plot Chart -#' @param object an XTS object with dates -#' where the vertical line has to be drawn -#' @param color description -#' -#' @example man/examples/scr_addVlines.R -#' -#' @family chart indicators -#' @export -addVlines <- function(plot, object, color = 'steelblue') { - - # quote <- toDF( - # object - # ) - - # 1) extract the main - # chart from the plot - plot_ <- plot$main - - - - plot_ <- plotly::layout( - p = plot_, - shapes = do.call( - list, - lapply( - zoo::index(object), - function(x) { - - vline( - x, - color = color - ) - } - - ) - ) - ) - - plot$main <- plot_ - # attributes(plot)$quote <- toDF(quote) - - return( - invisible(plot) - ) - - - -} - # script end; diff --git a/R/helper.R b/R/helper.R index dbb4d3c7..6920706c 100644 --- a/R/helper.R +++ b/R/helper.R @@ -310,7 +310,7 @@ toQuote <- function(DF) { vline <- function( x = 0, - color = 'steelblue' + col = 'steelblue' ) { list( @@ -330,4 +330,31 @@ vline <- function( + +annotations <- function( + x = 0, + text = 'text' +) { + + list( + x = x, + y = 1, + text = text, + showarrow = FALSE, + #xref = 'paper', + yref = 'paper', + xanchor = 'right', + yanchor = 'auto', + xshift = 0, + textangle = -90, + yshift = 0, + font = list( + size = 15, + color = "black", + angle = '90' + ) + ) + + +} # script end; diff --git a/man/addBBands.Rd b/man/addBBands.Rd index 2b813201..2fa455f8 100644 --- a/man/addBBands.Rd +++ b/man/addBBands.Rd @@ -22,10 +22,10 @@ A short description... } \seealso{ Other chart indicators: +\code{\link{addEvents}()}, \code{\link{addMACD}()}, \code{\link{addMA}()}, \code{\link{addRSI}()}, -\code{\link{addVlines}()}, \code{\link{addVolume}()} } \concept{chart indicators} diff --git a/man/addEvents.Rd b/man/addEvents.Rd new file mode 100644 index 00000000..5d94d1a9 --- /dev/null +++ b/man/addEvents.Rd @@ -0,0 +1,106 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/chartEvent.R +\name{addEvents} +\alias{addEvents} +\title{add eventlines to +the chart} +\usage{ +addEvents(plot, event) +} +\arguments{ +\item{plot}{Chart} + +\item{event}{a data.frame with index, event and colors.} +} +\description{ +A short description... + +\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} +} +\examples{ +# script: scr_addEvents +# date: 2023-12-07 +# author: Serkan Korkmaz, serkor1@duck.com +# objective: Describe the usage +# of addEvents +# script start; + +# laod library +#library(cryptoQuotes) + +# 1) Generate random events +# of buys and sells and convert +# to data.frame +# +# Note: tibbles, data.tables are also supported +# but only base R is shown here to avoid +# too many dependencies +set.seed(1903) +event_data <- ATOMUSDT[ + sample(1:nrow(ATOMUSDT), size = 2) +] + +# 1.1) Extract the index +# from the event data +index <- zoo::index( + event_data +) + +# 1.2) Convert the coredata +# into a data.frame +event_data <- as.data.frame( + zoo::coredata(event_data) +) + +# 1.3) Add the index into the data.frame +# case insensitive +event_data$index <- index + +# 1.4) add events to the data. +# here we use Buys and Sells. +event_data$event <- rep( + x = c('Buy', 'Sell'), + lenght.out = nrow(event_data) +) + +# 1.5) add colors based +# on the event; here buy is colored +# darkgrey, and if the position is closed +# with profit the color is green +event_data$color <- ifelse( + event_data$event == 'Buy', + yes = 'darkgrey', + no = ifelse( + subset(event_data, event == 'Buy')$Close < subset(event_data, event == 'Sell')$Close, + yes = 'green', + no = 'red' + ) +) + +# 1.6) modify the event to add +# closing price at each event +event_data$event <- paste0( + event_data$event, ' @', event_data$Close +) + +# 2) Chart the the klines +# and add the buy and sell events +chart( + chart = kline( + ATOMUSDT + ) \%>\% addEvents( + event = event_data + ) +) + +# script end; +} +\seealso{ +Other chart indicators: +\code{\link{addBBands}()}, +\code{\link{addMACD}()}, +\code{\link{addMA}()}, +\code{\link{addRSI}()}, +\code{\link{addVolume}()} +} +\concept{chart indicators} diff --git a/man/addMA.Rd b/man/addMA.Rd index e7b6625f..0bfcc284 100644 --- a/man/addMA.Rd +++ b/man/addMA.Rd @@ -55,9 +55,9 @@ chart( \seealso{ Other chart indicators: \code{\link{addBBands}()}, +\code{\link{addEvents}()}, \code{\link{addMACD}()}, \code{\link{addRSI}()}, -\code{\link{addVlines}()}, \code{\link{addVolume}()} } \concept{chart indicators} diff --git a/man/addMACD.Rd b/man/addMACD.Rd index 2f36319d..0234f105 100644 --- a/man/addMACD.Rd +++ b/man/addMACD.Rd @@ -51,9 +51,9 @@ chart( \seealso{ Other chart indicators: \code{\link{addBBands}()}, +\code{\link{addEvents}()}, \code{\link{addMA}()}, \code{\link{addRSI}()}, -\code{\link{addVlines}()}, \code{\link{addVolume}()} } \concept{chart indicators} diff --git a/man/addRSI.Rd b/man/addRSI.Rd index 02dd246c..cc83eb37 100644 --- a/man/addRSI.Rd +++ b/man/addRSI.Rd @@ -52,9 +52,9 @@ chart( \seealso{ Other chart indicators: \code{\link{addBBands}()}, +\code{\link{addEvents}()}, \code{\link{addMACD}()}, \code{\link{addMA}()}, -\code{\link{addVlines}()}, \code{\link{addVolume}()} } \concept{chart indicators} diff --git a/man/addVlines.Rd b/man/addVlines.Rd deleted file mode 100644 index f6fb8d8d..00000000 --- a/man/addVlines.Rd +++ /dev/null @@ -1,63 +0,0 @@ -% Generated by roxygen2: do not edit by hand -% Please edit documentation in R/chart_indicators.R -\name{addVlines} -\alias{addVlines} -\title{add vertical lines to -the chart} -\usage{ -addVlines(plot, object, color = "steelblue") -} -\arguments{ -\item{plot}{Chart} - -\item{object}{an XTS object with dates -where the vertical line has to be drawn} - -\item{color}{description} -} -\description{ -A short description... - -\ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#experimental}{\figure{lifecycle-experimental.svg}{options: alt='[Experimental]'}}}{\strong{[Experimental]}} -} -\examples{ -# script: scr_addVlines -# date: 2023-10-25 -# author: Serkan Korkmaz, serkor1@duck.com -# objective: Describe the usage -# of addVlines -# script start; - -# laod library -library(cryptoQuotes) - -# 1) add random a random -# buy date to plot -ATOMUSDT$buy <- sample( - c(1, rep(0, nrow(ATOMUSDT) - 1)) -) - -# 2) subset and -# chart -chart( - chart = kline( - ATOMUSDT - ) \%>\% addVlines( - subset( - ATOMUSDT, - buy == 1 - ) - ) -) - -# script end; -} -\seealso{ -Other chart indicators: -\code{\link{addBBands}()}, -\code{\link{addMACD}()}, -\code{\link{addMA}()}, -\code{\link{addRSI}()}, -\code{\link{addVolume}()} -} -\concept{chart indicators} diff --git a/man/addVolume.Rd b/man/addVolume.Rd index 83375b48..3f6b550d 100644 --- a/man/addVolume.Rd +++ b/man/addVolume.Rd @@ -50,9 +50,9 @@ chart( \seealso{ Other chart indicators: \code{\link{addBBands}()}, +\code{\link{addEvents}()}, \code{\link{addMACD}()}, \code{\link{addMA}()}, -\code{\link{addRSI}()}, -\code{\link{addVlines}()} +\code{\link{addRSI}()} } \concept{chart indicators} diff --git a/man/examples/scr_addEvents.R b/man/examples/scr_addEvents.R new file mode 100644 index 00000000..b030bfeb --- /dev/null +++ b/man/examples/scr_addEvents.R @@ -0,0 +1,76 @@ +# script: scr_addEvents +# date: 2023-12-07 +# author: Serkan Korkmaz, serkor1@duck.com +# objective: Describe the usage +# of addEvents +# script start; + +# laod library +#library(cryptoQuotes) + +# 1) Generate random events +# of buys and sells and convert +# to data.frame +# +# Note: tibbles, data.tables are also supported +# but only base R is shown here to avoid +# too many dependencies +set.seed(1903) +event_data <- ATOMUSDT[ + sample(1:nrow(ATOMUSDT), size = 2) +] + +# 1.1) Extract the index +# from the event data +index <- zoo::index( + event_data +) + +# 1.2) Convert the coredata +# into a data.frame +event_data <- as.data.frame( + zoo::coredata(event_data) +) + +# 1.3) Add the index into the data.frame +# case insensitive +event_data$index <- index + +# 1.4) add events to the data. +# here we use Buys and Sells. +event_data$event <- rep( + x = c('Buy', 'Sell'), + lenght.out = nrow(event_data) +) + +# 1.5) add colors based +# on the event; here buy is colored +# darkgrey, and if the position is closed +# with profit the color is green +event_data$color <- ifelse( + event_data$event == 'Buy', + yes = 'darkgrey', + no = ifelse( + subset(event_data, event == 'Buy')$Close < subset(event_data, event == 'Sell')$Close, + yes = 'green', + no = 'red' + ) +) + +# 1.6) modify the event to add +# closing price at each event +event_data$event <- paste0( + event_data$event, ' @', event_data$Close +) + +# 2) Chart the the klines +# and add the buy and sell events +chart( + chart = kline( + ATOMUSDT + ) %>% addEvents( + event = event_data + ) +) + +# script end; diff --git a/man/examples/scr_addVlines.R b/man/examples/scr_addVlines.R deleted file mode 100644 index f7554999..00000000 --- a/man/examples/scr_addVlines.R +++ /dev/null @@ -1,30 +0,0 @@ -# script: scr_addVlines -# date: 2023-10-25 -# author: Serkan Korkmaz, serkor1@duck.com -# objective: Describe the usage -# of addVlines -# script start; - -# laod library -library(cryptoQuotes) - -# 1) add random a random -# buy date to plot -ATOMUSDT$buy <- sample( - c(1, rep(0, nrow(ATOMUSDT) - 1)) -) - -# 2) subset and -# chart -chart( - chart = kline( - ATOMUSDT - ) %>% addVlines( - subset( - ATOMUSDT, - buy == 1 - ) - ) -) - -# script end; diff --git a/vignettes/articles/04-chartingEvents.Rmd b/vignettes/articles/04-chartingEvents.Rmd new file mode 100644 index 00000000..deb7e0d2 --- /dev/null +++ b/vignettes/articles/04-chartingEvents.Rmd @@ -0,0 +1,92 @@ +--- +title: "Charting Important Events" +--- + +```{r, include = FALSE} +knitr::opts_chunk$set( + collapse = TRUE, + comment = "#>" +) +``` + +```{r setup} +library(cryptoQuotes) +``` + + +Various events in the financial markets does, undoubtedly, have an impact on the prices. For traders relying on technical analysis one important event is when the short simple moving average (SMA), crosses the long SMA. + +```{r Locate bullcross} +## Calculate moving averages +## SMA(7) and SMA(10) +ATOMUSDT$short_SMA <- TTR::SMA( + x = ATOMUSDT$Close, + n = 7, +) + +ATOMUSDT$long_SMA <- TTR::SMA( + x = ATOMUSDT$Close, + n = 21, +) + +## Determine the cross +## from below +ATOMUSDT$cross <- as.numeric( + lag(ATOMUSDT$short_SMA) < ATOMUSDT$long_SMA & + ATOMUSDT$short_SMA > ATOMUSDT$long_SMA +) +``` + + +Based on the `cross` indicator, the `ATOMUSDT` pair can now be subset, and processed accordingly. + +> **NOTE:** The library supports all kinds of data.frames, including +> data.table and tibbles. + +```{r} +## create event data +## and store it as a data.rfrae +event_data <- subset( + ATOMUSDT, + cross == 1 +) + + +# 1.1) Extract the index +# from the event data +index <- zoo::index( + event_data +) + +# 1.2) Convert the coredata +# into a data.frame +event_data <- as.data.frame( + zoo::coredata(event_data) +) + +# 1.3) Add the index into the data.frame +# case insensitive +event_data$index <- index + + +# 1.4) add events to the data. +# here we use Buys and Sells. +event_data$event <- 'Bull Cross' +event_data$color <- 'darkgray' + +``` + + +Finally, the crosses can be plotted using the `chart` and `addEvents` functions, like below, + +```{r, out.width="100%",fig.align='center',fig.height=10} +chart( + chart = kline(quote = ATOMUSDT) %>% + addBBands() %>% + addMA(FUN = TTR::SMA, n = 7) %>% + addMA(FUN = TTR::SMA, n = 21) %>% + addEvents(event = event_data) +) +``` + +